summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2016-01-14 22:14:05 +0100
committerRoland Stigge <stigge@antcom.de>2016-01-14 22:14:05 +0100
commit48a59706c0085f40b3cb80c96bc7d5bf85307d34 (patch)
tree8b868502c759f4c9801ddbcf675c57ae1d3a7911
Import xcircuit_3.8.78.dfsg.orig.tar.bz2
[dgit import orig xcircuit_3.8.78.dfsg.orig.tar.bz2]
-rw-r--r--.gitignore19
-rw-r--r--CHANGES2786
-rw-r--r--COPYRIGHT293
-rw-r--r--Makefile.am286
-rw-r--r--Makefile.in898
-rw-r--r--Makefile.mingw64463
-rw-r--r--Makefile.win32425
-rw-r--r--README316
-rw-r--r--README.ISOLatin2108
-rw-r--r--README.Tcl732
-rw-r--r--README.ngspice54
-rw-r--r--README.notes345
-rw-r--r--TODO66
-rw-r--r--VERSION1
-rw-r--r--Xw/BBoard.c353
-rw-r--r--Xw/BBoard.h52
-rw-r--r--Xw/BBoardP.h71
-rw-r--r--Xw/Button.c786
-rw-r--r--Xw/Cascade.c1374
-rw-r--r--Xw/Cascade.h41
-rw-r--r--Xw/CascadeP.h85
-rw-r--r--Xw/Display.c672
-rw-r--r--Xw/DisplayP.h94
-rw-r--r--Xw/Form.c1902
-rw-r--r--Xw/Form.h34
-rw-r--r--Xw/FormP.h140
-rw-r--r--Xw/Imakefile99
-rw-r--r--Xw/Makefile.am18
-rw-r--r--Xw/Makefile.in617
-rw-r--r--Xw/Manager.c894
-rw-r--r--Xw/MapEvents.c948
-rw-r--r--Xw/MenuBtn.c2570
-rw-r--r--Xw/MenuBtn.h55
-rw-r--r--Xw/MenuBtnP.h148
-rw-r--r--Xw/MenuMgr.c652
-rw-r--r--Xw/MenuPane.c855
-rw-r--r--Xw/PButton.c640
-rw-r--r--Xw/PButton.h44
-rw-r--r--Xw/PButtonP.h79
-rw-r--r--Xw/PopupMgr.c4796
-rw-r--r--Xw/PopupMgr.h45
-rw-r--r--Xw/PopupMgrP.h99
-rw-r--r--Xw/Primitive.c1146
-rw-r--r--Xw/ResConvert.c797
-rw-r--r--Xw/SText.c1474
-rw-r--r--Xw/SText.h39
-rw-r--r--Xw/STextP.h89
-rw-r--r--Xw/SourceP.h57
-rw-r--r--Xw/SourceStr.c374
-rw-r--r--Xw/TextEdit.c2503
-rw-r--r--Xw/TextEdit.h263
-rw-r--r--Xw/TextEditP.h172
-rw-r--r--Xw/Toggle.c858
-rw-r--r--Xw/Toggle.h44
-rw-r--r--Xw/ToggleP.h82
-rw-r--r--Xw/Traversal.c1187
-rw-r--r--Xw/WorkSpace.c325
-rw-r--r--Xw/WorkSpace.h34
-rw-r--r--Xw/WorkSpaceP.h67
-rw-r--r--Xw/Xw.h470
-rw-r--r--Xw/XwP.h605
-rw-r--r--Xw/sub.c969
-rw-r--r--aclocal.m4951
-rw-r--r--colordefs.h42
-rwxr-xr-xconfig.guess1501
-rwxr-xr-xconfig.sub1410
-rwxr-xr-xconfigure8887
-rw-r--r--configure.in1359
-rw-r--r--cursors.h141
-rw-r--r--elements.c2315
-rw-r--r--events.c6827
-rw-r--r--examples/.xcircuitrc23
-rw-r--r--examples/.xcircuitrc.py23
-rw-r--r--examples/FlareLED.ps720
-rw-r--r--examples/USAflag.ps221
-rw-r--r--examples/analog1.ps241
-rw-r--r--examples/analog2.ps224
-rw-r--r--examples/analoglib1.lps238
-rw-r--r--examples/border.ps231
-rw-r--r--examples/buses.ps365
-rw-r--r--examples/diffamp_test.ps518
-rw-r--r--examples/diffamp_test2.ps533
-rw-r--r--examples/diffamp_test3.ps535
-rw-r--r--examples/envelope.ps343
-rw-r--r--examples/fourttest.ps292
-rw-r--r--examples/logic.sim11
-rw-r--r--examples/logic8.ps387
-rw-r--r--examples/panzoom.py19
-rw-r--r--examples/prelude.ps936
-rw-r--r--examples/systemd1.lgf2544
-rw-r--r--examples/test.py48
-rw-r--r--examples/threestage.ps352
-rw-r--r--examples/vcoblock.ps332
-rwxr-xr-xexamples/xc_remote.sh24
-rw-r--r--examples/xcclock.ps181
-rw-r--r--filelist.c893
-rw-r--r--files.c6907
-rw-r--r--flate.c147
-rw-r--r--fontfile.c384
-rw-r--r--formats.c676
-rw-r--r--functions.c2888
-rw-r--r--graphic.c580
-rw-r--r--help.c514
-rwxr-xr-xinstall-sh251
-rw-r--r--keybindings.c864
-rw-r--r--lib/XCircuit.ad35
-rw-r--r--lib/analog.lps312
-rw-r--r--lib/analoglib2.lps372
-rw-r--r--lib/analoglib3.lps457
-rw-r--r--lib/asg_spice.lps311
-rw-r--r--lib/avlsi.lps41
-rw-r--r--lib/digital.lps190
-rw-r--r--lib/digitallib.lps352
-rw-r--r--lib/digitaltcl.lps43
-rw-r--r--lib/fonts/courier.lps1825
-rw-r--r--lib/fonts/courier.xfe48
-rw-r--r--lib/fonts/courieriso.xfe47
-rw-r--r--lib/fonts/courieriso2.lps414
-rw-r--r--lib/fonts/courieriso2.xfe49
-rw-r--r--lib/fonts/courieriso5.lps56
-rw-r--r--lib/fonts/courieriso5.xfe47
-rw-r--r--lib/fonts/fonttest.ps22
-rw-r--r--lib/fonts/helvetica.lps1711
-rw-r--r--lib/fonts/helvetica.xfe48
-rw-r--r--lib/fonts/helveticaiso.xfe47
-rw-r--r--lib/fonts/helveticaiso2.lps414
-rw-r--r--lib/fonts/helveticaiso2.xfe48
-rw-r--r--lib/fonts/helveticaiso5.lps55
-rw-r--r--lib/fonts/helveticaiso5.xfe48
-rw-r--r--lib/fonts/letters.ps790
-rw-r--r--lib/fonts/myfont.lps614
-rw-r--r--lib/fonts/myfont.xfe54
-rw-r--r--lib/fonts/symbol.lps1506
-rw-r--r--lib/fonts/symbol.xfe50
-rw-r--r--lib/fonts/times_roman.lps1833
-rw-r--r--lib/fonts/times_roman.xfe49
-rw-r--r--lib/fonts/times_romaniso.xfe47
-rw-r--r--lib/fonts/times_romaniso2.lps414
-rw-r--r--lib/fonts/times_romaniso2.xfe47
-rw-r--r--lib/fonts/times_romaniso5.lps56
-rw-r--r--lib/fonts/times_romaniso5.xfe48
-rw-r--r--lib/generic.lps93
-rw-r--r--lib/ic_templates.lps435
-rw-r--r--lib/lgf.lps874
-rw-r--r--lib/musiclib.lps701
-rw-r--r--lib/pcb.lps1249
-rw-r--r--lib/pcb_layout.lps1249
-rw-r--r--lib/pixmaps/a.gifbin0 -> 897 bytes
-rw-r--r--lib/pixmaps/a.xpm30
-rw-r--r--lib/pixmaps/b.gifbin0 -> 118 bytes
-rw-r--r--lib/pixmaps/b.xpm28
-rw-r--r--lib/pixmaps/bd.gifbin0 -> 106 bytes
-rw-r--r--lib/pixmaps/bd.xpm26
-rw-r--r--lib/pixmaps/ccw.gifbin0 -> 127 bytes
-rw-r--r--lib/pixmaps/ccw.xpm28
-rw-r--r--lib/pixmaps/co.gifbin0 -> 130 bytes
-rw-r--r--lib/pixmaps/co.xpm28
-rw-r--r--lib/pixmaps/cp.gifbin0 -> 150 bytes
-rw-r--r--lib/pixmaps/cp.xpm30
-rw-r--r--lib/pixmaps/cw.gifbin0 -> 130 bytes
-rw-r--r--lib/pixmaps/cw.xpm28
-rw-r--r--lib/pixmaps/d2.gifbin0 -> 140 bytes
-rw-r--r--lib/pixmaps/d2.xpm28
-rw-r--r--lib/pixmaps/e.gifbin0 -> 125 bytes
-rw-r--r--lib/pixmaps/e.xpm28
-rw-r--r--lib/pixmaps/fi.gifbin0 -> 126 bytes
-rw-r--r--lib/pixmaps/fi.xpm26
-rw-r--r--lib/pixmaps/fx.gifbin0 -> 156 bytes
-rw-r--r--lib/pixmaps/fx.xpm31
-rw-r--r--lib/pixmaps/fy.gifbin0 -> 165 bytes
-rw-r--r--lib/pixmaps/fy.xpm31
-rw-r--r--lib/pixmaps/i.gifbin0 -> 117 bytes
-rw-r--r--lib/pixmaps/i.xpm29
-rw-r--r--lib/pixmaps/li.gifbin0 -> 184 bytes
-rw-r--r--lib/pixmaps/li.xpm31
-rw-r--r--lib/pixmaps/mk.gifbin0 -> 197 bytes
-rw-r--r--lib/pixmaps/mk.xpm33
-rw-r--r--lib/pixmaps/mv.gifbin0 -> 168 bytes
-rw-r--r--lib/pixmaps/mv.xpm31
-rw-r--r--lib/pixmaps/pa.gifbin0 -> 160 bytes
-rw-r--r--lib/pixmaps/pa.xpm29
-rw-r--r--lib/pixmaps/pl.gifbin0 -> 183 bytes
-rw-r--r--lib/pixmaps/pl.xpm30
-rw-r--r--lib/pixmaps/pm.gifbin0 -> 203 bytes
-rw-r--r--lib/pixmaps/pm.xpm32
-rw-r--r--lib/pixmaps/pn.gifbin0 -> 107 bytes
-rw-r--r--lib/pixmaps/pn.xpm26
-rw-r--r--lib/pixmaps/po2.gifbin0 -> 98 bytes
-rw-r--r--lib/pixmaps/po2.xpm27
-rw-r--r--lib/pixmaps/pu2.gifbin0 -> 99 bytes
-rw-r--r--lib/pixmaps/pu2.xpm27
-rw-r--r--lib/pixmaps/pz.gifbin0 -> 173 bytes
-rw-r--r--lib/pixmaps/pz.xpm30
-rw-r--r--lib/pixmaps/q.gifbin0 -> 105 bytes
-rw-r--r--lib/pixmaps/q.xpm28
-rw-r--r--lib/pixmaps/r.gifbin0 -> 149 bytes
-rw-r--r--lib/pixmaps/s.gifbin0 -> 135 bytes
-rw-r--r--lib/pixmaps/s.xpm29
-rw-r--r--lib/pixmaps/solid.xbm26
-rw-r--r--lib/pixmaps/stip12.xbm25
-rw-r--r--lib/pixmaps/stip25.xbm25
-rw-r--r--lib/pixmaps/stip38.xbm25
-rw-r--r--lib/pixmaps/stip50.xbm25
-rw-r--r--lib/pixmaps/stip62.xbm25
-rw-r--r--lib/pixmaps/stip75.xbm25
-rw-r--r--lib/pixmaps/stip88.xbm25
-rw-r--r--lib/pixmaps/t.gifbin0 -> 151 bytes
-rw-r--r--lib/pixmaps/t.xpm29
-rw-r--r--lib/pixmaps/tg.gifbin0 -> 148 bytes
-rw-r--r--lib/pixmaps/tg.xpm28
-rw-r--r--lib/pixmaps/ti.gifbin0 -> 150 bytes
-rw-r--r--lib/pixmaps/ti.xpm29
-rw-r--r--lib/pixmaps/tp.gifbin0 -> 148 bytes
-rw-r--r--lib/pixmaps/tp.xpm28
-rw-r--r--lib/pixmaps/uj.gifbin0 -> 159 bytes
-rw-r--r--lib/pixmaps/uj.xpm29
-rw-r--r--lib/pixmaps/w.gifbin0 -> 118 bytes
-rw-r--r--lib/pixmaps/w.xpm28
-rw-r--r--lib/pixmaps/xcircuit.gifbin0 -> 1017 bytes
-rw-r--r--lib/pixmaps/xcircuit.icobin0 -> 9062 bytes
-rw-r--r--lib/pixmaps/xcircuit.xpm95
-rw-r--r--lib/pixmaps/yp.gifbin0 -> 170 bytes
-rw-r--r--lib/pixmaps/yp.xpm30
-rw-r--r--lib/pixmaps/z4.gifbin0 -> 147 bytes
-rw-r--r--lib/pixmaps/z4.xpm30
-rw-r--r--lib/pixmaps/z5.gifbin0 -> 145 bytes
-rw-r--r--lib/pixmaps/z5.xpm29
-rw-r--r--lib/python/flatspice.py127
-rw-r--r--lib/python/gettext.py46
-rw-r--r--lib/python/loadlgf.py60
-rw-r--r--lib/python/pagebbox.py68
-rw-r--r--lib/python/spice.py282
-rw-r--r--lib/python/xcstartup.py40
-rw-r--r--lib/quadparts.lps89
-rw-r--r--lib/series74xx.lps8663
-rw-r--r--lib/signal.lps67
-rw-r--r--lib/standard_cells.cir108
-rw-r--r--lib/standard_cells_3V.cir109
-rw-r--r--lib/startup.script39
-rw-r--r--lib/tcl/boot_xcircuit.tcl42
-rw-r--r--lib/tcl/bparams.tcl17
-rw-r--r--lib/tcl/console.tcl20
-rw-r--r--lib/tcl/edif.tcl931
-rw-r--r--lib/tcl/files.tcl203
-rw-r--r--lib/tcl/library.tcl297
-rw-r--r--lib/tcl/matgen.tcl513
-rw-r--r--lib/tcl/mousehint.tcl104
-rw-r--r--lib/tcl/ngspice.tcl27
-rw-r--r--lib/tcl/panzoom.tcl6
-rw-r--r--lib/tcl/pcbout.tcl326
-rw-r--r--lib/tcl/pkgIndex.tcl3
-rw-r--r--lib/tcl/resource.tcl78
-rw-r--r--lib/tcl/selection.tcl6
-rw-r--r--lib/tcl/sinusoid.tcl11
-rw-r--r--lib/tcl/sue_xc.tcl383
-rw-r--r--lib/tcl/symbol.tcl672
-rw-r--r--lib/tcl/text.tcl267
-rwxr-xr-xlib/tcl/tkcon.tcl5328
-rw-r--r--lib/tcl/wrapper.tcl3286
-rw-r--r--lib/tcl/xchelp.tcl450
-rw-r--r--lib/tcl/xcircuit.bat.in34
-rwxr-xr-xlib/tcl/xcircuit.sh.in58
-rwxr-xr-xlib/tcl/xcircuit.tcl.in261
-rw-r--r--lib/tcl/xcstartup.tcl65
-rw-r--r--lib/xcircps2.pro166
-rw-r--r--lib/xcircuit.1.in1332
-rw-r--r--libraries.c1814
-rw-r--r--log_text.html0
-rw-r--r--menucalls.c1696
-rw-r--r--menudep.c164
-rw-r--r--menus.h434
-rwxr-xr-xmissing283
-rwxr-xr-xmkinstalldirs40
-rw-r--r--netlist.c6615
-rw-r--r--ngspice.c659
-rw-r--r--opengl.c445
-rw-r--r--parameter.c2626
-rw-r--r--pp.c129
-rw-r--r--prototypes.h1019
-rw-r--r--python.c2120
-rw-r--r--rcfile.c521
-rw-r--r--render.c779
-rw-r--r--resource.h55
-rw-r--r--resources.rc82
-rw-r--r--schema.c1152
-rw-r--r--selection.c1761
-rw-r--r--spiceparser/Makefile.am20
-rw-r--r--spiceparser/Makefile.in619
-rw-r--r--spiceparser/Makefile_orig38
-rw-r--r--spiceparser/README.c207
-rw-r--r--spiceparser/bitlist.c183
-rw-r--r--spiceparser/bitlist.h53
-rw-r--r--spiceparser/debug.h51
-rw-r--r--spiceparser/eqn.c906
-rw-r--r--spiceparser/eqn.h232
-rw-r--r--spiceparser/eqnlist.c291
-rw-r--r--spiceparser/equations.c742
-rw-r--r--spiceparser/equations.h176
-rw-r--r--spiceparser/eval.h65
-rw-r--r--spiceparser/hash.c267
-rw-r--r--spiceparser/hash.h110
-rw-r--r--spiceparser/list.c361
-rw-r--r--spiceparser/list.h138
-rw-r--r--spiceparser/list_search.c182
-rw-r--r--spiceparser/list_search.h83
-rw-r--r--spiceparser/memory.c224
-rw-r--r--spiceparser/memory.h63
-rw-r--r--spiceparser/mergedup.c153
-rw-r--r--spiceparser/mergedup.h53
-rw-r--r--spiceparser/names.c287
-rw-r--r--spiceparser/names.h62
-rw-r--r--spiceparser/netlist.c686
-rw-r--r--spiceparser/netlist.h282
-rw-r--r--spiceparser/netlist_dev.c198
-rw-r--r--spiceparser/netlist_dev.h202
-rw-r--r--spiceparser/netlist_extract.c550
-rw-r--r--spiceparser/netlist_extract.h45
-rw-r--r--spiceparser/netlist_funcs.c169
-rw-r--r--spiceparser/netlist_lib.c1480
-rw-r--r--spiceparser/netlist_lib.h275
-rw-r--r--spiceparser/netlist_spice.c1455
-rw-r--r--spiceparser/netlist_spice.h288
-rw-r--r--spiceparser/netlist_template.c55
-rw-r--r--spiceparser/scanner.c780
-rw-r--r--spiceparser/scanner.h163
-rw-r--r--spiceparser/sort.c482
-rw-r--r--spiceparser/test.lib1760
-rw-r--r--spiceparser/xcircspice.c153
-rw-r--r--svg.c1132
-rw-r--r--symbol.map4
-rw-r--r--tclxcircuit.c10154
-rw-r--r--text.c2286
-rw-r--r--tkSimple.c524
-rw-r--r--tkwin32.h39
-rw-r--r--tool_bar.h39
-rw-r--r--undo.c1744
-rw-r--r--w32x11.c421
-rw-r--r--wishexe.ini19
-rw-r--r--xcircexec.c80
-rw-r--r--xcircuit-tcl.nsi900
-rw-r--r--xcircuit-win32.c117
-rw-r--r--xcircuit.c1488
-rw-r--r--xcircuit.h1564
-rw-r--r--xcircuit.spec.in43
-rw-r--r--xcwin32-colors.h755
-rw-r--r--xcwin32.c3366
-rw-r--r--xcwin32.h587
-rw-r--r--xcwrap.c239
-rw-r--r--xtfuncs.c1822
-rw-r--r--xtgui.c2086
350 files changed, 192745 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f3ce576
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+xcircuit
+config.cache
+config.status
+config.log
+menudep
+spiceparser/Makefile
+asg/Makefile
+Xw/Makefile
+Makefile
+xcircexec
+menudep.h
+lib/xcircuit.1
+lib/tcl/xcircuit.sh
+lib/tcl/xcircuit.tcl
+*.o
+*.so
+*~
+UPDATE_ME
+VERSION
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..52d1cc9
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,2786 @@
+Xcircuit v3.x Change Log (file CHANGES)
+----------------------------------------------------------------------
+
+Please note that there is an automatically-generated, up-to-date list
+of the most recent code changes at the URL
+
+ http://opencircuitdesign.com/xcircuit/changes.html
+
+Occasionally I spend some time to convert that list into text and put it
+back here. So if you're looking for the most recent changes, try the
+website.
+
+Version 3.6 (January 2006 to present)
+----------------------------------------------------------------------
+369 v3.6 rev 21 4/7/06
+ Incorporated Michael Goffioul's code for (native) Windows
+ compilation.
+
+368 v3.6 rev 20 4/5/06
+ Fixed an error with the -noconsole -nowindow startup, where
+ the option switches were passed to GUI_init; XCircuit now
+ searches the arguments for a Tk window name rather than relying
+ on the number of arguments to figure out whether or not it is
+ running in batch mode.
+ Also: Fixed an error in a Wprintf() statement when a library
+ file cannot be found.
+
+368 v3.6 rev 19 3/31/06
+ Fixed the select color, which got changed to cyan because the
+ wrong line was deleted from the source file. Also, implemented
+ a policy of removing redundant points after a line has been
+ drawn, because some drawing programs use left-button + middle-
+ button, and I've seen several xcircuit novices doing this.
+ Also: Fixed the undo mechanism with respect to rotates and
+ flips, so that rotates and flips during a move or copy operation
+ don't screw up the undo operation.
+ Also: Changed the look of the GUI a bit, with softer colors and
+ no red borders around the buttons and message widgets.
+
+367 v3.6 rev 18 3/30/06
+ Added command option "config database" to update the internal
+ list of colors, fonts, and other values that should be able
+ to be set with the Tk "option" command. This now allows colors
+ to be redefined from within the startup script. Removed the
+ "query" color, which is no longer used, and the "filter2" and
+ "bar2" colors, which are (and never were) necessary.
+
+366 v3.6 rev 17 3/28/06
+ Reorganized the source code to separate most of the Xt GUI
+ functions into two separate files, xtgui.c and xtfuncs.c.
+
+365 v3.6 rev 16 3/27/06
+ Changed the "keybind" function to be per-window so that the
+ scroll-wheel and auto-increment functions work in multiple
+ xcircuit windows.
+ Also: Corrected a bad error that allowed an object instance
+ being moved to be selected when "carrying" it into another
+ object, causing xcircuit to crash.
+ Also: Changed the behavior of Tcl expression parameters so that
+ the parameter evaluation is done ONLY as part of the opsubstitute()
+ routine; this places some restrictions on the use of expression
+ parameters but should avoid problems where expression parameters
+ make XCircuit crash.
+ Also: Created a new symbol "netpointer" in the generic library
+ that implements a "netlist get" function. Corrected a number of
+ errors related to properly executing expression parameters.
+ Also: Added "analoglib3.lps" and "digitallib.lps" to the installed
+ libraries.
+ Also: Corrected the library zoom/position problem definitively
+ (see note for revision 13).
+
+364 v3.6 rev 15 3/22/06
+ Added command options "library writable" and "library changed".
+ Removed the "Library: " string from the beginning of library
+ names. Modified the "Write All" Tcl script to handle automatic
+ writeback of libraries that have changed, and to note libraries
+ that have changed but which are not writable.
+
+364 v3.6 rev 14 3/21/06
+ Added the "-target <library>" option to the "page load" command.
+ This allows objects in a file to be placed somewhere other than
+ the "User Library", without having to move them by hand. Let
+ XCOps(library) stand for *both* the -replace and -target libraries.
+ Fixed the Tcl wrapper script procedures accordingly.
+ Also: Added command-line options "xcircuit --help" and
+ "xcircuit --version" providing essential information.
+ Also: Added command option "library compose", although the fact
+ that the library does not get composed in certain cases needs to
+ be investigated.
+ Also: Added variable xobjs.hold = XCOps(hold); when FALSE, the
+ mouse HOLD modifier is disabled (perhaps this should be an
+ integer that sets the delay time, with 0 = disabled?).
+ Also: Fixed menu command callbacks that were broken for several
+ revisions.
+
+363 v3.6 rev 13 3/18/06
+ Various fixes to correct problems found running various steps
+ while writing tutorial number 3: Fixed Alt-f key binding for
+ font changes, user library redraw (still is wrong somewhere),
+ variable substitution in filenames, and a few others.
+
+362 v3.6 rev 12 3/17/06
+ Added the ability to move objects both within a library and between
+ libraries simply by using the "library move" macro (Shift-M) to
+ pick up the object, then transferring it between library pages.
+ Also, virtual copies can be made of any object in the library (not
+ just those that have paramters), and the virtual copies can be
+ flipped and rotated.
+ Also: Fixed the "-noconsole -nowindow" invocation, which was
+ broken.
+ Also: Added variable and tilde expansion to filenames in the
+ "%F" and "%f" escapes in info labels.
+
+361 v3.6 rev 11 3/15/06
+ Corrected a number of event errors, including the inability to
+ select from the library via a button tap and drop into "move"
+ mode.
+ Also: Implemented a version of James Vernon's mouse button hints.
+ Also: Corrected the LaTeX mode output to properly account for files
+ with non-".ps" extensions (e.g., ".eps").
+
+360 v3.6 rev 10 3/14/06
+ Corrected an error which prevented edited library object names
+ from being applied to the object name. This resulted in confusion,
+ because the library would show the modified name, while the
+ object itself retained its original name.
+ Also: Added multiple window handling to the undo/redo mechanism.
+ Also: Added a window close procedure and a command "config delete"
+ to correspond to it.
+
+359 v3.6 rev 9 3/13/06
+ A number of fixes to the key binding and function dispatch
+ routines from rev 8: Fixed Finish_Copy mode, fixed handling
+ of ASCII keystrokes in text entry modes, fixed retention of
+ view scale and position after displaying a library page.
+ Fixed error in prohibiting justification action in "normal"
+ mode.
+ Also: A number of fixes to the wrapper window menus for
+ multiple pages: Changed library and page menus to be shared,
+ applied new color, font, and encoding functions to all windows,
+ and fixed the Tk color picker call for the "add new color" menu
+ option.
+
+359 v3.6 rev 8 3/12/06
+ Major overhaul of the key binding and function dispatching
+ mechanisms to accomodate multiple windows.
+ Still to be done: Some menu items (lists of Libraries and
+ Pages, for example) need to be shared among all windows.
+ Need a window close routine. Need a routine to transfer a
+ selection between two windows. Need to handle multiple
+ windows in undo/redo.
+ Also: Fixed a warning message on number of parts that should
+ apply only to library objects, not pages.
+
+358 v3.6 rev 7 2/24/06
+ Changed the meaning of CAD_HOME to point to "libdir", such
+ that distributions can set it to something like /usr/share
+ without causing trouble. Changed CAD_HOME to CAD_ROOT so as
+ to prevent it from breaking backward-compatibility.
+
+357 v3.6 rev 6 2/23/06
+ Fixed a spurious "Error: end of file" message.
+ Corrected the configure.in once again because Tcl/Tk defines
+ TCL_INCLUDE_SPEC but *not*, stupidly enough, TK_INCLUDE_SPEC.
+
+356 v3.6 rev 5 2/21/06
+ Added the Shift-Button-1 bindings to duplicate Button-2
+ functions as an alternative to using "xcircuit -2".
+ Also: Added a flag bit to the line styles representing
+ square end caps.
+
+355 v3.6 rev 4 2/13/06
+ Fixed an error with the LaTeX mode ".tex" output to correctly
+ handle the filename when the extension of the xcircuit file
+ is not the default ".ps". Also, changed the configure script
+ to add some other standard locations to the directory search
+ for tclConfig.sh and tkConfig.sh, and made use of the
+ TCL_INCLUDE_SPEC and TK_INCLUDE_SPEC from those files to set
+ the INC_SPECS definition. Thanks to John Rigg for pointing
+ out these problems with the Debian compile.
+ Also: Fixed a bug that can potentially cause XCircuit to
+ crash when a box is drawn.
+
+354 v3.6 rev 3 2/3/06
+ Added a number of "undo" functions for minor things that had
+ been left unimplemented, including linewidth changes, scale
+ changes, style changes, and text justification and option
+ settings (flip invariance, latex mode, etc.). Thanks to Joel
+ Kuusk for pointing out the omissions.
+
+353 v3.6 rev 2 1/22/06
+ Updated a number of changes from around version 3.5.3 that
+ broke the non-Tcl-based version of xcircuit (not exhaustively
+ tested).
+
+352 v3.6 rev 1 1/20/06
+ Finally got around to correcting the crash backup behavior
+ so that xcircuit ignores crash backup files belonging to an
+ active process (i.e., another xcircuit currently running).
+
+351 v3.6 rev 0 1/7/06
+ Restructured variables internally to acommodate multiple
+ layout pages. This is only a start, as currently new
+ windows have no callbacks created.
+ Also: Created an enhanced version of the "Make Matching
+ Symbol" routine, and created a new routine and menu selection
+ "SPICE to Symbol", which creates a symbol for, and link to,
+ a SPICE file containing a subcircuit definition.
+ Also: Longtime error: Corrected the quick screen intersection
+ check to include the schematic bounding box. Otherwise, when
+ only pin and info labels intersect the window, nothing is drawn.
+
+Version 3.5 (November 2005 to January 2006)
+----------------------------------------------------------------------
+350 v3.5 rev 5 12/19/05
+ Added command option "object <handle> library [<library>]"
+ where the final optional argument was previously unavailable.
+ If present, the final argument declares a new library for the
+ object. If not present, the number of the library containing
+ the object is returned.
+ Also: Corrected lib/tcl/symbol.tcl where the "%n" was missing
+ from the end of the subcircuit call statement.
+
+349 v3.5 rev 4 12/14/05
+ Fixed an error in netlisting which causes the netlister to
+ write "X.." lines in the SPICE output of "trivial" symbols
+ like the "dot" object.
+
+348 v3.5 rev 3 12/13/05
+ Fixed another fatal error in file writing due to having a
+ NULL filename.
+ Also: Revised the Wprintf() calls to accept variable
+ argument lists, rewrote the Tcl versions of W*printf() as
+ calls to a script rather than being hard-coded as a specific
+ Tk function. This allows me to rewrite the script equivalent
+ of Wprintf() to print to both the message widget and the
+ console output, so the console now gets a complete record of
+ warning, error, and informational messages produced by
+ xcircuit.
+ Also: Fixed two fatal errors with "Load Dependencies", one
+ which crashed xcircuit due to a typo in the Tcl code for
+ command "page links load", and the other which created an
+ infinite loop if loadfile() failed to load a file inside
+ the recursive call to "page links load".
+
+347 v3.5 rev 2 12/8/05
+ Corrected a behavioral error in which xcircuit does not
+ generate netlist output for a symbol containing an info
+ label but no pins. Thanks to Herman Lee for pointing out
+ this problem.
+ Also: Corrected a problem in 3.5.1 in which xcircuit
+ changes filenames in a multi-schematic session to match
+ the top-level schematic. It ignored the setting of
+ "dmultiple", and thus would make changes without warning
+ when it generated the crash backup file, for example.
+ Also: Added a widget for managing multi-schematic file
+ writes, with a menu hook from "Files->Write All...".
+ Also: Changed the behavior of "page changes" to include
+ change counts of all descendents. Fixed the Tcl parsing
+ of the "page" command for certain options when a page is
+ specified in the command (e.g., "page 1 fit"). Modified
+ the "page changes" command so that the change count can
+ be altered, thus forcing a page to be recognized as either
+ modified or unmodified.
+
+346 v3.5 rev 1 11/21/05
+ Separated the source code into distribution (version 3.4) and
+ development (version 3.5) branches, on the suggestion of
+ Zvezdan Petkovic.
+ Also: Added command option "page changes" which reports the
+ number of changes on a page. Modified some behavior so that
+ starting certain commands like "copy" does not increment the
+ number of changes, so that the command can be canceled without
+ xcircuit thinking that the page has been modified.
+ Also: Added command option "config search file|library <list>"
+ with a colon-separated list <list>, specifying the search order
+ on a specific set of directories. These lists are initially
+ null, and behavior remains the same as before while these lists
+ are null. A non-null search path overrides the default search
+ on the current working directory, and a non-null library search
+ path overrides the search on XCIRCUIT_LIB_DIR and the default
+ install directory path. Modified the library manager to use
+ search paths.
+ Also: Allow "library load <filename>" on a regular xcircuit
+ (.ps) file, which has the behavior of loading the objects from
+ the file without loading the pages themselves.
+ Also: Added command option "netlist get -hier" to generate
+ a slash-separated hierarchy using device names and indices.
+ Also: Fixed "netlist goto <name>" to accept the same syntax
+ that is produced by "netlist get -hier", and finished the coding
+ of the routine.
+ Also: Added command options "netlist select <netname>" and
+ "netlist position <netname>".
+ Also: Changed behavior of the "%" macro so that it also raises
+ the console to the top of the window.
+ Also: Added command option "netlist parse <mode>" (e.g.,
+ "netlist parse spice") that allows some selective parsing from
+ a Tcl script.
+ Also: Created a script called "symbol.tcl" that replaces the
+ function of the "Make Matching Symbol" button in the xcircuit
+ menu, with a considerably fancier interface.
+ Also: Modified the command "color set" to accept color names.
+
+346 v3.5 rev 0 11/21/05
+ This revision was not posted, but reflects changes made through
+ version 3.4 revision 10 that were removed from the "stable"
+ branch of the distribution.
+ 1. Changed the crash backup file name to include the process ID.
+ This is intended to prevent xcircuit process from treating a backup
+ file from another existing xcircuit process as a crash file to be
+ recovered, but the code is not yet finished.
+ 2. Enabled creation of parameters on a top-level page, and revised
+ the Tcl "param set" command to handle this case.
+ 3. Added a "page links sheet" option to allow querying "sheet A of B".
+ 4. Added a "page links load" option to allow symbols to specify which
+ file contains the schematic, and load these prior to writing a netlist.
+
+Version 3.4 (August 2005 to November 2005)
+----------------------------------------------------------------------
+345 v3.4 rev 10 11/16/05
+ Removed the problem with automatic generation of pin labels on a
+ symbol during a copy action in the schematic.
+ Also: Added doubly-protected backups to standard file writes.
+ This renames the existing file to filename + tilde ("~") so
+ that the file is not truncated if a crash happens during a
+ normal file write.
+ Also: Added patch files by Zvezdan Petkovic for proper
+ compilation on OpenBSD.
+
+344 v3.4 rev 9 11/14/05
+ Applied (partially) a patch from Larry Doolittle that fixes a
+ pointer bug in the non-Tcl version, and allows compilation of
+ the non-Tcl version on a 64-bit system.
+ Also: Fixed the event mechanism to allow pages to be selected
+ in the page directory (otherwise, pages cannot be swapped).
+ Also: Fixed the Tcl "push" command so that "push selected" now
+ works, and clicking the "push" toolbar button when an object
+ is selected has the expected effect.
+ Also: Fixed the Tcl "label justify" command so that changing
+ vertical justification does not reset the horizontal justfication.
+ Also: Fixed the Tcl-to-xcircuit string conversion so that plain
+ text with spaces is handled as expected (thanks to Mark Martin
+ for pointing out this problem).
+
+343 v3.4 rev 8 11/10/05
+ Changed an instance of "regsub" to make it backwardly compatible
+ to Tcl version 8.3; otherwise, xcircuit fails to start up
+ properly when linked to Tcl/Tk 8.3.
+
+342 v3.4 rev 7 10/28/05
+ Corrected event handling of schematic/symbol association,
+ which was allowing xcircuit to return to "normal" mode while
+ on a library page, resulting in bizarre behavior, and preventing
+ the schematic/symbol association from being made. Thanks to
+ James Vernon for pointing out the problem.
+
+341 v3.4 rev 6 10/25/05
+ Fixed bounding-box calculations on instance loads so that
+ instanced values of expression parameters are handled correctly
+ on file read-in. Also, corrected "resolveparams" to remove
+ cached expression results before writing a page to a file.
+ Also: Added component unnumbering feature (as written, only
+ for devices having the "idx" parameter).
+
+340 v3.4 rev 5 10/21/05
+ Added command option "label replace", menu items "Text->
+ Increment" and "Text->Decrement", and key bindings "i" and
+ "I" (respectively) to auto-increment (decrement) numerical
+ values inside text labels. As part of this, I also rewrote
+ and completed the Tcl list-to-XCircuit string conversion
+ routine.
+ Also: Fixed a bug reported by James Vernon due to accessing
+ free'd memory, which appears to be fatal under Cygwin but
+ not under Linux.
+
+339 v3.4 rev 4 10/19/05
+ Added command option "library filename" and the ability to
+ save the first file from which a library page was loaded.
+ Also: Added the "page load -replace" and the ability to
+ load/save specific libraries by name. Changed the "File"
+ menu and the popup prompts to allow all of this to be done
+ from the GUI interface.
+ Also: Added more Cygwin handling to the Makefile process,
+ and tested the Cygwin compile and install.
+
+338 v3.4 rev 3 10/6/05
+ Some fixes to things broken between versions 3.3 and 3.4:
+ Move "undo" stays on grid. Items being moved during move
+ and copy commands stay with the cursor through pans.
+ Button-3 now does the proper thing for cancellations
+ during move mode.
+
+337 v3.4 rev 2 10/6/05
+ Refined and expanded the hierarchical element handle
+ notation to cover all commands accepting element handles.
+ This will now work for commands such as "element type".
+ Still, only "polygon points", "spline points", and
+ "instance center" commands translate point positions back
+ to the top level.
+
+336 v3.4 rev 1 10/5/05
+ Fixed an error with finishing path edit operations,
+ added "internal units" type to the grid display types,
+ and implemented a (preliminary) hierarchical specification
+ for element handles that can be used with the "polygon
+ points" command to refer point positions back to the
+ top level.
+
+335 v3.4 rev 0 10/3/05
+ Substantially revised the interface and input mechanism,
+ removing the remaining methods that were hard-coded to
+ various mouse buttons. Instead, I have implemented the
+ button "Hold" mechanism in a general-purpose manner that
+ also allows definitions of key hold bindings. I removed
+ many of the event modes, including all of the element
+ creation modes available from the GUI tool buttons, as
+ these are more obviously implemented by changing button
+ bindings. This allows the various modes to be switched
+ on and off, and allows wire drawing mode to be just one
+ of the modes rather than the default mode. Adding "wire",
+ "move", and "pan" modes as more-or-less obvious button
+ binding variations. Added ASCII85 and Flate encoding/
+ decoding to the graphic read/write operations. Added
+ a "-2" option to the command-line invocation of xcircuit
+ to set mouse button bindings for 2-button mice.
+
+Version 3.3 (September 2004 to July 2005)
+----------------------------------------------------------------------
+334 v3.3 rev 38 9/28/05
+ Corrected multiple-button checking routine to look at
+ the event state only, not the button, as the button
+ entry is changed by some routines. This was preventing
+ the shift-button key bindings from working.
+
+333 v3.3 rev 37 9/20/05
+ Corrected SPICE output to generate a line break and
+ continuation "+" character for wraparound lines.
+
+332 v3.3 rev 36 9/16/05
+ Fixed an error with netlist output in which parameters are
+ not substituted if xcircuit is run in batch mode.
+
+331 v3.3 rev 35 9/15/05
+ Fixed parameter indirection---parameter string was not
+ initialized on library read-in, causing a segfault. Also,
+ changed the behavior of ordered spice lines so that they
+ will be placed after any subcircuits are written, to avoid
+ nesting subcircuits. A syntax "spice@" has been added for
+ lines that really should go in front of everything (except
+ for the special title line #1).
+
+330 v3.3 rev 34 9/14/05
+ Implemented "label latex" in the Tcl version, which was
+ missed in the move from Xt to Tcl, and because it is an
+ obscure function, was not noticed for some time. Thanks
+ to Eric West for bringing it to my attention. Also:
+ Applied a patch by Joerg Wunsch that prevents a segfault
+ when rotating a path element.
+
+329 v3.3 rev 33 9/8/05
+ Corrected an error in netlisting that would incorrectly
+ identify empty parameter strings as the "idx" parameter.
+ Also, added a "-nowindow" switch to the UNIX command-line
+ invocation to allow xcircuit to be used as a filter (batch
+ process) without creating/displaying an X11 window.
+
+328 v3.3 rev 32 9/6/05
+ Changed the handling of netlist writing from symbols, in
+ particular to avoid crashing on encountering unexpected
+ info label contents. Also: Added a "-replace" option to
+ file loads, that causes any object in a file to be
+ overridden by one in a library "master copy". Also: Revised
+ the "library make" command to allow an arbitrary number of
+ empty libraries to be created.
+
+327 v3.3 rev 31 8/10/05
+ Fixed a problem with the graphic image handling in which graphic
+ images are saved to the output file if they exist, regardless of
+ whether or not they show up in the output page. Also fixed the
+ PPM reader to handle whitespace and newlines in the header
+ correctly, according to the PPM spec.
+ Also: Added revision information to the "welcome"
+ message in addition to the major.minor version.
+ Also: Some changes to the Makefile to properly handle
+ passing of linker flags in the shared vs. static compiles.
+
+326 v3.3 rev 30 7/28/05
+ Fixed a problem with the startup TCL code that causes XCircuit
+ to fail to start if a parse error is found in the user's
+ ~/.Xdefaults file (even a completely unrelated parse error).
+ Thanks to Roland Roberts for the bug report (and, much earlier,
+ Romano Giannetti, although at the time I administered to the
+ symptoms, not the disease.
+
+325 v3.3 rev 29 7/22/05
+ And yet more auto-numbering revisions. Ensure clearing of
+ device indices prior to both netlist output and auto-numbering.
+ Also, fixed parseinfo() to correctly handle the mode="" case.
+
+324 v3.3 rev 28 7/21/05
+ More fixes to auto-numbering code ($#!@&). Appears to work
+ now for various cases, although I am not satisfied that it
+ covers all situations. One part of the fix forces xcircuit
+ to ignore all fixed component assignments when generating
+ flattened netlists. While this ensures that all component
+ numbers are unique, the output is not what might be expected,
+ especially if there is no hierarchy in the schematic.
+ Probably the parsing for fixed device numbers should *not*
+ be done by parseinfo() but should be handled separately,
+ under the assumption that this handles a limited number of
+ backwardly-compatible cases and that normally it should
+ expect to find "idx" and "class" parameters for each component.
+
+323 v3.3 rev 27 7/20/05
+ Revamped the auto-numbering code (again!) to better handle
+ the "class" and "idx" parameter method, and make auto-numbering
+ independent of the netlist format (i.e., SPICE vs. pcb).
+ Device (component) name ("class") was moved from the object
+ structure to the Calllist structure (after all, if the class
+ is parameterized, then an instance may have a different class
+ from the object's default class), and this is generated directly
+ after generating the Calllist structure, since it is independent
+ of the netlist output format.
+
+322 v3.3 rev 26 7/19/05
+ Further corrections to revision 20 code. Device classes are
+ now checked and updated for non-pcb devices (e.g., mosfets)
+ when doing autonumbering. Also: parameter setting works
+ for multiple selections; e.g., several transistors can be
+ selected at once and have width or length changed simultaneously
+ for all of them. Thanks to Carsten Thomas for the bug report
+ and feature request.
+
+322 v3.3 rev 25 7/18/05
+ Finally logged into SourceForge and incorporated some of the
+ more recent patches found there. Includes a patch to
+ configure.in by Min Sik Kim, and a patch to fontfile.c by
+ Zunda.
+
+321 v3.3 rev 24 7/17/05
+ Updated keybindings with the new function "Graphic", which
+ otherwise causes the help utility to crash. Thanks to John
+ Rigg for the bug report.
+
+320 v3.3 rev 23 7/15/05
+ Added file load and save methods for the "graphic" element,
+ as well as undo/redo operations, a menu item for loading
+ graphic elements, and all essential operations.
+
+319 v3.3 rev 22 7/14/05
+ Corrected broken file parsing from revision 21. Image data
+ is now read from "objectread" like everything else inside
+ the Setup block.
+
+318 v3.3 rev 21 7/13/05
+ Fixed a bug introduced in revision 20. Also, started adding
+ the new basic element type "graphic", to handle inclusion and
+ placement of arbitrary graphic images. This will eventually
+ replace the buggy and cumbersome "background postscript"
+ rendering via ghostscript.
+
+317 v3.3 rev 20 7/8/05
+ Changed the component auto-numbering so that all component
+ values are treated as base-36, to allow handling of non-numeric
+ component numbers. Also, the routine that determines the
+ number to assign will return the smallest unused integer
+ instead of (1 + (largest number found)) so that use of
+ non-numeric values doesn't cause the auto-numbering algorithm
+ to generate strangely large numbers. Also: The auto-numbering
+ algorithm now looks at the parameter "idx" if it cannot find
+ a "pcb"-style info-label. This allows non-pcb parts like
+ transistors in VLSI schematics to be auto-numbered. This is
+ really the preferred way to handle auto-numbering, and all
+ library parts ought to be updated to contain the "idx" parameter.
+
+316 v3.3 rev 19 6/28/05
+ Resolved the issue with retaining the stack order of
+ parts through a delete-undo cycle, so that all previous
+ undo records point to the correct parts in the correct
+ order. This eliminates a lot of spurious error messages
+ coming from the undo mechanism.
+ Also: Resolved the issue with polygon/arc/spline/path
+ rotations, where rotations cannot be undone exactly due
+ to accumulating roundoff errors. The solution is simply
+ to treat the rotation as an edit for these element types.
+ Also: Fixed an error with label deletion. Labels that
+ are edited out of existance were not handled properly,
+ an egregious error that was somehow overlooked.
+ Also: Modified console.tcl script to withdraw the
+ console window on a window manager "close" request,
+ rather than exit the application. This bolsters
+ the end-user illusion that the console is a subsidiary
+ window of the layout, rather than vice versa.
+
+315 v3.3 rev 18 6/16/05
+ Fixed an error reported by Benoit Bidoggia, in which
+ an attempt to clean up redundant font changes triggers
+ a crash becuase it has been passed the top-level instance
+ instead of NULL (NULL is necessary because this function
+ is called when reading an object definition, at which
+ point there are no instances).
+
+314 v3.3 rev 17 6/12/05
+ Fixed another error that showed up in Uwe's schematic,
+ which is that the "test_insideness" algorithm fails if
+ the box is degenerate---which happens for labels that
+ are parameters set to a null string.
+
+313 v3.3 rev 16 6/10/05
+ Corrected an error found by Uwe Zimmermann in which
+ xcircuit calls free() on an unallocated space when
+ destroying an object containing an indirect parameter.
+ Also: Added some experimental code replacing the
+ drawing functions with OpenGL. This can be compiled
+ in by passing "--with-opengl" to the "configure"
+ script. However, the code is currently unfinished.
+
+312 v3.3 rev 15 5/31/05
+ Added another feature to the change of revision 14:
+ Info labels that have negative sequence numbers (e.g.,
+ "spice-1:", "spice-2:", etc.) will be written after all
+ subcircuit and component output, whereas the usual positive
+ sequenced labels "spice1:", "spice2:", etc., will be written
+ before subcircuit and component output. Each sequenced line
+ is followed by a return character in the output. First and
+ last line of the netlist output is hard-coded (e.g., circuit
+ title and ".end" line in SPICE (see rev 5 comments)).
+
+311 v3.3 rev 14 5/27/05
+ Changed behavior of netlist generation to allow (finally!)
+ info labels on a top-level schematic. These labels are
+ written verbatim into the output. Probably needs checks
+ to avoid attempting to process certain embedded escapes
+ like pins. . .
+
+310 v3.3 rev 13 4/08/05
+ Fixed an error that missed recalulating the instance
+ bounding box after a text rejustification.
+
+309 v3.3 rev 12 3/29/05
+ Changed behavior of the netlist connectivity highlight
+ function in response to a suggestion by Long Yang that
+ pin connection points should be hightlighted, the better
+ to show places where a net does not attach to a pin.
+ Also: Added a feature in response to a comment by John
+ Barry that error messages disappear when netlists are
+ saved if the netlist is not recreated. This feature
+ includes a checkbox in the Tcl wrapper that by default
+ forces regeneration of the netlist on each netlist file
+ write function.
+
+ IN PROGRESS---Added "idx" to Pagedata; need to separate
+ areastruct.page from the actual printed page number.
+ This simplifies page re-ordering and allows schematic
+ libraries to be "hidden" among the rest of the pages.
+ xobjs.pages and areastruct.page will still refer to the
+ index into pagelist.
+
+308 v3.3 rev 11 3/12/05
+ Fixed an error, pointed out by Long Yang and Svenn Bjerkem
+ in which xcircuit crashes when descending into an object.
+ This was due to out-of-bounds array addressing, and must
+ have been in the code for some time, but only shows up
+ on some compilers (Solaris?).
+
+307 v3.3 rev 10 2/27/05
+ Fixed an error in the flattened netlist output that has
+ probably existed in most revisions of 3.3 to date,
+ where net names are not correctly passed down from
+ parent cell to child cell. Thanks to Mark Chang for
+ pointing out the error.
+ Also: Fixed a bug in the selection mechanism where
+ the selection is not NULLed prior to return from the
+ calling routine if no selections are found.
+
+306 v3.3 rev 9 2/5/05
+ More changes to the selection mechanism. Selection
+ mechanism sorts polygons (wires) according to
+ distance of the nearest edit point. Previous
+ selection is always kept and compared against
+ current selection. "pick" is only advanced if the
+ selections are the same. Pointer position when
+ selecting a polygon to edit is restored from the
+ warped position after a button-3 cancel function.
+ Also: Added all edit functions to the "undo"
+ mechanism, as well as label creation.
+
+305 v3.3 rev 8 2/4/05
+ Corrected several mistakes in the selection mechanism
+ that left pending (unfinished) events on the stack.
+ Also: Corrected a problem from rev. 7 that did not
+ register unselection events (key "x") with the undo
+ mechanism.
+
+304 v3.3 rev 7 2/1/05
+ Revamped the selection mechanism (finally) to get
+ rid of the cumbersome "click to select or reject"
+ method. The new method picks one element, and
+ cycles through objects so that a different object
+ is selected on each button press, if several elements
+ are found at the pointer position. This method would
+ be equally unwieldy save for a change in the way
+ object instances are selected---the selection routine
+ recursively searches for elements inside objects that
+ are close to the pointer position (albeit with a wider
+ capture range than on the top level). This prevents
+ selecting an object instance with lots of white space
+ if the pointer is in the middle of the white space
+ (such as a frame or border object).
+ Also: Corrected the "Make Matching Symbol" callback.
+ Thanks to Mark Chang for pointing out the error.
+
+303 v3.3 rev 6 1/4/05
+ Made additions to the "pcbout.tcl" script to support
+ SMD integrated circuits, and resistors and capacitors
+ (both chip and axial). "pkg" parameter added to the
+ Resistor and Capacitor parts in the "analoglib2"
+ library.
+
+302 v3.3 rev 5 12/16/04
+ Corrected a fatal error in library copies if no valid
+ object is selected. Corrected a compile error (C++-like
+ syntax fails on many compilers). Added option to print
+ or not to print the ".end" statement at the end of a
+ SPICE deck.
+
+301 v3.3 rev 4 12/10/04
+ Corrected an error that allows "temp label" pins to be
+ assigned the same name for different nets. The number
+ following "int" or "ext" on temp labels is now changed
+ to match the net number when referencing the label name,
+ if it is found to be different.
+ Also: Corrected another bug that causes a crash when
+ copying an edited parameter back to an object. The
+ data record for the PARAM_END structure was not zeroed.
+ This was okay previously because the data record was
+ unused.
+
+300 v3.3 rev 3 12/6/04
+ Corrected a problem in which drawn subcircuits and
+ subcircuits declared with an "X.." in the info label
+ will share index numbers, by forcing SPICE output to
+ generate a devname of "X" for each drawn subcircuit
+ object.
+ Also: Changed the behavior so that device numbering
+ starts at zero, not one. Otherwise, if a device is
+ numbered zero on the drawing (e.g., by having the index
+ number entered by hand), xcircuit will generate a spurious
+ "duplicate part" warning.
+
+299 v3.3 rev 2 12/3/04
+ Fixed an error (apparently from 3.3 rev 0) that caused
+ parameters to become hosed if changed (also causes program
+ crashes).
+ Also: Added handling of X11 button4 and button5 events for
+ (potential) binding to mouse scroll wheel motion.
+
+298 v3.3 rev 1 10/8/04
+ Changed the behavior of the PCB netlist generator to be
+ more intelligent about finding the bottom of the
+ layout hierarchy. Also, corrected the netlist generator
+ where it allowed a global net to be merged into a local
+ net.
+
+297 v3.3 rev 0 9/28/04
+ Replaced the "hspice" directory with Conrad Ziesler's
+ "spiceparser". The use of routine AddNTermModule() has
+ broken the spice input for now, although once fixed, the
+ results should be much improved.
+ Also, changed the handling of expression parameters so
+ that expression parameter results may be numeric, and
+ evaluated results are saved in the PostScript output as
+ instance values. When traversing the hierarchy during
+ redisplay, commands invoking a "selected" element will
+ pick up the object instance being rendered. The
+ combination of these changes allows the implementation
+ of several useful features such as counter-rotation and
+ displaying the name of an object within the object.
+
+Version 3.2 (January 2004 to September 2004)
+----------------------------------------------------------------------
+296 v3.2 rev 27 9/17/04
+ Quick fix to allow the non-Tcl code to compile; the
+ experimental "ngspice" code contains numerous Tcl references,
+ and although it does not depend on Tcl in principle, it is
+ easier just to disable the code for the non-Tcl compile.
+ It will not be missed.
+ Also: Changed the startup method from the hacked-up
+ redirection of $HOME to a standalone "wish"-like executable
+ that sets up "wish" to read in the .xcircuitrc file as its
+ startup script.
+
+295 v3.2 rev 26 9/7/04
+ Changes based on comments from Dale Grover for correct
+ compilation/linking/installing under "Fink" on Mac OS-X
+ 10.3.
+
+294 v3.2 rev 25 9/6/04
+ Fixed the wrapper code to ignore Tk's standard binding for
+ the Tab and Shift-Tab key events during label text input.
+ Otherwise, the window loses focus, which is an annoyance.
+
+293 v3.2 rev 24 8/25/04
+ One major fix to the netlist code to insist that "updatenets"
+ is never run on a symbol. Otherwise, a circuit that has a
+ symbol that is not used anywhere will generate an error when
+ netlisting, resulting in no netlist.
+ Also, many minor fixes/enhancements to the TCL command-line
+ functions, mainly to support scripting. There is now a
+ script called "sue_xc.tcl" that supports the generation of
+ schematics from ".sue" files (in particular, this is to
+ allow xcircuit support for the IIT standard cell library;
+ see http://www.ece.iit.edu/~vlsi/scells/).
+
+292 v3.2 rev 23 8/18/04
+ Rather important fix from back in revision 19, in which routine
+ "pointtonet" is supposed to merge crossing wires if they cross
+ on top of a subcell port. This is the method used to connect
+ crossing wires with the "dot" symbol, so it is rather important.
+
+291 v3.2 rev 22 6/21/04
+ Added capability to the parameter selection mechanism to handle
+ Tcl-expression parameters of the form "lindex {list} <index>".
+ Such expressions will generate a listbox-type popup window in
+ which the user is prompted to select one of the choices in the
+ list. The parameter will be replaced by the same expression
+ but with <index> changed to reflect the index position of the
+ chosen parameter value. The way to make such parameters in the
+ first place is "parameter make expression <name> {lindex {list}
+ <index>}". To change the expression itself instead of selecting
+ a choice from the list, use "parameter set" instead of the GUI
+ interface. Thanks to Paul Surgeon for suggesting this method.
+
+289 v3.2 rev 21 5/58/04
+ More quick fixes: Makefile error installing .tcl and .lps files
+ due to an error in Makefile.am; library object import now checks
+ library version and does not attempt to import libraries that may
+ be missing a dependency list. Distribution libraries updated to
+ make sure all of them will work with the library import function.
+ Tcl function "library <name> <options...>" changed to accept
+ "<name>" when library name is "Library: <name>". This makes more
+ sense, as it allows one to do, for instance:
+ "library load asg_spice"
+ "library asg_spice save asg_spice_new"
+
+288 v3.2 rev 20 5/26/04
+ Quick fix to a bug pointed out by Petter Larsson, which must have
+ been in the code for some time, which checks for names incompatible
+ with the PostScript interpreter but then fails to make the change.
+ Also, cleaned out some source code copies left over from bus
+ representation implementation.
+
+287 v3.2 rev 19 5/20/04
+ Finally got the bus notation handling into enough of a working
+ condition that I dare to post the distribution. In addition to
+ basic fixes, improvements include handling of buses and partial
+ buses with the "connectivity" function, and in particular,
+ handling of instance-specific labels throughout the netlist
+ (previously was only applicable to the netlist output). The
+ instance-specific labels allow the new "tap" object to work.
+ Added the tutorial file "buses.ps" to the examples directory.
+
+286 v3.2 rev 18 5/6/04
+ Removed the requirement that the GUI must be in place prior
+ to startup. XCircuit can be embedded directly in another
+ application with or without its own GUI. Without the GUI,
+ it is necessary to create (and map) a "simple" window
+ (e.g., "simple .mytest.draw -bg white -width 700 -height 400"),
+ and then set the Tcl array variable "XCOps(window)" to be the
+ Tk pathname of this window. This creates a window into which
+ things can be drawn by Tcl command-line commands. To enable
+ button and key actions, it is necessary to do:
+
+ bind .mywin.draw <ButtonPress> {xcircuit::standardaction %b down %s}
+ bind .mywin.draw <ButtonRelease> {xcircuit::standardaction %b up %s}
+ bind .mywin.draw <KeyPress> {xcircuit::standardaction %k key %s}
+ bind .mywin.draw <Enter> {focus %W}
+
+ from the Tcl command line. It is also possible to rewrite the
+ wrapper script so that the whole GUI is present but rooted in a
+ location different from ".xcircuit". In that case, set the
+ variable "XCOps(top)" to the top-level window name before
+ invoking xcircuit::start. In either case, one must run "wish"
+ first, then load "xcircuit.so", create the appropriate Tk window
+ or windows, set the appropriate XCOps() variable, then do
+ xcircuit::start.
+
+ Handling of bus notation is still unfinished in this (unreleased)
+ version, and probably breaks the schematic capture altogether.
+ This will be fixed prior to an actual distribution release.
+
+285 v3.2 rev 17 4/14/04
+ Major enhancement: Handling of bus notation in netlists!
+ Also, Prohibit parameters from shadowing PostScript reserved
+ names and definitions in xcircps2.pro, as is done for object
+ names. Also, finally found and excised the bug that was
+ preventing correct comparison between object definitions on
+ read-in, which was introduced along with the parameter type-
+ promotion code. Fixed another bug which prevented
+ parameterizing position. And, fixed a bug which prevented
+ disabling flip invariance on text from the menu in the TCL
+ version. Also: made more convenient constructor/destructor
+ functions in elements.c, for general purpose use; these are
+ called from tclxcircuit.c. Also: Reimplemented "strdup"
+ as "Tcl_Strdup" in the TCL version; otherwise, there are
+ places where memory is allocated by strdup, bypassing TCL's
+ memory allocation, but free'd by Tcl_Free(). Also: modified
+ the library manager "library import" routine to load any
+ library instances of an object in addition to the object
+ itself.
+
+284 v3.2 rev 15 3/15/04
+ Reinstated colors and other parameters as XDefaults-style options
+ in the TCL version using the Tk_GetOption() command. Changed
+ autoconf so that the TCL version is compiled by default (unless
+ not found, or explicitly disabled). Initial work on bus
+ notation parsing.
+
+283 v3.2 rev 14 3/03/04
+ Added a library manager (often requested) for handling large
+ lists of parts. Allows objects to be imported from libraries
+ piecemeal.
+
+282 v3.2 rev 13 3/03/04
+ Changed the TCL scripts and shell startup file so that the
+ README directions for a test execution prior to install actually
+ work as advertised. Also, finally found a way to force automake
+ to compile the tcl version with just "make" and "make install",
+ thus hopefully eliminating the greatest source of compile-time
+ woes. Re-implemented the .so file loading so that the reported
+ error is the real root cause error, not "file not found". Also:
+ removed Imakefile and all references to it. Also: Added a
+ menu item for the PCB layout generation. This is not yet
+ sourced by default.
+
+281 v3.2 rev 12 3/01/04
+ A couple of fixes to bugs reported by Brek Miller. 1) Library
+ copy did not copy parameters correctly (missed both the "key"
+ and "which" entries), and 2) The object comparison mechanism
+ failed to correctly compare objects with parameters due to a
+ typo in the code.
+
+280 v3.2 rev 11 2/27/04
+ Some changes to command functions and netlist output. Added
+ file lib/tcl/pcbout.tcl, a script that converts an xcircuit
+ schematic into a preliminary PCB layout. This is very spare
+ at the moment, to say the least; for instance, it only
+ supports 7400-series devices. But it's mostly proof-of-
+ concept.
+
+279 v3.2 rev 10 2/26/04
+ Some Makefile/configure changes, esp. for systems like Debian
+ that do not find the Tcl/Tk include files. Also, rearranged
+ the menus so that "linewidth" commands (global and wire line-
+ width) are more obviously placed ("wire linewidth" duplicates
+ the "element border" entry). Thanks to Forrest Cook for this
+ suggestion. Also, rewrote the library load command in
+ xcircuit.tcl so that it prints the actual root cause error
+ instead of complaining about "file not found". Also, rewrote
+ and extended the "help" window in Tcl, making it entirely
+ script-driven from Tcl, and adding help text for each function.
+ This required adding Tcl command "bindkey" variant with no
+ arguments, which returns a list of all functions which can be
+ bound, and "bindkey -func <function>", which definitively
+ asserts that the argument is a function, not a key (because,
+ e.g., "Delete" is both a key name and a function). Also,
+ made XCF_Prompt (key "%") execute xcircuit::raiseconsole in
+ the TCL version (previously undefined in TCL).
+
+278 v3.2 rev 9 2/20/04
+ Greatly expanded the undo mechanism, which now covers most of
+ the major xcircuit functions. This is definitely "beta test"
+ code. Also, renamed a number of functions and definitions to
+ be clear about the difference between an element and an
+ object (this confusion was left over from the really early
+ days of the program).
+
+277 v3.2 rev 8 2/11/04
+ Improved the ghostscript rendering mechanism so that it can
+ handle (non-encapsulated) pages output from ghostview (which
+ includes some global state-setting commands). Also, greatly
+ improved the rendering by backgrounding the process. Xcircuit
+ draws a blank background and continues until ghostscript
+ reports that the page is finished, at which point the page
+ gets redrawn with the background.
+
+276 v3.2 rev 7 2/6/04
+ Some fixes to the ASG and hspice routines; automake now checks
+ for g++-3 <stl> vs. the older <stl.h> header file and adjusts
+ accordingly. The hspice parser no longer produces files
+ netlist.sp and netlist-flat.sp. Compilation of ASG is now
+ disabled by default (and will be until it's stable. . .), and
+ requires "configure --enable-asg" to enable the module.
+
+275 v3.2 rev 6 2/5/04
+ Added the ASG and hspice parser modules back in, with additions
+ to the master Makefile and configure script to support compiling
+ both modules into the xcircuit Tcl shared object library
+ xcircuit.so.
+
+274 v3.2 rev 5 1/29/04
+ There was a 3.2 previously for the ASG implementation. This is
+ being done again from scratch, but I'm continuing the revision
+ numbers where I left off, at 5. Prior to adding ASG back in,
+ version 3.2 is in the process of implementing the "comprehensive
+ undo" function by creating the framework for running undo/redo
+ events and recasting the "delete" function into this framework.
+ More to be added in coming revisions.
+
+Version 3.1 (January 2003 to January 2004)
+----------------------------------------------------------------------
+273 v3.1 rev 38 1/28/04
+ Removed #ifdef SCHEMA from everything. This should have been
+ done long ago. . . Also, removed %%PageBoundingBox from the
+ output for encapsulated PostScript files, as this appears to
+ screw up output when including the drawing in a document, such
+ as a LaTeX file. Changed the behavior of the output dialog box
+ such that the page label is checked before writing, and the page
+ label is set to the filename if the label is still "Page #"
+ at the time the label is set. Fixed the behavior of selecting
+ fill and border styles, especially a critical error with fill
+ styles that would allow polygons to acquire an invalid state,
+ causing netlist problems and/or unmatching PostScript output.
+ Changed the selection behavior such that elements are not
+ unselected after border/fill/color changes. Fixed the behavior
+ of network connectivity highlighting to work with multi-page
+ schematics. Changed some event handling to let most button-
+ release events act on the mouse position on the previous
+ button press (this works for drawing wires and editing polygons,
+ but not for copying elements). Added "%N" escape to the
+ tag callback mechanism to allow all arguments to be passed to
+ the callback procedure as a list. Fixed marking of "Closed"
+ checkbox in the Tcl "Border" menu.
+
+272 v3.1 rev 37 1/23/04
+ Preparing for XCircuit 3.2 (ASG).
+ Revised some of the code structure of netlist.c, added routines
+ NameToPosition(), from the ASG code (xcircuit-3.2), and
+ PortToPosition(), which is a variant thereof. Added the routine
+ ratsnest(), called by the command "netlist ratsnest" in the
+ Tcl console, which demonstrates some of the features required
+ for true ASG. Also: removes deleted items from the netlist
+ piecemeal, so that an ASG system can operate on an invalidated
+ netlist without encountering dereferenced pointers, or elements
+ which are not on the page they claim to be on.
+ Also: Fixed another bug similar to that in #271 where no space
+ was printed after the closing "}" in multipart strings appearing
+ in parameters, which equally bad results.
+
+271 v3.1 rev 36 1/21/04
+ Added support for schematics spread over multiple pages. The
+ method is that all top-level pages that have the same page
+ label (object name) will be considered part of the same
+ schematic. One of the pages is considered the "master", or
+ "primary" page, and keeps the netlist/portlist/calllist for
+ all the pages. The other pages are the "slave" or "secondary"
+ pages, and refer to the master page for netlist information.
+ Also: Fixed a couple of bugs resulting from messing with
+ the parameter formats, namely 1) put back the check for
+ equal "which" value in varpcheck and varfcheck, and 2) added
+ a space after printing a null-string "()" parameter value.
+
+270 v3.1 rev 35 1/16/04
+ Modified and completed support for expressions in parameters.
+ In the TCL version, this supports all TCL expressions. In the
+ non-TCL version, it allows simple character strings to be used
+ in parameters. The expressions are not translated into
+ PostScript; the PostScript output records the expression, which
+ is unused, and the last evaluated result, which is taken to be
+ the parameter value. Cleaned up more code for numeric and
+ indirect parameters, and added TCL options "-verbatim" and
+ "-indirect" to the "parameter" command to facilitate handling
+ indirect and expression parameters.
+
+269 v3.1 rev 34 1/9/04
+ Cleaned up and finished most of the stuff having to do with
+ numeric parameters, parameters promoted from numeric to string
+ types, parameters on a top-level page, and indirectly-referenced
+ parameters. Also: Tcl variables moved into a single array.
+ Also: Some support for arithmetic expressions in parameters.
+ Very rudimentary at present.
+
+268 v3.1 rev 33 12/16/03
+ Fixed the text justification routine in TCL ("label justify ...").
+ Thanks to Petter Larsson for the bug report. Fixed two problems
+ with "page clear"---one reported by Brek Miller, showing that
+ the free_single() routine was removing parameters from the
+ referenced object, not the instance, and one reported by Joel
+ Kuusk, where the Tcl "clear page" command allows clearing a page
+ while editing an object instance in the hierarchy of that page,
+ causing an immediate crash. Finally, corrected prototypes.h
+ for routines setjustbit() and setpinjustbit() for the non-Tcl
+ compile, left in an improper state in revision 32. Thanks to
+ Dave Armbruster for this bug report.
+
+267 v3.1 rev 32 12/10/03
+ Fixes to the linewidth/border width changing from the menu in the
+ TCL version, as pointed out by Rob Olsen. Also, on suggestion from
+ Makram Mansour, added LaTeX label handling.
+
+266 v3.1 rev 31 12/08/03
+ Three fixes from bug reports by Bliss Carkhuff: "page save" returns
+ TCL_OK rather than an undefined value, parameter entry requires
+ exact match to keywords to get text escapes such as "underline", and
+ substring parameter creation corrected for creating parameters in
+ the middle of a label. Page save error also pointed out by Mark
+ Martin, and Rob Olsen who additionally noted the additional error
+ in linewidth selection (which has also been fixed).
+
+265 v3.1 rev 30 12/01/03
+ Made another change to the output such that all objects used on
+ all pages are output first, inside a PostScript DSC block
+ "DocumentSetup", followed by all the pages. This modification
+ allows viewers like ghostview to figure out that these objects
+ may be used by any page, and prevents errors that occur when
+ skipping pages forwards or backwards in the viewer.
+
+264 v3.1 rev 29 11/26/03
+ In response to Romano Giannetti, fixed the bounding box
+ routines so that EPS files are handled the way they used to be.
+ The only thing required was to set the overall bounding box to
+ remove the 1" margins; the page bounding boxes remain the same,
+ and ghostscript, ghostview, and EPS insertions into LaTeX
+ documents all appear to be handled correctly. Also, added the
+ "override" commands to the TCL interface, although to match the
+ rest of the TCL syntax, these have been changed to "library
+ override", "loadfont override", etc.
+
+263 v3.1 rev 28 11/19/03
+ Changed the way XCircuit handles embedded bounding boxes
+ and does page scaling and translation in the output.
+ Removed the "offsets" comment line from the output and
+ changed it to a PostScript translation, which means that
+ all the positional values in the PostScript output on a
+ top-level page are all in xcircuit internal units, without
+ offset, and are therefore invariant with scale, page size,
+ etc. When an embedded bounding box is present, xcircuit
+ translates the output such that the bounding box is centered
+ on the page. If "auto-scale" is selected, then the output
+ is scaled such that the bounding box fits centered on the
+ page with 1" margins minimum.
+
+262 v3.1 rev 27 11/16/03
+ Extended the parameter method to include parameters passed
+ inherited by an object instance from its parent. Fixed the
+ "make object" method such that parameters are copied into the
+ new object (as yet, the new object does not correctly inherit
+ the parameter from the parent). Added preliminary support
+ for promoting numerical parameters to strings.
+
+261 v3.1 rev 26 11/11/03
+ More fixes and extensions related to parameter key:value
+ pairs. Added a popup window in the Tcl version for
+ editing substring parameters of an object instance,
+ including functions for formatting ASCII strings from
+ string parameters and vice versa. Added a function
+ for the "Add New Color" button in the Tcl version, which
+ was missing. Command syntax "color <idx>" changed to
+ "color set <idx>" and option "color add <name>" added.
+
+260 v3.1 rev 25 11/6/02
+ Changed parameter handling to a key:value pair model.
+ Revised built-in libraries to take advantage of this
+ method, using keys like "value", "units", "length",
+ "width", etc. Expanded and revised the "parameter"
+ command in Tcl-based XCircuit to provide the key:value
+ information, as well as providing parameter information
+ down one level in the hierarchy for an object instance
+ (using the key "-forward" as the last argument to the
+ "parameter" command). Added command option "type" to
+ list parameter types, or to list parameters by type.
+ Finished code for removing parameters.
+
+259 v3.1 rev 24 9/19/03
+ Added feature (macro "V" key) to make a library virtual
+ instance from an object selected on a page. This allows
+ users to make temporary copies of parameterized (or
+ rotated, or flipped) objects for quick retrieval.
+ Several corrections: Xcircuit now checks for symbols
+ associated with schematics and saves them, even if the
+ symbols are not used in any schematic. This prevents
+ associations from being lost after a save/quit/load
+ cycle in an unfinished schematic. Also: Snap and
+ polygon edit will invalidate the netlist. Also: "Make
+ matching symbol" reports an error if the schematic page
+ has an invalid name.
+
+258 v3.1 rev 23 9/15/03
+ Corrected revision 22, which duplicated the NameToObject
+ routine by mistake. Also added TCL wrapper key bindings
+ for function keys "Page Up" and "Page Down" to increment
+ or decrement the page number (helps with large numbers of
+ schematic pages).
+
+257 v3.1 rev 22 9/10/03
+ Moved routine NameToObject from tclxcircuit.c to schema.c,
+ since it is used by the non-Tcl based code and prevents
+ compiling the non-Tcl version. Thanks to Swee-Ann Teo for
+ pointing out the error.
+
+256 v3.1 rev 21 9/5/03
+ Fixed a problem with the Tcl calls to the zoom functions,
+ which were passing a NULL event structure. Thanks to Ed
+ Casas for pointing out this error. Also: Fixed the
+ Makefile.am file for compilation under Cygwin, which was
+ presented the wrong name for menudep.o. Thanks to Carlos
+ Davila for pointing out this error.
+
+255 v3.1 rev 20 9/4/03
+ Changed key and button handling in Tcl to work using the Tk
+ "bind" function, with the usual behavior being bound to the
+ "standardaction" command. Standard actions can be rebound
+ using the xcircuit "bindkey" command, or keys can be bound
+ to Tcl procedures using the Tk "bind" command.
+
+254 v3.1 rev 19 8/12/03
+ Required reconfiguring without Tcl once to generate the
+ "Makefile.in" in the Xw directory; otherwise, automake 1.7
+ becomes a requirement.
+
+253 v3.1 rev 18 8/6/03
+ A fix to the output, correcting the page numbering in the
+ PostScript page headers. The incorrect numbering can cause
+ some printers to lock up. . .
+
+252 v3.1 rev 17 7/14/03
+ Thanks to Ted Roth for fixing my rather too-hasty fix of
+ revision 16. Also: Some fixes to the autoconf script (also
+ from Ted Roth), and autoconf script updated to work with the
+ latest versions of autoconf/automake/aclocal.
+
+251 v3.1 rev 16 7/08/03
+ Fix to "x" and "y" output for .sim format---thanks to Kath Shih
+ for pointing out this error.
+
+250 v3.1 rev 14 5/05/03
+ Incorporated a patch from Max Horn to remove all references
+ to "malloc.h" from the headers, and fix the configuration file
+ for Mac OS-X compilation.
+
+249 v3.1 rev 13 4/29/03
+ Fixed a problem due to automatic search for schematics which
+ prevents a single page from being saved. The output window
+ now shows both "schematics" and "subcircuits" with checkboxes;
+ pushing "schematics" unlinks top-level schematics, and pushing
+ "subcircuits" can prevent subcircuits from being saved along
+ with the file. In either case, the filename is blanked out
+ so the user will not mistakenly overwrite the original file
+ with a truncated one. In conjunction with this method, the
+ Tcl "page links" command has been extended to include the
+ options "independent", "dependent", "total", "pagedependent",
+ and "all". Eventually, I expect to add an additional option
+ "list" to list page names instead of simply enumerating them.
+ Thanks to Mark Jones for pointing out this error.
+
+248 v3.1 rev 12 4/14/03
+ Fixed the PostScript background rendering, which was only
+ broken because of a broken implementation of ghostscript
+ (version 6.5).
+
+247 v3.1 rev 10 3/21/03
+ Replaced TkCon with the version used with magic, fixing a
+ minor issue with handling backslash escape sequences.
+
+246 v3.1 rev 9 2/26/03
+ Fixed the install for revision 8, which failed to run the
+ xcircuit.tcl script through the m4 preprocessor. Also, on
+ recommendation of Mark Jones, added a warning message when
+ pins exist on a symbol which do not exist in the associated
+ schematic.
+
+245 v3.1 rev 8 2/23/03
+ Resolved numerous issues with cross-application methods.
+ Overloaded the "label" Tcl procedure to accept both xcircuit
+ and Tcl syntax, and removed the "bgerror.tcl" file.
+ Added procedures for calling netgen, IRSIM, and magic while
+ running XCircuit.
+
+244 v3.1 rev 5 2/19/03
+ Fixed (for the third time(!)) occurrences of "getline" which
+ should have been changed to "setline". Fixed the toolbar
+ widget so that it recomputes its width when the window size
+ changes, and so that it does not squeeze the height of the
+ bottom message bar.
+
+243 v3.1 rev 4 2/12/03
+ Added handling of "va_copy" to the configuration script for
+ systems which do not define it. Also: Added "%x" and "%y"
+ escapes to the info label syntax, for writing positional
+ information to the output (helps LVS programs like "netgen"
+ trace back errors to the schematic). Split the "Manifest"
+ file into "CHANGES" and "TODO" and started adding revision
+ numbers to the change log entries to match the revision
+ number on the website download page.
+
+242 v3.1 rev 3 2/10/03
+ Added Tcl handling of the string parameter insertion via a
+ popup prompt.
+
+241 v3.1 rev 2 2/04/03
+ Traced the "No per display information" error to use of an Xt
+ function (XtDispatchEvent()); replaced with Tk_HandleEvent().
+
+240 v3.1 rev 1 2/03/03
+ Fixed numerous problems with the Tcl-based version, and added
+ several missing functions (such as the select filter, and
+ handling keystroke <return> in the filelist widget).
+
+239 v3.1 rev 0 1/24/03
+ Finished preliminary version of Tcl-based xcircuit. Relocated
+ runtime files back to (default) "/usr/local/lib" (instead of
+ autoconf's default $datadir "/usr/local/share"). Threw in
+ tkcon.tcl for compatibility with magic/irsim/netgen and recast
+ fprintf() as macro Fprintf(), which calls "tcl_printf()" in
+ the Tcl version and "fprintf()" in the other versions. Added
+ command-line function "-exec <file>" to the Tcl version for
+ running in batch mode (or alternately, just to bypass the
+ default startup file).
+
+Version 3.0 (June 2002 to January 2003)
+----------------------------------------------------------------------
+238 v3.0 1/15/03
+ On advice from Zhengdao Wang, changed the postscript header to
+ draw "opaque" styles as solid color, not stipples. All fill
+ styles except for white (empty) are made opaque by default and
+ fill style white is made transparent by default. The "opaque"
+ menu button can set the non-default behavior.
+ Also: Added a file loading command to the python and
+ non-interpreter command-line interfaces.
+
+237 v3.0 11/25/02
+ Cleaned up some code with respect to 64-bit pointers, checking
+ for the size of pointers in "configure", and setting the proper
+ integer type for pointers in xcircuit.h. Should compile cleanly
+ on 64-bit systems without the "-taso" switch (which doesn't
+ exist for Linux/alpha systems).
+
+236 v3.0 9/23/02
+ Added pixmap image handling to Tk/Tcl, and removed SWIG from
+ the "make" process. Configure option "--enable-wrapper" changed
+ to "--enable-tcl", "make wrapper" changed to "make tcl", and
+ "make install-wrapper" changed to "make install-tcl". Added
+ the toolbar and associated functions. Added "netlist" function
+ to Tcl for generic netlist handling. Fixed numerous errors in
+ the Tcl callbacks. Tcl functionality is now about 95% of what
+ it should be. Non-Tcl version has not been affected by these
+ changes.
+
+235) v3.0 7/17/02
+ Several bug fixes for bugs reported by Massimo Gaspari (see
+ below).
+
+234) v3.0 7/08/02
+ Fixed bug in the Python "bind" command such that keys not
+ bound to macros return an xcircuit error, not a Python error
+ (bug reported by Bob Paddock). Also fixed a bug reported by
+ Petter Larsson <f97-pla@nada.kth.se> in which the result of
+ getenv("XCIRCUIT_LIB_DIR") is not check for a NULL value
+ when executed from (any) interpreter.
+
+233) v3.0 7/03/02
+ Several bug fixes for parameter-functionality bugs found by
+ Massimo Gaspari <gaspari@tin.it>. Changes are relatively minor
+ and not worth inducing a version number change.
+
+232) v3.0 6/24/02
+ Abount 90% of the Tcl functionality necessary to duplicate all
+ existing functions has been completed. This makes the Tcl-wrapped
+ version useable, but experimental, and a bit crash-prone. The
+ command set it written up in "README.Tcl". Compiling involves
+ doing "configure --enable-wrapper" followed by "make wrapper"
+ and "make install-wrapper". Otherwise, the standard "configure"
+ and "make" results in the standard version of xcircuit.
+
+Version 2.5 (November 2001 to June 2002)
+----------------------------------------------------------------------
+231) v2.5.5 5/21/02
+ Started on the Tcl-wrapped version of XCircuit. Currently
+ this is just a big mess. I am posting it to the distribution
+ with all the wrapper stuff disabled and no instructions on how
+ to compile it, mainly so I don't have to keep making sure that
+ bug fixes are reflected in both versions.
+
+230) v2.5.4 5/14/02
+ Revised the CvtStringToPixel so that it satisfies (or should
+ satisfy) all X servers doing 8 bpp, even those that return
+ bogus values on XLookupColor(). Previous "fix" had disabled
+ private colormap installation.
+ Also: Improved "gettext.py" to deal with tabs and page breaks,
+ and takes optional values for maximum lines per page and font
+ to use. Fixed a bug in "pagebbox.py" and also a related bug
+ which clipped color values to size short when set by "setattr"
+ in Python.
+
+229) v2.5.4 5/10/02
+ Fixed a bug in which XCIRCUIT_LIB_DIR must be defined or the
+ program will crash. Also: Added text split and join functions,
+ and text "up" and "down", mapped to the Up and Down arrow keys.
+
+228) v2.5.4 5/09/02
+ Changed the format of the output of the Python netlist() function
+ to better facilitate flattened netlists. Nets are passed by
+ number and associated to names in a separate dictionary. This
+ allows names to be changed (as required when flattening) without
+ altering the netlist. Otherwise, it becomes a big mess. The
+ new format ends up being smaller than the original. "flatspice.py"
+ has not yet been completed, though.
+
+227) v2.5.4 5/07/02
+ Repaired some problems with the Python netlist() function, and
+ wrote a working version of "spice.py". Will replace the
+ internal functions when the "sim" and "pcb" scripts are written.
+
+226) v2.5.4 4/29/02
+ Various changes in response to bug reports: Fixed library and
+ page object exchange, PCB infolabels on quad parts. Seg fault
+ due to missing code in "unmakenumericalp" has been worked around,
+ but the routine still needs to be finished. Patched filelist.c
+ to query result of stat(). Fixed error with XQueryColors in
+ 8-bit pseudocolor mode.
+
+225) v2.5.4 4/26/02
+ Got rid of the "passive grab" action, which seems to be the root
+ cause of the video screen blanking on some systems. Eventually
+ discovered that "XtAddEventHandler" doesn't work for ButtonMotion
+ if it's called AFTER the button has already been pressed. With
+ this fact in hand, it was easy to avoid all the Add/Remove calls
+ and just add the event handler once, at the beginning.
+
+224) v2.5.4 4/19/02
+ Replaced the top-level object with a top-level instance, with
+ all the ensuing fallout. The resulting code is much cleaner.
+
+223) v2.5.4 3/25/02
+ Fixed the problem of parts being auto-deleted by the netlister
+ pointed out by Jeremy Brown. Also: Fixed a problem found by
+ Bob Paddock in which label segments are miscounted on output;
+ apparently, this only happens using the "gettext" script.
+
+222) v2.5.4 3/21/02
+ Changed library structure so that every object gets an instance.
+ This precipitated many code changes. Along the way I fixed up
+ a bunch of minor errors, too many to list. Bounding boxes in
+ the PostScript output ("bbox" entry) have become obsolete,
+ except for font files, where the bounding box is not necessarily
+ coincident with its contents.
+
+221) v2.5.4 3/19/02
+ Added key binding for "pin global" (key "G"), which was
+ documented but was not actually in the program. Thanks to
+ Jeremy Brown (jhbrown@ai.mit.edu) for pointing this out.
+ Also: On another suggestion of Jeremy's, added a scrollbar
+ to the help window. Along the same lines, cleaned up the
+ "file read" window so that the pixmap is never shorter than
+ the viewport. Fixed a small error with PostScript background
+ rendering---newline before "end_insert" avoids problems with
+ binary-format PostScript. Changed default key binding for
+ BackSpace to equal behavior of Delete. This seems to be what
+ most people expect and/or want as default behavior.
+
+220) v2.5.4 3/12/02
+ Implemented instance-defined bounding boxes and cleaned up a
+ lot of stuff related to bounding boxes. This was needed to
+ properly implement the new "libinst" method described below.
+ Also: Altered the connectivity highlight function so that it
+ retains the number of the highlighted net in the netlist, and
+ continues to display the highlight through page changes and
+ expose events. Fixed a bug in the PCB netlister.
+
+219) v2.5.3 2/27/02
+ Fixed a few minor inconsistencies related to color allocation.
+ Also: Implemented a "select previous" command, an undo command
+ for selections. Third mouse button function ("Escape") will
+ unselect anything that is selected, but if nothing is selected,
+ it will retrieve the last selection. Page/object changes
+ destroy the previous selection record. Also: Added intanced
+ scale and rotation values to the "libinst" record (values are
+ optional). This allows, for instance, the "arrowhead90" object
+ to be replaced by an instance of the original "arrowhead"
+ rotated by 90 degrees. All libraries updated to include
+ useful instantiations of objects rotated by 90 degrees:
+ arrowhead, arrow, circle, jumper, and all of the analoglib2
+ objects which allow instanced rotation and justification of
+ their parameter value labels.
+
+218) v2.5.3 2/26/02
+ Bug fixes to incremental netlisting. Also: Separated the loading
+ of GUI colors from that for layout colors. The schematic capture
+ was re-using SNAPCOLOR, AUXCOLOR, and BBOXCOLOR, which causes bad
+ effects if one attempts to change these values in the X defaults.
+ Re-used GUI colors were not necessarily duplicated or available
+ in the layout color palette, which was also confusing. Also:
+ environment variable XCIRCUIT_LIB_DIR now applies to the search
+ for the startup script. This enables xcircuit to be tested prior
+ to installation by doing "setenv XCIRCUIT_LIB_DIR ./lib" in the
+ top-level source directory.
+
+217) v2.5.3 1/30/02
+ Changed the behavior of the PostScript background so that it scales,
+ rotates, and translates with output selections (Landscape vs. Portrait,
+ and vs. Output Scale), so the behavior is what would be expected. Still
+ allows only one background image per page, though, and the PostScript
+ image can't be scaled, rotated, and translated independently of the rest
+ of the drawing (those things must be done to the image prior to loading).
+
+216) v2.5.3 1/3/02
+ Minor bugfixes: variable reading (varfscan, varpscan) requires skip
+ over whitespace. Netlist requires reinstating routine nearpoint()
+ because matrix transformations have roundoff errors and pin positions
+ should not be compared exactly. Updated Copyrights to 2002. Netlist
+ generation has been confirmed on a large schematic design.
+
+215) v2.5.3 1/1/02
+ First cut at incremental netlisting---implemented a scheme in which
+ netlists are kept after being generated, until they are invalidated
+ or the object is destroyed. This scheme allows the netlist structure
+ to be queried at any time. Netlist creation is independent of the
+ netlist mode, as it should have been to begin with.
+
+215) v2.5.2 12/26/01
+ Correction to duplicate object code makes sure that schematic/symbol
+ association does not get destroyed along with the duplicate object!
+
+ Also: Applied Holger Vogt's patches to configure.in for proper
+ compilation under Cygwin.
+
+214) v2.5.2 12/15/01
+ XCircuit now allows pin labels to be parameterized, treating them
+ as an instance-dependent label. While this does not alter the
+ SPICE and sim netlists, it allows (for example) quad parts such
+ as four NAND gates of a 7400 chip, each having its own unique
+ pinout but sharing the same object.
+
+ Also: To go with the pin labels, added a method for generating
+ "virtual copies" of an object to appear on a library page ("V"
+ key from the library page). The virtual copy is a different
+ instance of the object, and can take different parameters.
+ Started on library "quadparts" with 7400-series pinouts to
+ facilitate use of the new feature with PCB netlisting.
+
+213) v2.5.1 12/06/01
+ Revised the routines that deal with duplicate objects. New routines
+ prevent propagation of appended underscores (used to differentiate
+ between objects with the same name but different structure). The
+ major change is that a list of aliases is kept for objects with the
+ same structure but different names, so there is no confusion through
+ the process of reading the library. When the loading is done, the
+ aliases are removed and the names are cleaned up.
+
+ Also: Switched the copyright to GPL for better compatibility with
+ other open-source tools, and because it's the Right Thing To Do.
+
+212) v2.5.0 11/28/01
+ Removed an ill-conceived routine which would delete duplicate
+ copies of an object even if the names were different. This action
+ can give rise to very bad inconsistencies. A better idea would be
+ to try to "clean up" leading underscores whenever an object with
+ a leading underscore is deleted. However, this is a minor point.
+
+ Also: Fixed a string overrun bug in charreport().
+
+211) v2.5.0 11/16/01
+ Finally (!) added support for parameterized values other than
+ label (sub)strings. This includes parameterization of all
+ element values except color (which is handled by an inheritance
+ model). Includes parameterization of: point position (x, y, or
+ both), line style, linewidth, scale, rotation, label justification,
+ and arc radius, minor axis, and endpoint angles. Includes support
+ loading, saving, displaying, printing, and editing.
+
+Version 2.4 (November 2001)
+----------------------------------------------------------------------
+210) v2.4.0 11/14/01
+ Added python script "pagebbox.py" to create standard page-size
+ bounding boxes (request from Bob Paddock). Along with this,
+ I updated the python code to handle colors by name or RGB
+ components, rather than by index, which is visual-dependent.
+
+209) v2.4.0 11/12/01
+ Bug fixes to 2.4.0: Fallback resources string must be null-
+ terminated, added 2 remaining fallback resources that are
+ not taken care of by the XtGetApplicationResources() routine,
+ and changed XtAddConverter to XtAppAddConverter. I hope that
+ the application-specific references will prevent problems
+ with the timeout functions, and maybe with input focus as well.
+
+ Also: Fixed type casting of values retrieved from the message3
+ widget---values are type "Dimension" and "Position" (usually
+ defined as unsigned short and short, respectively), not int.
+ Causes errors under Solaris and probably other systems, too.
+
+208) v2.4.0 11/09/01
+ Switched to a new method for defining rotation. Rotation in
+ xcircuit is now given in degrees, which matches the PostScript
+ output. Flipping is done in the obvious way by declaring a
+ negative scale value (which is applied only to the X component
+ in the transformation matrix; Y is always positive). Lookup
+ tables for sines and cosines are replaced by the math library
+ functions, which presumably are fast enough not to show any
+ performance hit on most machines. The redefinition of the
+ PostScript prologue prompts the move to a new minor version
+ number. Rotation is still an integer value, so the minimum
+ rotation increment is 1 degree.
+
+ Also: Fixed an error in the PostScript prolog in which text
+ flip invariance was incorrectly implemented after the addition
+ of text kerning & scaling methods. Fixed another error in which
+ XCircuit and PostScript disagree about text orientation due to
+ roundoff errors. Matrix values must be compared to some epsilon,
+ not zero, to determine when the orientation is 90 or 270 degrees.
+ epsilon = 1e-9 works fine.
+
+ Also: Changed certain Xt routines to include XtAppContext in the
+ hope of avoiding the problem with the TimeOut function conflicting
+ with other X11 programs (namely, screensavers). Hopefully the
+ addition of fallback_resources to XtOpenApplication will prevent
+ problems with the X defaults when the X defaults file cannot be
+ found.
+
+Version 2.3 (May 2001 to November 2001)
+----------------------------------------------------------------------
+208) v2.3.6 11/05/01
+ Added rudimentary "edit-in-place". Currently, this is a bit odd,
+ because the hierarchy above the object is rotated to match the
+ "natural" orientation of the object, rather than the other way
+ around. This should be fixed by allowing rotation and flips to
+ the top-level page (keep the transformation matrix for the page
+ rather than just the scale and position). Skewing of the grid
+ due to rotations is a can of worms, though. Probably rotating
+ to the nearest 90 degrees would suffice for most purposes.
+ Edit-in-Place is turned on by default. It can be turned off if
+ the extra drawing clutters the window.
+
+207) v2.3.6 11/01/01
+ Fixed a long-standing error in which the "rejustify" routine
+ was giving labels invalid "justify" bit fields. Fixed a problem
+ with the "visible pins" in which the visibility flag would always
+ be reset by a rejustification of the label.
+
+ Also: Removed the ":n" suffix from pages in multiple-page files
+ with the same name. The addition of the suffix was screwing up
+ the association of symbols to schematics on file reads, and it
+ seems to work fine without it. Some attempt is made to enforce
+ unique names for pages associated to symbols, but it seems to
+ work correctly whether or not names are unique.
+
+ Also: Fixed an error in string parameter deletion, and added
+ a call to mergestring() after deletestring() to connect any
+ divided text.
+
+206) v2.3.6 10/25/01
+ Revamped the file list window on the suggestion of Zhengdao
+ to highlight files that match the expected file extension.
+ Extended this idea to include a "file filter" which displays
+ only those files with matching extensions. This feature can
+ be turned off by clicking a toggle button in case a file with
+ an unusual name or extension cannot be seen.
+
+ Also: Added a flag to the label justification value which
+ allows pins to be seen on hierarchical levels other than the
+ top. Changes to the prolog prompted the change to subversion
+ 6 although the change is fully backward-compatible. Thanks
+ to Bob Paddock for the suggestion.
+
+205) v2.3.5 10/24/01
+ Fixed a netlisting bug pointed out by Bryce Denny in which the
+ layer ordering of label vs. polygon can cause the label to not
+ be associated with the network under it. This led me to
+ discover another bug in which a label position would update the
+ netlist properly but the actual label itself would not be added
+ to the netlist (the only apparent consequence is that the label
+ is not hightlighted during a connectivity check).
+
+ Also: Fixed the behavior of the .xcircuitrc file loading so that
+ keys can be rebound from the file. Added Python commands for
+ pan and zoom, and wrote an example script which rebinds keys "Z"
+ and "z" to a python function which combines the pan and zoom.
+ Separated zoom functions between those with and without screen
+ refresh.
+
+204) v2.3.4 10/22/01
+ Fixed some buggy behavior with respect to loading and setting
+ default fonts in .xcircuitrc and xcstartup.py. Thanks to Jeremy
+ Braun (jtbraun@MIT.EDU) for reporting these errors in detail.
+ Also: Fixed a missing requirement in checking object name
+ syntax. A PostScript name must be a string which cannot be
+ interpreted as a number. Thus, "+9" and "1E9" are illegal
+ names. Thanks to Bob Paddock (bpaddock@csonline.net) for
+ reporting this bug.
+
+ Also: Changed behavior with respect to environtment variables,
+ allowing "TMPDIR" to set the temporary directory and allowing
+ an override of the "XAPPLRESDIR" directory. Added a list of
+ environment variables used by xcircuit to the manual page.
+
+ Also: Revised the tempfile mechanism once again to include a
+ check on the number of times a file has been modified; heavy
+ modification will induce a temp-file save even if the timer
+ has not expired.
+
+203) v2.3.4 10/19/01
+ Implemented a "changed" file mechanism which checks for changes
+ to pages and objects and queries for confirmation if there are
+ unsaved changes upon quitting. Changed filename behavior so that
+ all filenames have their own malloc'd space, instead of sharing
+ filenames. Extended file backup to include different filenames
+ on different pages. Added a toggle box on the output popup
+ window so that a page can be unlinked from a multipage file,
+ and displays the number of pages in the file. Added the simple
+ popup window (no text entry) to the list of python calls.
+
+202) v2.3.4 10/18/01
+ Fixed the crash file recovery so that ONLY the given crash file
+ can be loaded (load and cancel are the only choices). Also,
+ the actual temp file name is hidden from view, and the original
+ filename is recovered from the "%%Title:" header line.
+ Also: Fixed the problem in which startwire() was called after
+ a popup window button was selected.
+
+201) v2.3.4 9/18/01
+ Names of pages added to the library and page directories.
+ Thanks to Bob Paddock <bpaddock@csonline.net> for suggesting
+ the feature.
+
+ Also: Updated "configure.in" to check for the infamous python
+ version 1.5, and disable the python interface if found.
+
+200) v2.3.4 9/10/01
+ RPM package makefile fixes (thanks to Alex Habig
+ <habig@neutrino.d.umn.edu>). Also: changed undelete() to
+ xc_undelete() to avoid conflict with OpenBSD/FreeBSD system
+ calls. Thanks to Mike Andrews <mikea@mikea.ath.cx> for
+ bringing this to my attention.
+
+200) v2.3.4 8/12/01
+ Implemented a Python interface into the netlist structures.
+ Set up for use of Python scripts to generate all netlist
+ output, as well as dealing with non-PostScript format input.
+
+ Also: fixed a problem with crash recovery caused by the
+ program exiting on call to Py_Exit. Improved the crash
+ recovery mechanism to automatically find crash files on
+ startup, and prompt user to load.
+
+ Also: added more Python functions, for page clear, page change,
+ add key bindings to Python functions, and create menu buttons
+ with callbacks to Python functions. Added Python functions for
+ calling a popup prompt, file browser.
+
+198) v2.3.3 7/27/01
+ Fixed more man page problems with the make process. Added
+ default values for Python libraries when the Python Makefile
+ can't be found. Made the rcfile parsing more robust, esp.
+ so it doesn't crash if it attempts to read a non-script file.
+
+197) v2.3.3 7/26/01
+ Added auto-numbering of component numbers using netlist mode
+ "idxpcb". This works for all component numbering (including
+ SPICE and sim) where the component number is parameterized and
+ denoted by a question mark ("?"). Thanks to Lapo Pieri
+ <lapo@iroe.fi.cnr.it> for the suggestion and some code to
+ implement the function outside of xcircuit.
+
+ Also: Fixed Imakefile so that imake uses m4 to generate the
+ man page correctly on "make install.man".
+
+196) v2.3.3 7/18/01
+ Fixed two errors, one which split global nets in hierarchical PCB
+ netlists, the other which failed to find nested parameters.
+
+195) v2.3.3 7/17/01
+ Some changes to the GNU autoconf (with much help from Albert
+ Chin) for correct parsing of the path to python, avoidance of
+ errors when generating the man page, and re-instantiation of
+ the keyboard input focus workaround.
+
+ Also: Removed the behavior of turning pins back into labels
+ when creating objects or moving labels between pages or
+ objects. Added behavior that if a pin is removed (or moved
+ out of an object), and the pin has a unique string, any pin
+ on the corresponding symbol/schematic will revert to a plain
+ label. This was the intended behavior.
+
+194) v2.3.3 7/09/01
+ Added label strings to the Python setattr() command. Added a
+ getcursor() command to Python. Created a python script called
+ "gettext(filename)" which creates an xcircuit label from the
+ contents of an ASCII file.
+
+193) v2.3.3 7/06/01
+ Quick fix to an error in interpreting key names for key bindings.
+
+192) v2.3.3 7/05/01
+ Added environment variable XAPPLRESDIR so that application
+ defaults come from the location specified by the configure script,
+ not /usr/lib/X11/app-defaults. This also allows app-defaults to
+ be used even if xcircuit is compiled without root privileges.
+ The configure script was modified to compile in Xpm, if it can
+ be found.
+
+191) v2.3.3 7/02/01
+ Changed netlist behavior so that wires only connect at endpoints
+ (although an endpoint may attach TO any location along a segment
+ of another wire). Optimized a few routines for speed. Netlist
+ output now changes symbol font and standard font "mu" (i.e.,
+ micro) to "u". Fixed a bug preventing correct loading of files
+ containing multi-part strings as parameters.
+
+190) v2.3.3 6/28/01
+ Cleaned up some behavior with respect to component numbering,
+ including fixing numbering for flattened SPICE output. Added
+ a PCB library for generic IC parts.
+
+189) v2.3.3 6/27/01
+ Corrected the parseinfo() routine so that it correctly uses the
+ symbol, not the schematic, to pick up information about a pcb
+ name. Changed some of the library objects (namely the passive
+ devices like Resistor and Capacitor) so that pin names are PCB-
+ like and device can be given a part number. Changed the netlist
+ compiler behavior so that all indices are numbered relative to
+ a particular component, rather than numbered relative to all
+ components.
+
+188) v2.3.2 6/25/01
+ Replaced the imake build with a GNU configure build. Thanks to
+ Albert Chin-A-Young <china@thewrittenword.com> for setting up
+ the scripts for automake/autoconf. For purposes of compliance
+ with modern directory nomenclature, startup files and such are
+ now installed in /usr/local/share/ instead of /usr/local/lib/.
+
+ Also: Added a "show pin positions" feature (recommended by
+ Larry Doolittle) to the Options menu, which allows pin locations
+ to appear on the hierarchical level above, to help in finding
+ pin connections into objects.
+
+187) v2.3.1 6/22/01
+ More patches from Larry Doolittle, some cleaning up cruft flagged
+ by compiling with -Wall, and re-patching a string function (an
+ error which I am unable to duplicate. But I will take his word
+ for it). Also, worked on Xw/TextEdit.c to implement horizontal
+ scrolling of text (so it will no longer run off the end of the
+ window).
+
+ Also, finally implemented a way to check for overlapping objects
+ caused by a copy or move (this is not exhaustive, but covers the
+ most obvious ways this can happen). This is especially critical
+ for schematics, because multiple circuit elements will end up in
+ the netlist when they cannot be seen on the schematic.
+
+186) v2.3.1 6/21/01
+ Applied patch from Larry Doolittle <ldoolitt@recycle.lbl.gov>
+ to correct error in line length computation when writing output.
+ Also modified file reader to treat lines ending with "{" as
+ continuation lines (such as the beginning of a label), if they
+ don't look like object definitions.
+
+ Also: Copying library objects now also copies the parameters,
+ and the page viewing parameters. Corrected an error wherein
+ stringcopy() calls makesegment(), although the former is
+ supposed to ignore parameters, and the latter doesn't. Also,
+ instantiated a slightly "improved" object compare that is able
+ to compare objects against objects with underscore-prepended name
+ adjustments, in an attempt to avoid a proliferation of underscores.
+ Fixed an error that reset "version" in the middle of a file read
+ if a font was loaded. Updated some of the "examples" files to the
+ current format.
+
+185) v2.3.1 6/18/01
+ Added tilde ('~') expansions to filenames. Thanks to Norman
+ Werner <norman.werner@student.uni-magdeburg.de> for patches which
+ seeded the final version of this code.
+
+184) v2.3.1 6/12/01
+ Changed the Imakefile for Python-2.1 and added instructions to the
+ README file on how to make a shared (.so) python library.
+
+183) v2.3.1 6/11/01
+ Corrected a few errors which showed up on other compilers (thanks
+ once again to Albert Chin, <china@thewrittenword.com>).
+
+182) v2.3.1 6/04/01
+ Fixed an error caught by John Livsey (<jlivsey@bigpond.com>) in
+ which loading old library files causes the version number to
+ revert to 1.9, causing havoc when reloading saved files. This
+ has been fixed along with code to check more decisively for
+ which label syntax is in the file, and adjust the version number
+ accordingly rather than depend solely on the version number
+ extracted from the file header.
+
+181) v2.3.1 5/31/01
+ Cleaned up errors found in the netlist code while doing a large
+ chip project. Added flattened SPICE output and changed SPICE
+ output to be compatible with "hspice" syntax. Netlist compilation
+ runs about three times faster than before, but should be able to
+ do better, still.
+
+180) v2.3 5/16/01
+ Completed the full hierarchy search on subschematics. searchconnect()
+ makes a call to search_on_siblings(), looking for any connection from
+ any object in the hierarchy of viewable (sub)schematics to the object
+ under consideration. Added a bounding box disjoint test to reduce
+ unnecessary searching. Could use a lot more optimization, though.
+
+ Also, from the March 27 version, genportpins() has been merged back
+ into gencalllist(). Spice and Sim netlists are correct for numerous
+ torture tests given to xcircuit.
+
+ Corrected errors in text generation stemming from the new
+ PostScript profile (thanks to Jeremy T Braun <jtbraun@MIT.EDU>
+ for patches). Ultimately, decided to more closely match the
+ PostScript and XCircuit label formats by declaring an overall
+ scale outside of the label segments. All font scales declared
+ by "cf" commands are therefore relative, not absolute. The
+ change in output format prompted the change to version number
+ 2.3.
+
+Version 2.2 (December 2000 to May 2001)
+----------------------------------------------------------------------
+179) v2.2.3 3/27/01
+ Completely overhauled the method for text strings, implementing
+ a linked-list method. In conjunction with this change, also
+ overhauled parameters to be called bottom-up rather than top-
+ down, thus eliminating the need for tracking reallocated
+ memory (which was not compiling correctly under the latest
+ version of gcc). Also made other structural changes, removed
+ the text backspace character, and replaced it with a tabbing
+ system. Made key bindings for text home, end, left, right,
+ delete, return, and special character insert, as well as the
+ new tabbing commands. PostScript profile revised to
+ incorporate the tabbing features.
+ Also: Overhauled the netlist generator. The result is much
+ cleaner and more understandable. The main difference is that
+ the Netlist structure is comprised of nets and pins (no
+ separate Pinlist), and the Paramlist (now called a Portlist
+ to distinguish from object parameters) calls by net number,
+ not by pin name. Ports are accessed dictionary-style, by
+ key-value pairs (port ID : netID). The netlist is generated
+ in by three recursive routines, gennetlist(), genportpins(),
+ and gencalllist(). genportpins() now searches for net
+ connections arbitrarily far down into the netlist hierarchy.
+ gencalllist() resolves net numbers and removes empty calls
+ as it traverses the hierarchy.
+ Also: Implemented recursive selection for finding network
+ connectivity, so any net visible on the page can be queried
+ for both a net name and highlighting the network.
+ Also: Implemented automatic redraw of text with parameters,
+ so that parameters which are edited are immediately updated
+ wherever they occur in the current top-level page.
+ Also: Thanks to Masao Kawamura (kawamura@mlb.co.jp) Media Lab.
+ Inc., Japan, for tracking down several bugs, including a very
+ bad one in which the admittedly dubious syntax
+ a[x] = a[--x];
+ acts like (the intended)
+ a[x] = a[x - 1]; x--;
+ when compiled with -g (debug) option, but acts like
+ x--; a[x] = a[x];
+ when compiled without debug. Also, temporary files have been
+ reimplemented using mkstemp(), which is more secure than
+ tempnam() and tmpnam().
+
+178) v2.2.2 3/7/01
+ Added significantly to the Python interface, including access to
+ all elements on a page by dictionary key:value pair assignment.
+ Added mouse button handling to the key binding, and changed the
+ help window to reflect current key bindings.
+
+177) v2.2.2 3/1/01
+ Fixed a bug in the PostScript profile introduced with version 2.2,
+ wherein string bounding boxes were computed incorrectly because
+ user space was rotated.
+
+176) v2.2.1 2/27/01
+ Implemented code for user-defined key bindings; set up default
+ key bindings to match all prior versions of xcircuit, and added
+ python and script commands to bind and unbind keys with function
+ definitions.
+
+175) v2.2.1 1/30/01
+ Cleaned up a lot of code, making the subroutine parameter lists
+ consistent. Added all the necessary function prototypes as a
+ separate prototypes.h file, and removed unused parameters and
+ unused variables. Fixed a few heretofore unnoticed bugs in the
+ process. Thanks to Karim Kaschani (karim.kaschani@arcormail.de)
+ for instigating this process, although I failed to find the bugs
+ he was experiencing, and may have to revamp the label and
+ parameter string concept (again!) to fix it. Also, thanks to
+ David Nicholls (davidallannicholls@hotmail.com) for a fix to
+ nosprint(), although I didn't implement the rest of his
+ thoughtfully provided code (and there was a lot of it!),
+ preferring to leave much of it to Python scripts, which are
+ coming soon. Expanded the Python functions, but so far, still
+ mostly experimental.
+
+174) v2.2.1 1/22/01
+ Completely redefined the command-line, including the startup
+ script and .xcircuitrc file to be Python scripts, and embedded
+ the Python interpreter into xcircuit.
+
+173) v2.2.0 12/19/00
+ Made additions to the command-line functions; also, declared
+ the library inclusion commands "loadlibrary" and "loadfontencoding"
+ to be obsolete, and changed the startup file "builtins.lps" to
+ a startup script called "startup.script". This makes a lot more
+ sense.
+
+172) v2.2.0 12/15/00
+ Finally declared version to be stable enough for a non-beta
+ release. Revised methods for generating schematics and symbols
+ in the circuit hierarchy. Added (a modified) analoglib2.lps
+ (circuit elements with parameters) to the "builtins" list.
+ Fixed errors with sim and pcb netlist outputs, and cleaned up
+ other minor things. Object types are now "fundamental",
+ "trivial", and "subschematic", as well as "normal" object,
+ with the type depending partly on context.
+
+Version 2.1b (July 2000 to December 2000)
+----------------------------------------------------------------------
+171) v2.1b9 (beta) 11/30/00
+ Added full functionality for text blocks (carriage-return),
+ kerning, scaling, and color change within labels.
+
+170) v2.1b8 (beta) 11/11/00
+ More fixes to the parameterization and netlist functions (thanks
+ to Terry Hancock <hancock@earthlink.net> for help with testing
+ and debugging this extraordinarily complex code). Created a new
+ PostScript prolog which not only fixes one very long-standing
+ error, but also allows text blocks with carriage returns and
+ kerning within text blocks. These functions have not yet been
+ reflected in the xcircuit code.
+
+169) v2.1b7 (beta) 10/30/00
+ Possible fix (again!) to the input focus problem: Added an
+ event handler to catch map and unmap events, so xcircuit should
+ never attempt to set input focus on an unmapped window. Also:
+ extention to information labels allows labels to be broken into
+ parts, i.e., "sim1:", "sim2:", etc., and extended the protocol
+ of '%' sequences to include %r (carriage-return), %t (tab), and
+ %% ('%' symbol, literal).
+
+168) v2.1b7 (beta) 10/25/00
+ Extended PCB netlist capability: An info label beginning with
+ "pcb:" now indicates the object name to be used in naming the
+ pins. The info label can contain all the %-escapes used for
+ spice: and sim: info labels, and similarly, can use parameters
+ with the Alt-p key sequence. A new escape "%n" has been added
+ which inserts the name of the object into the output. The new
+ pcb method can be used to explicitly define instances of an
+ object (i.e., "cap_1", "cap_2") or to redefine a name locally
+ ("inverter" becomes "1/6 74HC04", for instance).
+
+167) v2.1b6 (beta) 10/23/00
+ Fixed a fatal bug pointed out by Wilson Barroz
+ (wbarroz@bol.com.br), in which a break statement got lost,
+ effectively crashing xcircuit if a path was selected.
+
+166) v2.1b6 (beta) 10/2/00
+ Fixed problem with schematic capture on/off, so that pins and
+ info labels are not displayed or saved when schematic capture
+ has been turned off. Fixed much of the problem with parameter
+ strings, and added simple capability to apply a single parameter
+ to multiple strings.
+
+165) v2.1b5 (beta) 9/27/00
+ Fixed problem with writing empty parameter strings to the output;
+ also, fixed a fatal crash error when an entire string is a
+ parameter and is deleted. XCircuit now prevents the creation of
+ parameters on a top-level page.
+
+164) v2.1b5 (beta) 9/25/00
+ More changes to bounding box calculation: Everything was correct
+ except for the top-level page offsets, which were calculated from
+ the bounding box excluding schematic pins and info labels. Thanks
+ to Albert Ma <ama@cag.lcs.mit.edu> for pointing this out.
+
+163) v2.1b4 (beta) 9/22/00
+ Added menu option to read a script, which has the same
+ functionality as the .xcircuitrc script (see #160, below). Added
+ "enable toolbar" and "enable xschema" to the command-line parser.
+
+162) v2.1b3 (beta) 8/7/00
+ Changes to fix problems caused by (158) below; the toolbar widget
+ has finally been arranged to use multiple columns when there is
+ not enough room for one.
+
+161) v2.1b2 (beta) 8/4/00
+ Added a "auto-fit" feature to automatically scale the drawing to
+ fit the output page. Also improved the behavior of the text-edit
+ widget to delete a selection if it exists in lieu of deleting a
+ character.
+
+160) v2.1b2 (beta) 8/3/00
+ Added a command-line window which accepts the same commands as
+ the .xcircuitrc file. This syntax will be expanded in the near
+ future. Added text hints to the toolbar buttons. Added a
+ user-definable bounding-box capability, and fixed the automatic
+ bounding-box calculation to include spacing between pins and
+ their text.
+
+159) v2.1b1 (beta) 8/1/00
+ Added a temporary file saving feature for recovery from crashes,
+ sudden power-downs, or emergency exit. Added a Control-C handler
+ to execute graceful exits from a hung state. Temporary files are
+ doubly-protected by duplication before writing, so crashes during
+ writes will not cause the (previous) backup to be lost.
+
+158) v2.1b1 (beta) 7/31/00
+ Minor changes for compilation using HP/UX's ANSI-C compiler; one
+ major fix preventing loadlibrary() from calling composelib()
+ with argument FONTLIB (composefontlib() should be used for that).
+ Updated version number to 2.1 after Graham Murphy pointed out
+ that xcircuit-2.0a11 crashes when reading 2.0b4 input:
+ incompatibility is due to the reformatted label statement.
+ Added warning if file version is greater than executable version.
+
+Version 2.0b (October 1999 to July 2000)
+----------------------------------------------------------------------
+157) v2.0b4 (beta) 7/18/00
+ Corrected the partial-text-selection algorithm; new algorithm
+ makes an insideness test between each string character and the
+ select box.
+
+156) v2.0b4 (beta) 6/28/00
+ Corrected and enhanced the routine printing the cursor position
+ and other information to the top of the window.
+
+155) v2.0b4 (beta) 2/25/00
+ Finished implementing ghostscript-rendered backgrounds. Added
+ a toolbar widget for easy access to common commands; this
+ implementation is not yet complete.
+
+154) v2.0b3 (beta) 2/13/00
+ More bug fixes, covering several bugs which were introduced
+ with the 2.0b series: bbox calculation after copy & move
+ across pages, segmentation fault when using middle mouse button
+ to finish a text label, double-printing of non-ASCII characters
+ in the output, confusion of grid and snap space functions from
+ the menu, and incorrect path starting position saved when 1st
+ path component is a spline or arc.
+
+153) v2.0b3 (beta) 2/8/00
+ Testing preliminary support for Ghostscript-rendered backgrounds.
+ Bugfix to multiple library code (fatal error---adding new library
+ writes over current user library). Another bugfix---objcompare
+ was not being called.
+
+152) v2.0b3 (beta) 1/26/00
+ Further implementation of multiple libraries, including loading,
+ appending, and saving; specifying library pages from the rc
+ file and the library file (specifically, "builtins.lps"), and
+ a menu item for creating new library pages. Currently there
+ is no way to move objects from one library page to any other
+ than the "User Library" (always defined as the last library
+ page), which is also true for object creation using "M" or
+ "Make Object".
+
+151) v2.0b3 (beta) 1/13/00
+ Fixed behavior of rotate and flip when acting on groups and
+ extended behavior of both to cover all elements. Fixed a bug
+ in text select. Added a library-list page to enable multiple
+ libraries. Fixed bounding box calculations so that the bounding
+ box updates on every element change, and that update is reflected
+ in the page directory, libraries, and library directory as
+ required.
+
+150) v2.0b2 (beta) 1/10/00
+ More changes: Added a page-list page to enable page reordering.
+ Structural changes: Put page parameters into separate structure
+ and viewscale and pcorner parameters into the object structure.
+ Now every object retains its zoom scale and position where last
+ edited. Also: some attempt to keep all/only variables required
+ by the top-level window in "areastruct", so later it will be
+ possible to implement multiple windows. Also some bug fixes and
+ other cleanups to the code, particularly the window/object
+ resizing and centering.
+
+149) v2.0b2 (beta) 1/5/00
+ Numerous minor bug fixes, including automatic loading of derived
+ fonts (previously handled incorrectly), proper drawing during
+ scrollbar drags, and many fixes to the schematic capture system.
+ Symbol-Schematic association redone so that the symbol and
+ schematic do not have to have the same name. Because this code
+ is beta, this feature will not be backwardly compatible with
+ previous versions.
+
+148) v2.0b1 (beta) 11/2/99
+ Changes to the Imakefile from Monte Bateman fix the reported
+ problems with both the RPM creation, and with the make process
+ not generating the proper subdirectories/installing files.
+ Changes to the RPM spec file go along with these fixes.
+ Support added for parameterized objects (full support for
+ string parameters, partial implementation of integer
+ parameters).
+
+Version 2.0a (July 1998 to November 1999)
+----------------------------------------------------------------------
+147) v2.0a11 (alpha) 11/19/99
+ Thanks to Mathieu Clar (mclar@ulg.ac.be) for finding that fix
+ #144 can be overridden if environment variable LANG is set
+ (e.g., to "french") and results in the same kind of program
+ crash. Now xcircuit sets LANG to "POSIX" internally.
+
+146) v2.0a11 (alpha) 10/26/99
+ After a number of partial fixes, and with the help of Raymond
+ Burns (rayburns@eskimo.com), I fixed the keyboard input focus
+ problem which plagued, especially, the WindowMaker window
+ manager. Neverthess, this problem refuses to go away, and
+ this appears not yet to be the end of the story.
+
+145) v2.0a10 (alpha) 6/25/99
+ Changed behavior of wire drawing so that mouse button 3 deletes
+ only the last segment of the line rather than deleting the
+ whole line. Added key macro "." to place a dot object or draw
+ a dot at the cursor position.
+
+144) v2.0a10 (alpha) 6/16/99
+ Fixed a problem under non-US UNIX versions in which LC_NUMERIC
+ is set to use a comma character as a numeric decimal point.
+ Thanks to Lars Pettersson <larsp@oso.chalmers.se> and Paulo
+ Mario dos Santos Dias de Moraes <paulo.mario@omninet.com.br>
+ for helping to track down the problem (6/24/99---changed from
+ LC_NUMERIC to LC_ALL because there are apparently other things
+ which also screw up file loads if not set to US or equivalent).
+
+143) v2.0a10 (alpha) 6/14/99
+ Added ISO-Latin5 (Turkish) on request from Recai Oktas at
+ Ondokuz Mayis University <roktas@samsun.omu.edu.tr>. Rewrote
+ source to allow future inclusion of all ISO-LatinX encodings.
+
+142) v2.0a10 (alpha) 5/25/99
+ Finally got around to instantiating edit mode for paths.
+
+141) v2.0a10 (alpha) 5/24/99
+ In text edit modes, the backslash character brings up a
+ page containing the font encoding, allowing entry of non-
+ printing characters by simple point-and-click. Use of
+ backslash escape sequences is deprecated. Also, fixed a
+ bug which prevented compilation if MAKE_LGF was not defined
+ in the Imakefile; thanks to Zhengdao Wang for the bug fix
+ <zhengdao@aphrodite.ee.umn.edu>.
+
+140) v2.0a9 (alpha) 5/20/99
+ Finally fixed the "actions not found" bug, which seems to
+ be due to conflicting names of widget classes between Xaw
+ and Xw, and changed the popup menu behavior to place the
+ popup menu such that the cursor is initially on the title,
+ not on the top button. Also, added a README.ISOLatin2 file
+ giving instructions on how to setup xcircuit for Latin2
+ encoded output.
+
+139) v2.0a9 (alpha) 5/17/99
+ Changed menu button calling to the style adopted for
+ the abandoned attempt at using Motif; this style calls
+ each menubutton by its Widget address rather than explicitly
+ referring to the path created by panes, managers, etc., which
+ can be toolkit-dependent.
+
+138) v2.0a9 (alpha) 5/12/99
+ Added font vectors for ISO-Latin2 encoding. Also, reparied
+ two fatal bugs (one involving the backslash character in
+ text, the other involving large user library files), and
+ reintroduced fix number 117 which somehow got lost.
+
+137) v2.0a9 (alpha) 5/1/99
+ Font-drawing mechanism completely overhauled and replaced
+ with object-encoded fonts. Added font encoding selection
+ and a better interface for choosing font family, shape,
+ and encoding. Added PostScript output for generating
+ ISOLatin1 encodings of standard PostScript fonts. Fonts
+ extended and heavily revised; Courier, Helvetica, Times,
+ and Symbol all have unique font vectors.
+
+136) v2.0a8 (alpha) 5/6/99
+ Zoltan Csahok <csahok@phase4.ujf-grenoble.fr> sent a bug fix
+ for the problem in which some objects would be made "hidden"
+ without being declared hidden in the library.
+
+135) v2.0a8 (alpha) 4/14/99
+ Paul Ortyl <ortylp@key.net.pl> sent a fix to allow keyboard
+ entry of 8-bit characters (e.g., ISO-Latin1 or ISO-Latin2
+ encoding). Text vectors still reflect Adobe Standard
+ encoding but hopefully this will be extended in the near
+ future. Added "W" key macro for popping up Write-Xcircuit
+ dialog, at Paul's request.
+
+134) v2.0a8 (alpha) 2/25/99
+ Possibly just fixed the problematic window manager hints
+ (WMHints) bug which has been plaguing the system.
+
+133) v2.0a7 (alpha) 1/26/99
+ Fixed a bug which was introduced into version 2.0a7 which
+ prevents landscape-oriented files from being loaded back into
+ xcircuit.
+
+132) v2.0a7 (alpha) 12/18/98
+ Fixed a problem wherein the FileList and Help widgets set
+ their own fonts directly rather than getting them from the
+ X Resource manager. This causes XCircuit to crash when the
+ computer does not have that particular font preinstalled, as
+ noted by Niitsu Yoichiro <niitsu@amc.toshiba.co.jp>.
+
+131) v2.0a7 (alpha) 11/20/98
+ Fixed a long-standing bug by making gridspace and snapspace
+ per-page variables, and permitting loading and saving these
+ values in the output file. At the same time, made these
+ values type float for better resolution (preliminary to
+ making all internal point values type float).
+
+130) v2.0a7 (alpha) 11/19/98
+ Added the "zoom-out" box suggested by ():
+ the current area of the drawing window is made to fit into
+ the area bounded by the box. Added a button to the little
+ square at the intersection of the horizontal and vertical
+ scrollbars which acts like the "zoom view" function or "v"
+ key macro.
+
+129) v2.0a7 (alpha) 11/17/98
+ Changed the behavior of the horizontal and vertical scrollbars
+ so that some smooth scrolling is possible (that which can be
+ accomplished by copying from the existing pixmap onto the
+ window, without redrawing the whole window).
+
+128) v2.0a6 (alpha) 11/16/98
+ Made some fixes for Dale Scheetz <dwarf@polaris.net> to correct
+ some odd behavior under Linux: The help page has been shortened
+ by 30 pixels to clear the Windows-95-like menu bar in fvwm95, and
+ the "done" button has been moved to the top of the help window.
+ Also, reduced argv[0] (the command from the command line) to its
+ root before comparing to "xschema" and loading Xdefaults so that
+ the program isn't confused by an appended pathname.
+
+127) v2.0a6 (alpha) 11/12/98
+ Added code suggested by Alireza Moini <moini@eleceng.adelaide.edu.au>
+ to use environment variable "XCIRCUIT_LIB_DIR" for searching for
+ libraries before trying the hard-coded BUILTINS_DIR as a last
+ resort.
+
+126) v2.0a6 (alpha) 10/4/98
+ Cleaned up the code a little; moved most of the menu button
+ callbacks into a single file "menucalls.c", moved the file
+ list widget code into "filelist.c", and moved the help window
+ code into "help.c".
+
+125) v2.0a6 (alpha) 10/4/98
+ Fixed a long-standing problem with the simple help window in
+ which it could not be repositioned. In addition, I prevented
+ the window from exceeding the computer screen boundary; when
+ it does, the help window is truncated but can be "scrolled"
+ in a simple sense by clicking the mouse in the help text
+ window.
+
+124) v2.0a5 (alpha) 9/27/98
+ Fixed a problem apparently due to the above pixmap icon code
+ which caused window managers to lose input focus for the whole
+ xcircuit window. This appears to be fixed at least for "i386"
+ Linux systems.
+
+123) v2.0a4 (alpha) 9/1/98
+ Upon urging of Michael Le, I generated a built-in pixmap icon.
+ Also fixed what was apparently a long-standing bug in resizearea().
+
+122) v2.0a3 (alpha) 8/23/98
+ Fixed a bug pointed out by Geert Jordaens which limited library
+ object names to 20 characters on file input. Added flip-invariant
+ text. Added pad space to pin labels. Began preliminary work on
+ support for parameterized objects (beginning with some example
+ code and a postscript prolog). Added missing definitions for
+ quarter and half space to xcircps2.pro. Changed library files
+ to take advantage of flip invariant text.
+
+121) v2.0a2 (alpha) 8/11/98
+ More "load file" fixing: Modified the file loading routine so that
+ library files can be loaded with "Read Xcircuit PS"; i.e., they are
+ read like normal postscript files, and so can be read on the command
+ line. Only restriction is that they go into the user library, as
+ they would if read as part of a regular xcircuit postscript file.
+
+120) v2.0a2 (alpha) 8/10/98
+ Fixed three LGF-related errors: 1) LGF files were imported whether
+ "read" or "import" was selected, 2) labels needed to set property
+ "pin", and 3) one of the connections in the definition for "TO"
+ in lgf.lps needed to be moved.
+
+119) v2.0a1 (alpha) 7/17/98
+ Fixed some errors in setting filename and object name when loading
+ or attempting to load files. Fixed netlist error for connecting
+ multiple instances of the same label on a page. Got rid of
+ string-sharing behavior for labels and malloc'd each copy instead.
+
+118) v2.0a0 (alpha) 7/10/98
+ Replaced Xcircuit version 1.7 with version 2.0, schematic capture
+ system included. Instantiating better management for version
+ numbers, starting right here!
+
+Version 1.6 (January 1998 to May 1998)
+----------------------------------------------------------------------
+May 1998
+
+117) A few bugfixes and additions courtesy of Jo"rg Wunsch, including
+ the addition of handling WM_DELETE_WINDOW client messages to
+ allow the program to be closed by window manager controls.
+
+116) Bug fixes from Paul Slootman for the 64-bit Alpha platform.
+
+115) David DiGiacomo pointed out that the problem with the "make"
+ halting under Solaris is the indeterminate exit status returned
+ by the menudep program. This has been fixed.
+
+April 1998
+
+114) Backspace can no longer be typed from the keyboard; instead,
+ the keyboard Backspace acts like Delete, and a Backspace
+ character can be inserted from the "Text" menu.
+
+March 1998
+
+113) Fixed a bug found by Cliff Koch <koch@cig.mot.com> in which
+ xcircuit did not check if an object name consists entirely of
+ numerals, which screws up the PostScript interpreter, which
+ tries to treat it as an integer.
+112) Fixed a bug found by Dale Scheetz <dwarf@polaris.net> in which
+ a divide by zero would occur if a directory list was longer than
+ the pixel height of the file read window.
+111) Fixed the colormap problem by figuring out how to get XCircuit
+ to gracefully install its own colormap on startup if the default
+ map is full.
+
+February 1998
+
+110) Cleaned up the last typecasting problems in both the toplevel
+ directory and Xw; now should compile cleanly on all platforms
+ without specifically setting CCOPTIONS and CDEBUGFLAGS in the
+ Imakefile.
+109) Changed the file loading routine so that Xcircuit automatically
+ figures out whether the file is a PostScript or LGF file, so
+ that there are no longer two separate "load" commands in the
+ File menu.
+108) Added a number of "diglog" gates to the lgf.lps library; fixed
+ a bug reported by Jean-Luc Margot in which Imakefile refuses
+ to create the lib directory.
+107) Fixed more problems with the inch/cm conversion, bugs reported
+ by Uwe Steinmann. Made all displays report in cm when in cm
+ gridstyle mode. Also made the full page switch from letter
+ size to A4 size when switching between inch and cm grids.
+
+January 1998
+
+106) Cleaned up typecasting problems which produced compile-time
+ warnings. Added "integral" sign to the alphabet vectors and
+ revised the signal.lps library to include it.
+105) Fixed longstanding bug in which the library (M)ove command would
+ overwrite an object with another.
+104) Fixed another bug found by Monte Bateman in which the system
+ crashed when one tried to delete an object which had a dependency
+ somewhere.
+103) Fixed a bug found by Monte Bateman which was that the alternate
+ color scheme flag did not toggle if the alternate color set was
+ chosen from the .xcircuitrc file, and in which the catalog objects
+ did not invert color and so became black-on-black or white-on-white.
+ All catalog objects now have color DEFAULTCOLOR instead of color
+ FOREGROUND, which makes more sense anyway.
+
+Version 1.5 (May 1997 to December 1997)
+----------------------------------------------------------------------
+
+December 1997
+
+102) Added a copyright "artistic license". Changed filename
+ of distribution tarfile to contain the version number
+ (xcircuit-6.1.tar.gz). Began posting xcircuit to
+ sunsite.unc.edu.
+
+November 1997
+
+101) Fixed a bug found by Mark Cohen in which xcircuit loses track of
+ the drawing area-to-window coordinate transformation whenever the
+ window is resized.
+
+October 1997
+
+100) Fixed a long-standing problem with rhomboid-edit style for
+ polygons. The edit points can no longer spontaneously change
+ during editing; they are fixed when the editing begins. Added
+ a "Rhomboid-A" style, which is similar to Manhattan style.
+99) Used a global variable to keep track of which element is being
+ edited so that it is unnecessary to swap elements to the end of
+ the list in order to edit them.
+98) Fixed "bug" to make RHOMBOID edit like NORMAL edit when there are
+ only 2 points in the line (otherwise the second point gets dragged
+ along with the first).
+97) Added capability to "hide" objects if the name of the object ends
+ with an ampersand ('&').
+96) Added override of default colors and addition of new colors to the
+ .xcircuitrc file definition.
+95) Changed all color entries from type "short" to type "int" to allow
+ xcircuit to run on 16- and 24-bit TrueColor visuals.
+
+August 1997
+
+94) Added "setmiterlimit" command to xcircps.pro to supress odd glitches
+ in some renderers (gs and certain printers) when drawing paths. Do
+ these devices not have the (stated) default value of 10?
+93) Finished adding color. Added "scb" and "sce" (select-color-begin
+ and -end) to PS profile. "Opaque-stipple" style no longer selects
+ "setgray" in postscript; gray is selected by choosing the color
+ gray. Added "Inherited" color to list & based color scheme on the
+ idea of "color inheritence".
+92) Began adding color; separated definitions for color and stipple
+ patterns, and set default color scheme to black-on-white. Added
+ stippled and colored rectangles to the Xw MenuBtn options for
+ menu buttons.
+
+July 1997:
+
+91) Added path horizontal and vertical flipping; fixed a long-standing
+ bug to let user cancel a "make object" command during the object
+ name popup prompt.
+90) Stopped linking the filename to the page (object) name.
+89) Enabled creation of paths through the use of the "join" function,
+ and the ability to deconstruct the path into its constituent parts
+ with the "unjoin" (keystroke "J") function.
+88) Implemented paths (currently no editing capability).
+87) Redesigned the edit and element creation modes to be consistent
+ between polygons, arcs, and splines. Arcs and splines can be
+ edited when created by using mouse button 1 to cycle between
+ control points.
+86) Finished implementation of the revised "attach" command, including
+ attachment to ellipses and to the chord on a closed arc.
+85) Finished implementation of ellipses.
+84) Implemented a dual color scheme which is switchable from the menu;
+ no longer need XCircuit.ad.alt. This is preliminary to adding full
+ color.
+
+
+May 1997:
+
+83) Preliminary implementation of ellipses. On the top level, ellipses
+ are constrained to the x-y axes, but can be rotated as part of an
+ object.
+82) Changed the "attach" command to operate on *all* elements, so,
+ e.g., a polygon end can be forcibly attached to a circle perimeter,
+ and so forth. Needs a little refining, plus effects should be
+ duplicated for edit mode in "trackpoly", "trackarc", and
+ "trackspline".
+81) Finished implementing rotate and flip for all element types.
+80) Implemented optional graphics double-buffering for very clean and
+ quick refreshing of graphics.
+79) Changed lists of elements from separate list for each element to
+ one list of type (genericptr *), which is re-typecast to each
+ element type. Makes a number of things much cleaner
+78) Got rid of type WIRE altogether; only has polygons. No more "J"
+ command for unjoin, but "j" joins polygons together and the
+ algorithm is much cleaner than before and shouldn't be error-prone.
+77) Gave arcs a line-segment representation, thus fixing the problem
+ of filled arcs and paving the way for the "path" aggregate element.
+
+Version 1.4 (August 1995 to March 1997)
+----------------------------------------------------------------------
+
+March 1997:
+
+76) Made the scaling slightly more restrictive, to prevent xcircuit
+ from exceeding bounds of type short int either in the window or
+ in the page coordinate system.
+75) Prevented drawing objects and labels outside of the window area
+ in order to speed up rendering at close scales.
+74) Better precision for Bezier curve rendering and object attachment.
+73) Changed rendering to a stacked transformation matrix model.
+ Speeds up rendering, makes rendering more accurate, and cuts
+ down on code complexity.
+72) Added Fixed-Width (Courier) font, made proper widths for both
+ Times and Helvetica fonts; implemented some different
+ characters for each font.
+71) Allow change of font, style, and justification for one or more
+ selected labels. Now deselects labels and arc/poly/spline after
+ a style change.
+70) Menu entries for text font, style and arc/poly/spline style change
+ to reflect the status of the currently selected element.
+69) Colormap allocation problem fixed by new CvtStringToPixel() routine
+ which searches colormap for best approximation to color on a failed
+ color allocation.
+68) Wrote program to automatically generate the pathnames for button
+ and cascade widgets in the pulldown menus.
+67) Added polygon flip capability.
+
+February 1997:
+
+66) Expanded file selection widget to select and load multiple files,
+ also to load (single or multiple) library .lps and analog .lgf files.
+65) Added a file selection widget to the popup prompt when selecting
+ a file to read.
+64) Changed structure "select" to "selection" in order to get around
+ problem compiling under Solaris.
+
+January 1997:
+
+63) Added an output page width and height per xcircuit page instead
+ of the default 8.5" x 11" page that existed previously. Output
+ continues to be centered on the page.
+62) Separated file names and page names. These are linked by default,
+ but can be separated by supplying a different page name, or by
+ having a multi-page output.
+
+December 1996:
+
+61) Added inch/cm reporting for keyboard-adjusted snap spacing.
+
+November 1996:
+
+60) Fixed minor bugs in the DSC-PostScript: %%PageTrailer statement
+ is not needed, and %%Trailer *must* come after all page commands
+ including the "showpage". Only the XCIRCsave restore statement
+ should be between %%Trailer and %%EOF.
+59) Output scale changed to default of 1.0, with the arbitrary
+ pixel-to-PostScript-units constants bansished to the
+ PostScript prologue.
+58) Changed grid and snap spacing routines to display inches/cm
+ instead of pixel coordinates. Pixel coordinates are now
+ entirely hidden from the user, who only sees things in
+ inches or centimeters (with a default of inches, reported
+ in fractions).
+57) Position display now gives length of simple wires in addition
+ to the cursor position.
+56) Modified routine to print coordinates in fractional inches,
+ to be able to generate a fraction from an arbitrary float.
+
+October 1996:
+
+55) Added code to prevent infinite recursion by attempting
+ to place an object within itself.
+54) Revised .lgf-file reading for an exact 1:1 correspondence
+ of lgf names to the xcircuit library object names; made
+ a library "lgf.lps" to cover the main analog gates, with
+ some stylistic changes to the look of some of the gates.
+53) Added capability to move objects around inside the
+ libraries.
+52) Added capability to make a copy of an object from
+ either library page into the user library.
+51) Added capability to delete objects from the library.
+
+September 1996:
+
+50) Cleaned up the Xw code so that it will compile on
+ not-so-forgiving compilers; also pruned out a
+ few things that are not used by Xcircuit.
+49) Finally wrote the routine to compare objects and
+ avoid name conflicts.
+48) Made PostScript output DSC-compliant, made file
+ reading more robust to errors in the input file.
+47) Started implementing library manipulation routines
+ with library object rename; also added keystroke
+ "c" from library mode for "copy".
+46) Fixed some problems with catalog organization of
+ objects.
+45) Added multiple page loads and saves: pages with
+ the same name will be grouped together into one
+ file. EPS is not an option for multiple pages.
+44) Made pages reallocatable, and added "Goto Page"
+ option in menu for accessing page numbers > 10.
+ New pages are automatically added to the pull-down
+ menu. Page names are the same as the object name.
+43) Changed format of file ".xcircuitrc" and added
+ ability to load libraries, override the default
+ library load, load extra fonts, and set certain
+ variables.
+42) Added ability to load an arbitrary number of
+ user-defined fonts. New fonts are automatically
+ added to the pull-down Font menu.
+41) Changed embedded commands in text string to two bytes
+ each, allowing future extension of embedded commands.
+40) Added handling of Ctrl-A and Ctrl-E for moving
+ to beginning and end of text, respectively
+
+August 1996:
+
+39) Added reading of ".xcircuitrc" in user's home
+ directory as an additional library file (file
+ takes same form as xcircuit or library files).
+38) String text appears in message window immediately
+ upon starting or editing a label, and disappears
+ when done.
+37) Fixed bugs in labels: Rewrote routines so all
+ labels start with a font-change specifier;
+ removed "fontset" command from PostScript profile.
+
+February 1996:
+
+36) Differentiate between Writing and Overwriting
+ a file (to prevent disasters!) and warn user
+ when file is about to be overwritten.
+35) Made all spline routines relative to SPLINESEGS
+ and increased default SPLINESEGS to 20
+
+January 1996:
+
+34) Allow push and pop while an object or objects
+ are selected and being dragged.
+33) Added Rhomboid box editing in addition to
+ Manhattan box edit.
+32) Added arrow-attachment routine to align arrows
+ with an underlying wire/polygon/spline/arc while
+ dragging.
+31) Changed selection mechanism (again) to a simple
+ cartesian measure of distance from a line to
+ the cursor position.
+30) Added capability to flip, rotate, and snap-to
+ while an object is selected and being dragged.
+
+August 1995:
+
+29) Added vertical flipping capability using macro "F".
+28) Added extended character set capability;
+ both octal codes and LaTeX-like symbol names
+ can be entered at the text prompt after a
+ backslash.
+27) Added lines to show spline control points and
+ arc center during creation and editing.
+26) Moved to PostScript prologue version 1.5, for
+ which the order of parameters for polygon, arc,
+ and spline are rearranged and made similar to
+ each other. Reading of v1.4 files is kept for
+ backward compatibility.
+25) Added rudimentary opaque-fill style for polygons,
+ arcs, and splines. "Vertical" alignment can only
+ be controlled on the object level, using the X
+ command (exchange).
+24) Added "Manhattan Box Edit" style (default: ON)
+ such that right angles in polygons are maintained
+ during editing.
+
+Version 1.3 (March 1995 to June 1995)
+----------------------------------------------------------------------
+
+May/June 1995:
+
+23) Added backspace character handling in text.
+22) One-step keystroke for dotted/dashed/solid line.
+21) Allowed "join wires" to join wires and polygons.
+20) Allowed "styles" options to operate on wires
+ by automatically converting them to polygons.
+19) Fixed bug in which Xw copy buffer overflowed
+ string in sprintf() [solution: restrict
+ "precision" of string thus: "%.149s"].
+18) Added "edit (e)" command to menu.
+17) Added capability to read Caltech tools' "analog"
+ .lgf format files.
+
+March 1995:
+
+16) Added feature to report non-printing characters
+ in a label, when editing.
+15) Added Zoom Box function.
+14) Changed copy behavior to allow multiple copies
+ when button1 is used, and a single copy when
+ button2 is used.
+13) Fixed problems with pixel trash left behind by
+ text editing.
+12) Beeps when it doesn't write file due to filename
+ problem.
+11) Added countdown for multiple selections.
+10) Added new cursor for edit mode.
+9) Xcircuit *only* does auto delete/addition of the
+ extension if extension is ".ps". All other
+ filename extensions are left alone.
+8) Changed behavior so that request to load a file
+ which does not exist will change the current
+ file name, provided that current page is empty.
+7) Changed library pages to be actual objects, made
+ routine "composelib" to arrange the library objects
+ based on height and width of each object, changed
+ names of objects to xcircuit labels.
+6) Fixed numerous malloc() bugs.
+5) Added function to import xcircuit files into the
+ current file as well as loading them into a page
+ with page reset.
+4) Added ability to change coordinate grid and
+ report coordinates in inches (decimal and
+ fractional) and centimeters as well as the usual
+ pixel grid.
+3) Added (simple) help screen
+2) Added simple scrollbars on side and bottom, allowing
+ click-to-pan. Added global variables to save current
+ GC state and foreground color.
+1) Added 2 message widgets, one for name of file
+ to edit, one for coordinates, one for information
+
+----------------------------------------------------------------------
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..823c615
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,293 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+---------------------------------------------------------------------
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+---------------------------------------------------------------------
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+---------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+---------------------------------------------------------------------
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+---------------------------------------------------------------------
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+---------------------------------------------------------------------
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..0dd2053
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,286 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign no-dependencies no-dist
+
+# Additional files to distribute
+EXTRA_DIST = COPYRIGHT README README.ISOLatin2 README.notes
+
+SUBDIRS = @SUBDIRS@
+VERSION = @VERSION@
+REVISION = @REVISION@
+FULL_VERSION = @VERSION@.@REVISION@
+
+# Override standard "make" target when compiling under TCL
+ALL_TARGET = @ALL_TARGET@
+INSTALL_TARGET = @INSTALL_TARGET@
+
+# Menudep program generates menudep.h needed by some of the
+# source files for Xcircuit
+noinst_PROGRAMS = menudep$(EXEEXT)
+
+menudep$(EXEEXT): menudep.o
+ $(CC) -o $@ menudep.o
+
+menudep.h: menudep$(EXEEXT)
+ ./menudep$(EXEEXT)
+
+xcwrap.o: xcwrap.c menudep.h
+ $(CC) ${CPPFLAGS} ${CFLAGS} ${DEFS} $(PATHNAMES) $(INCLUDES) \
+ xcwrap.c -c -o xcwrap.o
+
+lib/tcl/xcircuit${SHDLIB_EXT}: xcwrap.o ${xcircuit_OBJECTS} ${xcircuit_DEPEND}
+ $(RM) lib/xcircuit${SHDLIB_EXT}
+ $(CC) ${CFLAGS} ${SHLIB_CFLAGS} -o $@ ${LDDL_FLAGS} xcwrap.o \
+ ${xcircuit_OBJECTS} ${xcircuit_LDADD} ${SHLIB_LIB_SPECS} \
+ ${LDFLAGS} ${X_EXTRA_LIBS} ${EXTRA_LIBS} -lc ${LIBS} \
+ ${LIB_SPECS} ${EXTRA_LIB_SPECS}
+
+xcircexec$(EXEEXT): xcircexec.o
+ $(RM) ./xcircexec$(EXEEXT)
+ $(CC) ${CFLAGS} ${CPPFLAGS} ${DEFS} $(PATHNAMES) $(INCLUDES) \
+ xcircexec.c -o xcircexec$(EXEEXT) ${LIB_SPECS} \
+ ${LD_RUN_PATH} ${LDFLAGS} ${LIBS} ${EXTRA_LIB_SPECS}
+
+tcl:
+ @echo Making tcl library object
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (echo "Making tcl in $$subdir"; \
+ cd $$subdir && $(MAKE) $(AM_MAKEFLAGS)) \
+ done
+ $(MAKE) lib/tcl/xcircuit${SHDLIB_EXT}
+ $(MAKE) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(MAKE) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ $(MAKE) xcircexec$(EXEEXT)
+
+# Automake files
+ac_aux_dir = dist
+
+# Requirements for Xcircuit
+bin_PROGRAMS = xcircuit
+
+# Temporary directory (if not overridden by environment variable TMPDIR)
+tmpdir = /tmp
+
+# Directories for app-defaults file and manual page
+appdefaultsdir = $(libdir)/$(PACKAGE)-$(VERSION)/app-defaults
+appmandir = $(libdir)/$(PACKAGE)-$(VERSION)/man
+
+PATHNAMES = -DPROG_VERSION=$(VERSION) \
+ -DPROG_REVISION=$(REVISION) \
+ -DCAD_DIR=\"$(libdir)\" \
+ -DTEMP_DIR=\"$(tmpdir)\" \
+ -DRESOURCES_DIR=\"$(appdefaultsdir)\" \
+ -DSCRIPTS_DIR=\"$(scriptsdir)\" \
+ -DBUILTINS_DIR=\"$(librarydir)\" \
+ -DBUILTINS_FILE=\"$(BUILTINS_FILE)\" \
+ -DUSER_RC_FILE=\"$(USER_RC_FILE)\" \
+ -DPROLOGUE_DIR=\"$(librarydir)\" \
+ -DPROLOGUE_FILE=\"$(PROLOGUE_FILE)\" \
+ -DSTARTUP_FILE=\"$(STARTUP_FILE)\" \
+ -DLGF_LIB=\"$(LGF_LIB)\" \
+ -DASG_SPICE_LIB=\"$(ASG_SPICE_LIB)\"
+
+xcircuit_SOURCES = elements.c events.c filelist.c files.c \
+ flate.c fontfile.c formats.c functions.c graphic.c \
+ help.c keybindings.c libraries.c menucalls.c \
+ netlist.c ngspice.c opengl.c parameter.c python.c \
+ rcfile.c render.c schema.c selection.c svg.c text.c undo.c \
+ tclxcircuit.c tkSimple.c xcircuit.c xtfuncs.c xtgui.c
+
+xcircuit_DEPEND = @SUBLIB@
+xcircuit_LDADD = @SUBLIB@ @STDLIBS@
+
+help.c: menudep.h
+menucalls.c: menudep.h
+rcfile.c: menudep.h
+schema.c: menudep.h
+xcircuit.c: menudep.h
+parameter.c: menudep.h
+python.c: menudep.h
+tclxcircuit.c: menudep.h
+xtgui.c: menudep.h
+xtfuncs.c: menudep.h
+
+# Man page
+M4_DEFS = @M4_DEFS@ @DEFS@
+man_MANS = lib/xcircuit.1
+
+# Main compiler arguments
+DEFS = @DEFS@ $(PATHNAMES)
+INCLUDES = -IXw ${INC_SPECS}
+SHDLIB_EXT = @SHDLIB_EXT@
+LDDL_FLAGS = @LDDL_FLAGS@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+LDFLAGS = @LDFLAGS@
+EXTRA_LIB_SPECS = @EXTRA_LIB_SPECS@
+TCL_LIB_DIR = @TCL_LIB_DIR@
+WISH_EXE = @WISH_EXE@
+INTERPRETER = @INTERPRETER@
+
+# Library directory and files
+librarydir = $(libdir)/$(PACKAGE)-$(VERSION)
+scriptsdir = $(libdir)/$(PACKAGE)-$(VERSION)
+USER_RC_FILE = .xcircuitrc
+PROLOGUE_FILE = xcircps2.pro
+LGF_LIB = lgf.lps
+ASG_SPICE_LIB = asg_spice.lps
+SIGNAL_LIB = signal.lps
+MUSIC_LIB = musiclib.lps
+STARTUP_FILE = @STARTUP_FILE@
+INTERP_PATH = @INTERP_PATH@
+
+FONTS_LPS = courier courieriso2 courieriso5 helvetica helveticaiso2 \
+ helveticaiso5 myfont symbol times_roman times_romaniso2 \
+ times_romaniso5
+FONTS_XFE = courier courieriso courieriso2 courieriso5 helvetica \
+ helveticaiso helveticaiso2 helveticaiso5 myfont symbol \
+ times_roman times_romaniso times_romaniso2 times_romaniso5
+SCRIPTS_PY = spice gettext pagebbox
+
+WRAPPER_INIT = xcircuit.tcl
+WRAPPER_OBJ = xcircuit${SHDLIB_EXT}
+WRAPPER_SO = xcircuit.so
+WRAPPER_SH = xcircuit.sh
+CONSOLE = tkcon.tcl
+CONSOLE_SCRIPT = console.tcl
+
+lib/$(INTERP_PATH)/$(WRAPPER_SH): lib/$(INTERP_PATH)/$(WRAPPER_SH).in
+ sed -e '/XCLIBDIR/s#XCLIBDIR#$(librarydir)#' \
+ -e '/WRAPPER_INIT/s/WRAPPER_INIT/$(WRAPPER_INIT)/' \
+ -e '/CONSOLE_SCRIPT/s/CONSOLE_SCRIPT/$(CONSOLE_SCRIPT)/' \
+ -e '/CONSOLE/s/CONSOLE/$(CONSOLE)/' \
+ -e '/PROG_VERSION/s/PROG_VERSION/$(VERSION)/' \
+ -e '/PROG_REVISION/s/PROG_REVISION/$(REVISION)/' \
+ -e '/TCLLIBDIR/s#TCLLIBDIR#$(TCL_LIB_DIR)#' \
+ -e '/WISH_EXE/s#WISH_EXE#$(WISH_EXE)#' \
+ lib/$(INTERP_PATH)/$(WRAPPER_SH).in > $@
+ chmod 0755 $@
+
+lib/$(INTERP_PATH)/$(WRAPPER_INIT): lib/$(INTERP_PATH)/$(WRAPPER_INIT).in
+ sed -e '/LIBDIR/s#LIBDIR#$(librarydir)#' \
+ -e '/SCRIPTSDIR/s#SCRIPTSDIR#$(scriptsdir)#' \
+ lib/$(INTERP_PATH)/$(WRAPPER_INIT).in > $@
+ chmod 0755 $@
+
+lib/xcircuit.1: lib/xcircuit.1.in
+ sed -e '/LIBDIR/s#LIBDIR#$(libdir)#' \
+ -e "/^${HAVE_LGF}/s/^${HAVE_LGF} //" \
+ -e "/^${INTERPRETER}/s/^${INTERPRETER} //" \
+ -e '/^PYTHON /d' \
+ -e '/^TCL /d' \
+ -e '/^LGF /d' \
+ -e '/^NOINTERP /d' \
+ lib/xcircuit.1.in > $@
+
+install-data-local: lib/xcircuit.1
+ @echo "Installing app-defaults file"
+ $(mkinstalldirs) $(DESTDIR)$(appdefaultsdir)
+ $(mkinstalldirs) $(DESTDIR)$(appmandir)
+ $(INSTALL_DATA) lib/XCircuit.ad $(DESTDIR)$(appdefaultsdir)/XCircuit
+ $(INSTALL_DATA) lib/xcircuit.1 $(DESTDIR)$(appmandir)/xcircuit.1
+ @echo "Installing library and netlist files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ ( cd lib ; for i in $(PROLOGUE_FILE) *.lps *.cir; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir); \
+ done )
+ ( cd lib/$(INTERP_PATH) ; for i in $(STARTUP_FILE); do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir); \
+ done )
+ @echo "Installing .lps font files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)/fonts
+ for i in $(FONTS_LPS); do \
+ $(INSTALL_DATA) lib/fonts/$$i.lps $(DESTDIR)$(librarydir)/fonts; \
+ done
+ @echo "Installing .xfe font files"
+ for i in $(FONTS_XFE); do \
+ $(INSTALL_DATA) lib/fonts/$$i.xfe $(DESTDIR)$(librarydir)/fonts; \
+ done
+ @echo "Installing scripts (if option enabled)"
+ if test "$(PYTHON)" != ""; then \
+ $(mkinstalldirs) $(DESTDIR)$(scriptsdir)/python; \
+ for i in $(SCRIPTS_PY); do \
+ $(INSTALL_DATA) lib/python/$$i.py \
+ $(DESTDIR)$(scriptsdir)/python; \
+ done; \
+ fi
+
+# Note that MacOS/Fink uses SHDLIB_EXT = .dylib but Tcl expects .so anyway.
+# So we make a symbolic link if SHDLIB_EXT != .so
+
+install-tcl: xcircexec$(EXEEXT) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ @echo "Installing standard XCircuit library files"
+ $(MAKE) $(AM_MAKEFLAGS) install-data-local
+ @echo "Installing Tcl files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ $(mkinstalldirs) $(DESTDIR)$(scriptsdir)
+ ( cd lib/$(INTERP_PATH) ; for i in $(WRAPPER_OBJ) *.tcl ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(scriptsdir); \
+ done )
+ $(INSTALL_DATA) xcircexec$(EXEEXT) $(DESTDIR)$(librarydir)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(CONSOLE)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(CONSOLE_SCRIPT)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(WRAPPER_OBJ)
+ chmod 0755 $(DESTDIR)$(librarydir)/xcircexec$(EXEEXT)
+
+ if test "${SHDLIB_EXT}" != ".so"; then \
+ ( cd $(DESTDIR)$(librarydir); \
+ $(RM) $(WRAPPER_SO) ; \
+ ln -s $(WRAPPER_OBJ) $(WRAPPER_SO) ) ; \
+ fi
+
+ @echo "Installing GIF images"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)/pixmaps
+ ( cd lib/pixmaps ; for i in `ls *.gif *.xbm *.ico` ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir)/pixmaps; \
+ done )
+ @echo "Installing shell script as xcircuit executable"
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/$(WRAPPER_SH) $(DESTDIR)$(bindir)/xcircuit
+ chmod 0755 $(DESTDIR)$(bindir)/xcircuit
+
+clean:
+ (cd ./Xw; $(RM) *.o *.a *.bak core)
+ (cd ./asg; $(MAKE) clean)
+ (cd ./spiceparser; $(MAKE) clean)
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ $(RM) xcircuit *.o *.bak lib/xcircuit.1 core xcircexec$(EXEEXT)
+ $(RM) menudep$(EXEEXT) menudep.h
+ $(RM) config.cache config.log
+
+distclean:
+ (cd ./Xw; $(RM) *.o *.a *.bak Makefile core)
+ (cd ./asg; $(MAKE) clean ; $(RM) Makefile)
+ (cd ./spiceparser; $(MAKE) clean ; $(RM) Makefile)
+ $(RM) xcircuit *.o *.bak core
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) menudep$(EXEEXT) menudep.h lib/xcircuit.1 xcircexec$(EXEEXT)
+ $(RM) Makefile config.cache config.log config.status
+ $(RM) xcircuit-$(FULL_VERSION) xcircuit.spec xcircuit-$(FULL_VERSION).tgz
+
+dist:
+ $(RM) xcircuit.spec xcircuit-$(FULL_VERSION) xcircuit-$(FULL_VERSION).tgz
+ sed -e /%VERSION%/s/%VERSION%/$(FULL_VERSION)/ \
+ xcircuit.spec.in > xcircuit.spec
+ ln -nsf . xcircuit-$(FULL_VERSION)
+ tar zchvf xcircuit-$(FULL_VERSION).tgz --exclude CVS \
+ --exclude xcircuit-$(FULL_VERSION)/xcircuit-$(FULL_VERSION) \
+ --exclude xcircuit-$(FULL_VERSION)/xcircuit-$(FULL_VERSION).tgz \
+ xcircuit-$(FULL_VERSION)
+
+quiteclean:
+ (cd ./Xw; $(RM) *.o *.a *.bak Makefile.in Makefile core)
+ (cd ./asg; $(MAKE) clean ; $(RM) Makefile.in Makefile)
+ (cd ./spiceparser; $(MAKE) clean ; $(RM) Makefile.in Makefile)
+ $(RM) xcircuit *.o *.bak core
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) menudep$(EXEEXT) menudep.h lib/xcircuit.1 xcircexec$(EXEEXT)
+ $(RM) install-sh missing mkinstalldirs Makefile.in Makefile
+ $(RM) config.* aclocal.m4
+
+$(ALL_TARGET):
+ $(MAKE) tcl
+
+$(INSTALL_TARGET):
+ $(MAKE) install-tcl
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..edd0ae0
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,898 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = xcircuit$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/configure $(am__configure_deps) mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+menudep_SOURCES = menudep.c
+menudep_OBJECTS = menudep.$(OBJEXT)
+menudep_LDADD = $(LDADD)
+am_xcircuit_OBJECTS = elements.$(OBJEXT) events.$(OBJEXT) \
+ filelist.$(OBJEXT) files.$(OBJEXT) flate.$(OBJEXT) \
+ fontfile.$(OBJEXT) formats.$(OBJEXT) functions.$(OBJEXT) \
+ graphic.$(OBJEXT) help.$(OBJEXT) keybindings.$(OBJEXT) \
+ libraries.$(OBJEXT) menucalls.$(OBJEXT) netlist.$(OBJEXT) \
+ ngspice.$(OBJEXT) opengl.$(OBJEXT) parameter.$(OBJEXT) \
+ python.$(OBJEXT) rcfile.$(OBJEXT) render.$(OBJEXT) \
+ schema.$(OBJEXT) selection.$(OBJEXT) svg.$(OBJEXT) \
+ text.$(OBJEXT) undo.$(OBJEXT) tclxcircuit.$(OBJEXT) \
+ tkSimple.$(OBJEXT) xcircuit.$(OBJEXT) xtfuncs.$(OBJEXT) \
+ xtgui.$(OBJEXT)
+xcircuit_OBJECTS = $(am_xcircuit_OBJECTS)
+xcircuit_DEPENDENCIES =
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = menudep.c $(xcircuit_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+ACLOCAL = @ACLOCAL@
+
+# Override standard "make" target when compiling under TCL
+ALL_TARGET = @ALL_TARGET@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+
+# Main compiler arguments
+DEFS = @DEFS@ $(PATHNAMES)
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_LIB_SPECS = @EXTRA_LIB_SPECS@
+GREP = @GREP@
+GS_EXEC = @GS_EXEC@
+HAVE_LGF = @HAVE_LGF@
+INC_SPECS = @INC_SPECS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTALL_TARGET = @INSTALL_TARGET@
+INTERPRETER = @INTERPRETER@
+INTERP_PATH = @INTERP_PATH@
+LD = @LD@
+LDDL_FLAGS = @LDDL_FLAGS@
+LDFLAGS = @LDFLAGS@
+LD_RUN_PATH = @LD_RUN_PATH@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIB_SPECS = @LIB_SPECS@
+LTLIBOBJS = @LTLIBOBJS@
+M4 = @M4@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+REVISION = @REVISION@
+SET_MAKE = @SET_MAKE@
+SHDLIB_EXT = @SHDLIB_EXT@
+SHELL = @SHELL@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_LIB_SPECS = @SHLIB_LIB_SPECS@
+SPICE_EXEC = @SPICE_EXEC@
+STARTUP_FILE = @STARTUP_FILE@
+STDLIBS = @STDLIBS@
+STRIP = @STRIP@
+SUBDIRS = @SUBDIRS@
+SUBLIB = @SUBLIB@
+TCL_LIB_DIR = @TCL_LIB_DIR@
+VERSION = @VERSION@
+WISH_EXE = @WISH_EXE@
+WRAPPER_SCRIPT = @WRAPPER_SCRIPT@
+XCIRCUIT_TARGET = @XCIRCUIT_TARGET@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies no-dist
+
+# Additional files to distribute
+EXTRA_DIST = COPYRIGHT README README.ISOLatin2 README.notes
+FULL_VERSION = @VERSION@.@REVISION@
+
+# Menudep program generates menudep.h needed by some of the
+# source files for Xcircuit
+noinst_PROGRAMS = menudep$(EXEEXT)
+
+# Automake files
+ac_aux_dir = dist
+
+# Temporary directory (if not overridden by environment variable TMPDIR)
+tmpdir = /tmp
+
+# Directories for app-defaults file and manual page
+appdefaultsdir = $(libdir)/$(PACKAGE)-$(VERSION)/app-defaults
+appmandir = $(libdir)/$(PACKAGE)-$(VERSION)/man
+PATHNAMES = -DPROG_VERSION=$(VERSION) \
+ -DPROG_REVISION=$(REVISION) \
+ -DCAD_DIR=\"$(libdir)\" \
+ -DTEMP_DIR=\"$(tmpdir)\" \
+ -DRESOURCES_DIR=\"$(appdefaultsdir)\" \
+ -DSCRIPTS_DIR=\"$(scriptsdir)\" \
+ -DBUILTINS_DIR=\"$(librarydir)\" \
+ -DBUILTINS_FILE=\"$(BUILTINS_FILE)\" \
+ -DUSER_RC_FILE=\"$(USER_RC_FILE)\" \
+ -DPROLOGUE_DIR=\"$(librarydir)\" \
+ -DPROLOGUE_FILE=\"$(PROLOGUE_FILE)\" \
+ -DSTARTUP_FILE=\"$(STARTUP_FILE)\" \
+ -DLGF_LIB=\"$(LGF_LIB)\" \
+ -DASG_SPICE_LIB=\"$(ASG_SPICE_LIB)\"
+
+xcircuit_SOURCES = elements.c events.c filelist.c files.c \
+ flate.c fontfile.c formats.c functions.c graphic.c \
+ help.c keybindings.c libraries.c menucalls.c \
+ netlist.c ngspice.c opengl.c parameter.c python.c \
+ rcfile.c render.c schema.c selection.c svg.c text.c undo.c \
+ tclxcircuit.c tkSimple.c xcircuit.c xtfuncs.c xtgui.c
+
+xcircuit_DEPEND = @SUBLIB@
+xcircuit_LDADD = @SUBLIB@ @STDLIBS@
+
+# Man page
+M4_DEFS = @M4_DEFS@ @DEFS@
+man_MANS = lib/xcircuit.1
+INCLUDES = -IXw ${INC_SPECS}
+
+# Library directory and files
+librarydir = $(libdir)/$(PACKAGE)-$(VERSION)
+scriptsdir = $(libdir)/$(PACKAGE)-$(VERSION)
+USER_RC_FILE = .xcircuitrc
+PROLOGUE_FILE = xcircps2.pro
+LGF_LIB = lgf.lps
+ASG_SPICE_LIB = asg_spice.lps
+SIGNAL_LIB = signal.lps
+MUSIC_LIB = musiclib.lps
+FONTS_LPS = courier courieriso2 courieriso5 helvetica helveticaiso2 \
+ helveticaiso5 myfont symbol times_roman times_romaniso2 \
+ times_romaniso5
+
+FONTS_XFE = courier courieriso courieriso2 courieriso5 helvetica \
+ helveticaiso helveticaiso2 helveticaiso5 myfont symbol \
+ times_roman times_romaniso times_romaniso2 times_romaniso5
+
+SCRIPTS_PY = spice gettext pagebbox
+WRAPPER_INIT = xcircuit.tcl
+WRAPPER_OBJ = xcircuit${SHDLIB_EXT}
+WRAPPER_SO = xcircuit.so
+WRAPPER_SH = xcircuit.sh
+CONSOLE = tkcon.tcl
+CONSOLE_SCRIPT = console.tcl
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+xcircuit$(EXEEXT): $(xcircuit_OBJECTS) $(xcircuit_DEPENDENCIES)
+ @rm -f xcircuit$(EXEEXT)
+ $(LINK) $(xcircuit_OBJECTS) $(xcircuit_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+install-man1: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-data-local install-man
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags ctags-recursive \
+ distclean distclean-compile distclean-generic distclean-tags \
+ dvi dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+
+menudep$(EXEEXT): menudep.o
+ $(CC) -o $@ menudep.o
+
+menudep.h: menudep$(EXEEXT)
+ ./menudep$(EXEEXT)
+
+xcwrap.o: xcwrap.c menudep.h
+ $(CC) ${CPPFLAGS} ${CFLAGS} ${DEFS} $(PATHNAMES) $(INCLUDES) \
+ xcwrap.c -c -o xcwrap.o
+
+lib/tcl/xcircuit${SHDLIB_EXT}: xcwrap.o ${xcircuit_OBJECTS} ${xcircuit_DEPEND}
+ $(RM) lib/xcircuit${SHDLIB_EXT}
+ $(CC) ${CFLAGS} ${SHLIB_CFLAGS} -o $@ ${LDDL_FLAGS} xcwrap.o \
+ ${xcircuit_OBJECTS} ${xcircuit_LDADD} ${SHLIB_LIB_SPECS} \
+ ${LDFLAGS} ${X_EXTRA_LIBS} ${EXTRA_LIBS} -lc ${LIBS} \
+ ${LIB_SPECS} ${EXTRA_LIB_SPECS}
+
+xcircexec$(EXEEXT): xcircexec.o
+ $(RM) ./xcircexec$(EXEEXT)
+ $(CC) ${CFLAGS} ${CPPFLAGS} ${DEFS} $(PATHNAMES) $(INCLUDES) \
+ xcircexec.c -o xcircexec$(EXEEXT) ${LIB_SPECS} \
+ ${LD_RUN_PATH} ${LDFLAGS} ${LIBS} ${EXTRA_LIB_SPECS}
+
+tcl:
+ @echo Making tcl library object
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (echo "Making tcl in $$subdir"; \
+ cd $$subdir && $(MAKE) $(AM_MAKEFLAGS)) \
+ done
+ $(MAKE) lib/tcl/xcircuit${SHDLIB_EXT}
+ $(MAKE) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(MAKE) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ $(MAKE) xcircexec$(EXEEXT)
+
+help.c: menudep.h
+menucalls.c: menudep.h
+rcfile.c: menudep.h
+schema.c: menudep.h
+xcircuit.c: menudep.h
+parameter.c: menudep.h
+python.c: menudep.h
+tclxcircuit.c: menudep.h
+xtgui.c: menudep.h
+xtfuncs.c: menudep.h
+
+lib/$(INTERP_PATH)/$(WRAPPER_SH): lib/$(INTERP_PATH)/$(WRAPPER_SH).in
+ sed -e '/XCLIBDIR/s#XCLIBDIR#$(librarydir)#' \
+ -e '/WRAPPER_INIT/s/WRAPPER_INIT/$(WRAPPER_INIT)/' \
+ -e '/CONSOLE_SCRIPT/s/CONSOLE_SCRIPT/$(CONSOLE_SCRIPT)/' \
+ -e '/CONSOLE/s/CONSOLE/$(CONSOLE)/' \
+ -e '/PROG_VERSION/s/PROG_VERSION/$(VERSION)/' \
+ -e '/PROG_REVISION/s/PROG_REVISION/$(REVISION)/' \
+ -e '/TCLLIBDIR/s#TCLLIBDIR#$(TCL_LIB_DIR)#' \
+ -e '/WISH_EXE/s#WISH_EXE#$(WISH_EXE)#' \
+ lib/$(INTERP_PATH)/$(WRAPPER_SH).in > $@
+ chmod 0755 $@
+
+lib/$(INTERP_PATH)/$(WRAPPER_INIT): lib/$(INTERP_PATH)/$(WRAPPER_INIT).in
+ sed -e '/LIBDIR/s#LIBDIR#$(librarydir)#' \
+ -e '/SCRIPTSDIR/s#SCRIPTSDIR#$(scriptsdir)#' \
+ lib/$(INTERP_PATH)/$(WRAPPER_INIT).in > $@
+ chmod 0755 $@
+
+lib/xcircuit.1: lib/xcircuit.1.in
+ sed -e '/LIBDIR/s#LIBDIR#$(libdir)#' \
+ -e "/^${HAVE_LGF}/s/^${HAVE_LGF} //" \
+ -e "/^${INTERPRETER}/s/^${INTERPRETER} //" \
+ -e '/^PYTHON /d' \
+ -e '/^TCL /d' \
+ -e '/^LGF /d' \
+ -e '/^NOINTERP /d' \
+ lib/xcircuit.1.in > $@
+
+install-data-local: lib/xcircuit.1
+ @echo "Installing app-defaults file"
+ $(mkinstalldirs) $(DESTDIR)$(appdefaultsdir)
+ $(mkinstalldirs) $(DESTDIR)$(appmandir)
+ $(INSTALL_DATA) lib/XCircuit.ad $(DESTDIR)$(appdefaultsdir)/XCircuit
+ $(INSTALL_DATA) lib/xcircuit.1 $(DESTDIR)$(appmandir)/xcircuit.1
+ @echo "Installing library and netlist files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ ( cd lib ; for i in $(PROLOGUE_FILE) *.lps *.cir; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir); \
+ done )
+ ( cd lib/$(INTERP_PATH) ; for i in $(STARTUP_FILE); do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir); \
+ done )
+ @echo "Installing .lps font files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)/fonts
+ for i in $(FONTS_LPS); do \
+ $(INSTALL_DATA) lib/fonts/$$i.lps $(DESTDIR)$(librarydir)/fonts; \
+ done
+ @echo "Installing .xfe font files"
+ for i in $(FONTS_XFE); do \
+ $(INSTALL_DATA) lib/fonts/$$i.xfe $(DESTDIR)$(librarydir)/fonts; \
+ done
+ @echo "Installing scripts (if option enabled)"
+ if test "$(PYTHON)" != ""; then \
+ $(mkinstalldirs) $(DESTDIR)$(scriptsdir)/python; \
+ for i in $(SCRIPTS_PY); do \
+ $(INSTALL_DATA) lib/python/$$i.py \
+ $(DESTDIR)$(scriptsdir)/python; \
+ done; \
+ fi
+
+# Note that MacOS/Fink uses SHDLIB_EXT = .dylib but Tcl expects .so anyway.
+# So we make a symbolic link if SHDLIB_EXT != .so
+
+install-tcl: xcircexec$(EXEEXT) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ @echo "Installing standard XCircuit library files"
+ $(MAKE) $(AM_MAKEFLAGS) install-data-local
+ @echo "Installing Tcl files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ $(mkinstalldirs) $(DESTDIR)$(scriptsdir)
+ ( cd lib/$(INTERP_PATH) ; for i in $(WRAPPER_OBJ) *.tcl ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(scriptsdir); \
+ done )
+ $(INSTALL_DATA) xcircexec$(EXEEXT) $(DESTDIR)$(librarydir)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(CONSOLE)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(CONSOLE_SCRIPT)
+ chmod 0755 $(DESTDIR)$(librarydir)/$(WRAPPER_OBJ)
+ chmod 0755 $(DESTDIR)$(librarydir)/xcircexec$(EXEEXT)
+
+ if test "${SHDLIB_EXT}" != ".so"; then \
+ ( cd $(DESTDIR)$(librarydir); \
+ $(RM) $(WRAPPER_SO) ; \
+ ln -s $(WRAPPER_OBJ) $(WRAPPER_SO) ) ; \
+ fi
+
+ @echo "Installing GIF images"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)/pixmaps
+ ( cd lib/pixmaps ; for i in `ls *.gif *.xbm *.ico` ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(librarydir)/pixmaps; \
+ done )
+ @echo "Installing shell script as xcircuit executable"
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/$(WRAPPER_SH) $(DESTDIR)$(bindir)/xcircuit
+ chmod 0755 $(DESTDIR)$(bindir)/xcircuit
+
+clean:
+ (cd ./Xw; $(RM) *.o *.a *.bak core)
+ (cd ./asg; $(MAKE) clean)
+ (cd ./spiceparser; $(MAKE) clean)
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ $(RM) xcircuit *.o *.bak lib/xcircuit.1 core xcircexec$(EXEEXT)
+ $(RM) menudep$(EXEEXT) menudep.h
+ $(RM) config.cache config.log
+
+distclean:
+ (cd ./Xw; $(RM) *.o *.a *.bak Makefile core)
+ (cd ./asg; $(MAKE) clean ; $(RM) Makefile)
+ (cd ./spiceparser; $(MAKE) clean ; $(RM) Makefile)
+ $(RM) xcircuit *.o *.bak core
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) menudep$(EXEEXT) menudep.h lib/xcircuit.1 xcircexec$(EXEEXT)
+ $(RM) Makefile config.cache config.log config.status
+ $(RM) xcircuit-$(FULL_VERSION) xcircuit.spec xcircuit-$(FULL_VERSION).tgz
+
+dist:
+ $(RM) xcircuit.spec xcircuit-$(FULL_VERSION) xcircuit-$(FULL_VERSION).tgz
+ sed -e /%VERSION%/s/%VERSION%/$(FULL_VERSION)/ \
+ xcircuit.spec.in > xcircuit.spec
+ ln -nsf . xcircuit-$(FULL_VERSION)
+ tar zchvf xcircuit-$(FULL_VERSION).tgz --exclude CVS \
+ --exclude xcircuit-$(FULL_VERSION)/xcircuit-$(FULL_VERSION) \
+ --exclude xcircuit-$(FULL_VERSION)/xcircuit-$(FULL_VERSION).tgz \
+ xcircuit-$(FULL_VERSION)
+
+quiteclean:
+ (cd ./Xw; $(RM) *.o *.a *.bak Makefile.in Makefile core)
+ (cd ./asg; $(MAKE) clean ; $(RM) Makefile.in Makefile)
+ (cd ./spiceparser; $(MAKE) clean ; $(RM) Makefile.in Makefile)
+ $(RM) xcircuit *.o *.bak core
+ $(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(RM) menudep$(EXEEXT) menudep.h lib/xcircuit.1 xcircexec$(EXEEXT)
+ $(RM) install-sh missing mkinstalldirs Makefile.in Makefile
+ $(RM) config.* aclocal.m4
+
+$(ALL_TARGET):
+ $(MAKE) tcl
+
+$(INSTALL_TARGET):
+ $(MAKE) install-tcl
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Makefile.mingw64 b/Makefile.mingw64
new file mode 100644
index 0000000..a060520
--- /dev/null
+++ b/Makefile.mingw64
@@ -0,0 +1,463 @@
+# Makefile for MinGW gcc64 compiler (modified from Makefile.win32)
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Prerequisites: - mingw x64 gcc compiler
+# - make (often supplied with the gcc compiler)
+# - Tcl x64 ver 8.5
+# - gs9.02x64
+# - graphicsmagick-1.3.14
+#
+# Note: This Makefile support only the tcl build.
+
+###########################
+# Configuration variables #
+###########################
+# INSTALLDIR = C:\app\xcircuit-tcl
+# INSTALLDIR = C:/MinGW/msys/1.0/home/TEdwards/xcircuit-tcl
+INSTALLDIR = C:/OpenCircuitDesign/XCircuit-3.8
+# TEMPDIR = D:\Temp
+# TEMPDIR = C:/Temp
+TEMPDIR = C:/OpenCircuitDesign/Temp
+
+
+# CC_EXEC = C:\app\gcc64\bin\gcc.exe
+CC_EXEC = C:/MinGW64/bin/x86_64-w64-mingw32-gcc.exe
+# GSDIR = C:\gs\gs9.02x64
+GSDIR = "C:\Program Files\gs\gs9.05"
+# GMDIR = C:\graphicsmagick-1.3.14
+GMDIR = "C:/Program Files/GraphicsMagick"
+WINDRES = C:/MinGW64/bin/x86_64-w64-mingw32-windres.exe
+
+# Possible values: tcl, win32
+BUILD_TYPE = tcl
+
+# Additional settings for win32 build
+USE_WIN32_COM = 0
+USE_WIN32_DOTNET = 0
+XCCOMDIR = xccom2
+
+# Additional settings for tcl build
+# TCLDIR = C:\app\tclx64
+TCLDIR = "C:/Tcl"
+TCLVERSION = 85
+
+# Some defines:
+SIZEOF_VOID_P := 8
+SIZEOF_UNSIGNED_INT := 4
+SIZEOF_UNSIGNED_LONG := 4
+SIZEOF_UNSIGNED_LONG_LONG := 8
+
+####################################################################
+# End of configuration. DO NOT CHANGE ANYTHING AFTER THIS POINT!!! #
+####################################################################
+
+SOURCES = menudep.c $(xcircuit_SOURCES)
+
+MK = $(MAKE) -f Makefile.mingw64
+
+srcdir = .
+top_srcdir = .
+top_builddir = .
+mkinstalldirs = mkdir -p
+
+menudep_SOURCES = menudep.c
+menudep_OBJECTS = menudep.$(OBJEXT)
+menudep_LDADD = $(LDADD)
+xcircuit_OBJECTS = elements.$(OBJEXT) events.$(OBJEXT) \
+ filelist.$(OBJEXT) files.$(OBJEXT) flate.$(OBJEXT) \
+ fontfile.$(OBJEXT) formats.$(OBJEXT) functions.$(OBJEXT) \
+ graphic.$(OBJEXT) help.$(OBJEXT) keybindings.$(OBJEXT) \
+ libraries.$(OBJEXT) menucalls.$(OBJEXT) netlist.$(OBJEXT) \
+ ngspice.$(OBJEXT) opengl.$(OBJEXT) parameter.$(OBJEXT) \
+ python.$(OBJEXT) rcfile.$(OBJEXT) render.$(OBJEXT) \
+ svg.$(OBJEXT) \
+ schema.$(OBJEXT) selection.$(OBJEXT) text.$(OBJEXT) \
+ undo.$(OBJEXT) xcircuit.$(OBJEXT) $(WIN32_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(CPPFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -Fe$@ #Not in use
+SOURCES = menudep.c $(xcircuit_SOURCES)
+DIST_SOURCES = menudep.c $(xcircuit_SOURCES)
+man1dir = $(mandir)
+MANS = $(man_MANS)
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+DIST_ARCHIVES = $(distdir).zip
+
+XC_CFLAGS =
+XC_LIBS =
+XC_OBJECT =
+XC_INCLUDES =
+
+ifeq ($(BUILD_TYPE),win32)
+ WIN32_OBJECTS = xcwin32.$(OBJEXT) xtfuncs.$(OBJEXT) xtgui.$(OBJEXT) resources.res
+ BUILTINS_DIR = WinBuiltinsDir()
+ STARTUP_FILE = startup.script
+ XC_CFLAGS = -DHAVE_XPM
+ ifneq ($(USE_WIN32_COM),0)
+ XC_CFLAGS = $(XC_CFLAGS) -DUSE_WIN32_COM
+ XC_DEPEND = $(XCCOMDIR)\XCCom.lib
+ XC_LIBS = $(XCCOMDIR)\XCCom.lib ole32.lib oleaut32.lib
+ ifneq ($(USE_WIN32_DOTNET),0)
+ XC_CFLAGS = $(XC_CFLAGS) -DUSE_WIN32_DOTNET
+ endif
+ endif
+else #!win32
+ WIN32_OBJECTS = tclxcircuit.$(OBJEXT) tkSimple.$(OBJEXT) w32x11.$(OBJEXT)
+ BUILTINS_DIR = \"$(subst \,/,$(librarydir))\"
+ SCRIPTS_DIR = \"$(subst \,/,$(scriptsdir))\"
+ STARTUP_FILE = xcstartup.tcl
+ XC_CFLAGS = -DTCL_WRAPPER
+ XC_INCLUDES = -I$(TCLDIR)/include
+ XC_LIBS = $(TCLDIR)/bin/base-tcl8.5-thread-win32-x86_64.dll \
+ $(TCLDIR)/bin/tcl$(TCLVERSION).dll \
+ $(TCLDIR)/bin/tk$(TCLVERSION).dll
+endif
+
+
+# Override standard "make" target when compiling under TCL
+ALL_TARGET = all-recursive
+INSTALL_TARGET = install
+
+CC = $(CC_EXEC)
+CFLAGS = -g -DSPICE_EXEC=\"$(subst \,/,$(SPICE_EXEC))\" -DHAVE_PUTENV -DGS_EXEC=\"$(subst \,/,$(GS_EXEC))\" -DGM_EXEC=\"$(subst \,/,$(GM_EXEC))\" -DXC_WIN32 -DDOUBLEBUFFER $(XC_CFLAGS) -DSIZEOF_VOID_P=$(SIZEOF_VOID_P) -DSIZEOF_UNSIGNED_INT=$(SIZEOF_UNSIGNED_INT) -DSIZEOF_UNSIGNED_LONG=$(SIZEOF_UNSIGNED_LONG) -DSIZEOF_UNSIGNED_LONG_LONG=$(SIZEOF_UNSIGNED_LONG_LONG) -D_MSC_VER
+CPP = _not_in_use_
+CPPFLAGS =
+RM = rm
+RMDIR = rmdir
+
+# Main compiler arguments
+DEFS = $(PATHNAMES)
+ECHO_C = echo
+ECHO_N = echo
+ECHO_T = echo
+EGREP = egrep
+EXEEXT = .exe
+EXTRA_LIB_SPECS =
+GS_EXEC = $(GSDIR)\bin\gswin64c.exe
+GM_EXEC = $(GMDIR)\gm.exe
+INC_SPECS = -I. $(XC_INCLUDES)
+INSTALL_DATA = cp
+INSTALL_PROGRAM = cp
+INSTALL_SCRIPT = cp
+INSTALL_STRIP_PROGRAM = cp
+INTERP_PATH = tcl
+LD = link _not_in_use_
+LDDL_FLAGS =
+LDFLAGS =
+LIBS = -lws2_32 -lgdi32 $(XC_LIBS)
+# LIBS = ws2_32.lib gdi32.lib user32.lib kernel32.lib comdlg32.lib comctl32.lib $(XC_LIBS)
+# imm32.lib shell32.lib comctl32.lib advapi32.lib
+
+LIB_SPECS =
+PP = pp.exe
+
+# Man page
+MAKEINFO = makeinfo
+OBJEXT = o
+PACKAGE = xcircuit
+PACKAGE_NAME = xcircuit
+PATH_SEPARATOR = \\
+VERSION = 3.8
+REVISION = 17
+SHDLIB_EXT = .dll
+SHLIB_CFLAGS = -shared
+SHLIB_LIB_SPECS =
+SPICE_EXEC = ngspice.exe
+SUBDIRS =
+TCL_LIB_DIR = $(TCLDIR)\lib
+WISH_EXE = $(TCLDIR)\bin\wish$(TCLVERSION).exe
+WRAPPER_SCRIPT =
+XCIRCUIT_TARGET = $(BUILD_TYPE)
+X_EXTRA_LIBS =
+prefix = $(INSTALLDIR)
+bindir = $(prefix)/bin
+datadir = $(prefix)
+exec_prefix = $(prefix)/bin
+includedir = $(prefix)/include
+libdir = $(prefix)/lib
+libexecdir = $(prefix)/bin
+mandir = $(prefix)/doc
+mkdir_p = mkdir -p
+
+# Temporary directory (if not overridden by environment variable TMPDIR)
+tmpdir = $(TEMPDIR)
+
+# Directories for app-defaults file and manual page
+PATHNAMES = -DPROG_VERSION=$(VERSION) \
+ -DPROG_REVISION=$(REVISION) \
+ -DCAD_DIR=\"$(prefix)\" \
+ -DTEMP_DIR=\"$(tmpdir)\" \
+ -DSCRIPTS_DIR=\"$(scriptsdir)\" \
+ -DBUILTINS_DIR=$(BUILTINS_DIR) \
+ -DBUILTINS_FILE=\"$(BUILTINS_FILE)\" \
+ -DUSER_RC_FILE=\"$(USER_RC_FILE)\" \
+ -DPROLOGUE_DIR=$(BUILTINS_DIR) \
+ -DPROLOGUE_FILE=\"$(PROLOGUE_FILE)\" \
+ -DSTARTUP_FILE=\"$(STARTUP_FILE)\" \
+ -DLGF_LIB=\"$(LGF_LIB)\"
+
+xcircuit_SOURCES = elements.c events.c filelist.c files.c \
+ flate.c fontfile.c formats.c functions.c graphic.c \
+ help.c keybindings.c libraries.c menucalls.c \
+ netlist.c ngspice.c opengl.c parameter.c python.c \
+ rcfile.c render.c schema.c selection.c \
+ svg.c \
+ text.c undo.c \
+ tclxcircuit.c tkSimple.c xcircuit.c w32x11.c
+
+xcircuit_DEPEND = $(XC_DEPEND)
+xcircuit_LDADD =
+man_MANS = lib/xcircuit.1
+INCLUDES = $(INC_SPECS)
+
+# Library directory and files
+# librarydir = $(datadir)/$(PACKAGE)-$(VERSION)
+# scriptsdir = $(datadir)/$(PACKAGE)-$(VERSION)
+librarydir = $(datadir)
+scriptsdir = $(datadir)
+USER_RC_FILE = .xcircuitrc
+PROLOGUE_FILE = xcircps2.pro
+LGF_LIB = lgf.lps
+SIGNAL_LIB = signal.lps
+MUSIC_LIB = musiclib.lps
+FONTS_LPS = courier courieriso2 courieriso5 helvetica helveticaiso2 \
+ helveticaiso5 myfont symbol times_roman times_romaniso2 \
+ times_romaniso5
+
+FONTS_XFE = courier courieriso courieriso2 courieriso5 helvetica \
+ helveticaiso helveticaiso2 helveticaiso5 myfont symbol \
+ times_roman times_romaniso times_romaniso2 times_romaniso5
+
+SCRIPTS_PY = spice gettext pagebbox
+WRAPPER_INIT = xcircuit.tcl
+WRAPPER_OBJ = xcircuit$(SHDLIB_EXT)
+WRAPPER_SO = xcircuit.dll
+WRAPPER_SH = xcircuit.bat
+CONSOLE = tkcon.tcl
+CONSOLE_SCRIPT = console.tcl
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj .rc .res
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c "$<"
+
+.rc.res:
+ $(WINDRES) -o $@ -O coff $(XC_CFLAGS) -I $(XCCOMDIR) $<
+
+
+##################
+# Building rules #
+##################
+
+menudep$(EXEEXT): menudep.$(OBJEXT)
+ $(CC) -o $@ menudep.$(OBJEXT)
+
+menudep.h: menudep$(EXEEXT) menus.h
+ .\menudep$(EXEEXT)
+
+xcwrap.obj: xcwrap.c menudep.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFS) $(PATHNAMES) $(INCLUDES) \
+ xcwrap.c -c -o xcwrap.$(OBJEXT)
+
+lib/tcl/xcircuit$(SHDLIB_EXT): xcwrap.$(OBJEXT) $(xcircuit_OBJECTS) $(xcircuit_DEPEND)
+ -$(RM) lib\xcircuit$(SHDLIB_EXT)
+ $(CC) $(CFLAGS) $(SHLIB_CFLAGS) -o $@ $(LDDL_FLAGS) xcwrap.$(OBJEXT) \
+ $(xcircuit_OBJECTS) $(xcircuit_LDADD) $(LDFLAGS) \
+ $(X_EXTRA_LIBS) $(EXTRA_LIBS) $(LIBS) $(EXTRA_LIB_SPECS) \
+ $(SHLIB_LIB_SPECS)
+
+xcircuit$(EXEEXT): $(xcircuit_OBJECTS) $(xcircuit_DEPEND)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCLUDES) $(xcircuit_OBJECTS) \
+ -o $@ $(LDFLAGS) $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS) shell32.lib \
+ /link /SUBSYSTEM:CONSOLE
+
+xcircexec$(EXEEXT): xcircexec.$(OBJEXT)
+ -$(RM) .\xcircexec$(EXEEXT)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(PATHNAMES) $(INCLUDES) \
+ xcircexec.c -o $@ $(LDFLAGS) \
+ $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS)
+
+xcircuit-win32$(EXEEXT): xcircuit-win32.c resources.res
+ $(CC) $(CFLAGS) $(CPPFLAGS) \
+ -DWISH_EXE=L\"$(subst \,/,$(WISH_EXE))\" \
+ -DBUILTINS_DIR=L$(BUILTINS_DIR) \
+ $(INCLUDES) xcircuit-win32.c resources.res \
+ -o $@ $(LDFLAGS) $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS) -lshell32 -ladvapi32
+
+tcl:
+ @echo Making tcl library object
+ $(MK) lib/tcl/xcircuit$(SHDLIB_EXT)
+ $(MK) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ $(MK) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ $(MK) xcircexec$(EXEEXT)
+ $(MK) xcircuit-win32$(EXEEXT)
+
+win32:
+ @echo Making win32
+ifneq ($(USE_WIN32_COM),0)
+ cd $(XCCOMDIR) && $(MK) && cd ..
+endif
+ $(MK) xcircuit$(EXEEXT)
+
+help.c: menudep.h
+menucalls.c: menudep.h
+rcfile.c: menudep.h
+schema.c: menudep.h
+xcircuit.c: menudep.h
+parameter.c: menudep.h
+python.c: menudep.h
+tclxcircuit.c: menudep.h
+resources.rc: lib/pixmaps/xcircuit.ico
+
+$(PP): pp.c
+ $(CC) -g -o $@ pp.c
+
+lib/$(INTERP_PATH)/$(WRAPPER_SH): $(PP) lib/$(INTERP_PATH)/$(WRAPPER_SH).in
+ $(PP) $(PATHNAMES) -DXCLIBDIR=\"$(subst \,/,$(librarydir))\" \
+ -DWRAPPER_INIT=\"$(WRAPPER_INIT)\" -DCONSOLE=\"$(CONSOLE)\" \
+ -DCONSOLE_SCRIPT=\"$(CONSOLE_SCRIPT)\" \
+ -DTCLLIBDIR=\"$(subst \,/,$(TCL_LIB_DIR))\" \
+ -DWISH_EXE=\"$(subst \,/,$(WISH_EXE))\" \
+ lib/$(INTERP_PATH)/$(WRAPPER_SH).in > $@
+
+lib/$(INTERP_PATH)/$(WRAPPER_INIT): $(PP) lib/$(INTERP_PATH)/$(WRAPPER_INIT).in
+ $(PP) $(PATHNAMES) -DLIBDIR=\"$(subst \,/,$(librarydir))\" \
+ lib/$(INTERP_PATH)/$(WRAPPER_INIT).in > $@
+
+lib/xcircuit.1: $(PP) lib/xcircuit.1.in
+ $(PP) -DLIBDIR=\"$(libdir)\" \
+ -DSCRIPTSDIR=\"$(scriptsdir)\" \
+ -DLGF=1 -DPYTHON=0 -DTCL=1 -DNOINTERP=0 \
+ lib/xcircuit.1.in > $@
+
+install-data-local: lib/xcircuit.1
+ @echo "Installing library files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ $(INSTALL_DATA) lib/$(PROLOGUE_FILE) $(DESTDIR)$(librarydir)
+ $(INSTALL_DATA) lib/*.lps $(DESTDIR)$(librarydir)
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/$(STARTUP_FILE) $(DESTDIR)$(librarydir)
+ @echo "Installing .lps font files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)/fonts
+ $(foreach f,$(FONTS_LPS), $(INSTALL_DATA) lib/fonts/$(f).lps $(DESTDIR)$(librarydir)/fonts &)
+ @echo "Installing .xfe font files"
+ $(foreach f,$(FONTS_XFE), $(INSTALL_DATA) lib/fonts/$(f).xfe $(DESTDIR)$(librarydir)/fonts &)
+ @echo "Installing scripts (if option enabled)"
+
+# Note that MacOS/Fink uses SHDLIB_EXT = .dylib but Tcl expects .so anyway.
+# So we make a symbolic link if SHDLIB_EXT != .so
+
+install-tcl: xcircexec$(EXEEXT) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH) lib/$(INTERP_PATH)/$(WRAPPER_INIT) xcircuit-win32$(EXEEXT)
+ # if $(prefix) $(RMDIR) $(prefix)
+ mkdir -p $(prefix)
+ @echo "Installing standard XCircuit library files"
+ $(MK) $(AM_MAKEFLAGS) install-data-local
+ @echo "Installing Tcl files"
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) $(DESTDIR)$(librarydir)
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/*.tcl $(DESTDIR)$(librarydir)
+ $(INSTALL_DATA) xcircexec$(EXEEXT) $(DESTDIR)$(librarydir)
+ @echo "Installing pixmap images"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)\pixmaps
+ $(INSTALL_DATA) lib/pixmaps/*.gif $(DESTDIR)$(librarydir)/pixmaps
+ $(INSTALL_DATA) lib/pixmaps/*.xbm $(DESTDIR)$(librarydir)/pixmaps
+ @echo "Installing shell script as xcircuit executable"
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) lib/$(INTERP_PATH)/$(WRAPPER_SH) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) xcircuit-win32$(EXEEXT) $(DESTDIR)$(bindir)
+
+install-win32: xcircuit$(EXEEXT)
+ if exist $(prefix) $(RMDIR) $(prefix)
+ $(MK) $(AM_MAKEFLAGS) install-data-local "librarydir=$(prefix)"
+ $(INSTALL_DATA) xcircuit$(EXEEXT) $(DESTDIR)$(prefix)
+
+clean:
+ -$(RM) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH)
+ -for %%e in (ilk exp pdb lib) do @if exist lib/$(INTERP_PATH)/xcircuit.%%e $(RM) lib/$(INTERP_PATH)/xcircuit.%%e
+ -$(RM) lib/$(INTERP_PATH)/$(WRAPPER_INIT)
+ -for %%f in (*.$(OBJEXT) xcircexec$(EXEEXT) lib/xcircuit.1 xcircuit$(EXEEXT) xcircuit.suo) do $(RM) %%f
+ -for %%e in (aps res) do $(RM) resources.%%e
+ -for %%e in (ilk exp pdb lib) do @if exist xcircexec.%%e $(RM) xcircexec.%%e
+ -for %%e in (ilk exp pdb lib) do @if exist xcircuit.%%e $(RM) xcircuit.%%e
+ -for %%e in (ilk exp pdb lib) do @if exist pp.%%e $(RM) pp.%%e
+ -for %%e in (ilk exp pdb lib exe) do @if exist xcircuit-win32.%%e $(RM) xcircuit-win32.%%e
+ -$(RM) menudep$(EXEEXT) menudep.h
+ -$(RM) pp$(EXEEXT)
+ -$(RM) *.pdb
+ -$(RM) *~
+ifeq ($(BUILD_TYPE),win32)
+ ifneq ($(USE_WIN32_COM),0)
+ cd $(XCCOMDIR) && $(MK) clean && cd ..
+ endif
+endif
+
+$(ALL_TARGET):
+ $(MK) $(XCIRCUIT_TARGET)
+
+$(INSTALL_TARGET):
+ $(MK) install-tcl
+
+examples: all
+ifeq ($(BUILD_TYPE),win32)
+ ifneq ($(USE_WIN32_COM),0)
+ cd $(XCCOMDIR) && $(MK) examples && cd ..
+ endif
+endif
+
+ifeq ($(BUILD_TYPE),win32)
+xcircuit.h: xcwin32.h
+xcwin32.c: xcircuit.h
+else
+xcircuit.h: tkwin32.h
+endif
+elements.c: xcircuit.h
+events.c: xcircuit.h
+filelist.c: xcircuit.h
+files.c: xcircuit.h
+flate.c: xcircuit.h
+fontfile.c: xcircuit.h
+formats.c: xcircuit.h
+functions.c: xcircuit.h
+graphic.c: xcircuit.h
+help.c: xcircuit.h
+keybindings.c: xcircuit.h
+libraries.c: xcircuit.h
+menucalls.c: xcircuit.h
+netlist.c: xcircuit.h
+ngspice.c: xcircuit.h
+opengl.c: xcircuit.h
+parameter.c: xcircuit.h
+python.c: xcircuit.h
+rcfile.c: xcircuit.h
+render.c: xcircuit.h
+schema.c: xcircuit.h
+selection.c: xcircuit.h
+text.c: xcircuit.h
+undo.c: xcircuit.h
+xcircuit.c: xcircuit.h
+xtgui.c: xcircuit.h
+xtfuncs.c: xcircuit.h
+ifeq ($(BUILD_TYPE),win32)
+ ifneq ($(USE_WIN32_COM),0)
+resources.rc: $(XCCOMDIR)/XCCom.tlb
+ endif
+endif
diff --git a/Makefile.win32 b/Makefile.win32
new file mode 100644
index 0000000..bf3e414
--- /dev/null
+++ b/Makefile.win32
@@ -0,0 +1,425 @@
+# Makefile for VC++ compiler (modified from original Makefile.in)
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+###########################
+# Configuration variables #
+###########################
+
+INSTALLDIR = D:\Software\XCircuit-tcl-dev
+TEMPDIR = D:\Temp
+
+GSDIR = C:\gs\gs8.15
+
+# Possible values: tcl, win32
+BUILD_TYPE = tcl
+
+# Additional settings for win32 build
+USE_WIN32_COM = 0
+USE_WIN32_DOTNET = 0
+XCCOMDIR = xccom2
+
+# Additional settings for tcl build
+TCLDIR = D:\Software\Tcl
+TCLVERSION = 84
+
+####################################################################
+# End of configuration. DO NOT CHANGE ANYTHING AFTER THIS POINT!!! #
+####################################################################
+
+SOURCES = menudep.c $(xcircuit_SOURCES)
+
+MAKE = $(MAKE) -f Makefile.win32
+
+srcdir = .
+top_srcdir = .
+top_builddir = .
+mkinstalldirs = mkdir
+
+menudep_SOURCES = menudep.c
+menudep_OBJECTS = menudep.$(OBJEXT)
+menudep_LDADD = $(LDADD)
+xcircuit_OBJECTS = elements.$(OBJEXT) events.$(OBJEXT) \
+ filelist.$(OBJEXT) files.$(OBJEXT) flate.$(OBJEXT) \
+ fontfile.$(OBJEXT) formats.$(OBJEXT) functions.$(OBJEXT) \
+ graphic.$(OBJEXT) help.$(OBJEXT) keybindings.$(OBJEXT) \
+ libraries.$(OBJEXT) menucalls.$(OBJEXT) netlist.$(OBJEXT) \
+ ngspice.$(OBJEXT) opengl.$(OBJEXT) parameter.$(OBJEXT) \
+ python.$(OBJEXT) rcfile.$(OBJEXT) render.$(OBJEXT) \
+ schema.$(OBJEXT) selection.$(OBJEXT) text.$(OBJEXT) \
+ undo.$(OBJEXT) xcircuit.$(OBJEXT) $(WIN32_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(CPPFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -Fe$@
+SOURCES = menudep.c $(xcircuit_SOURCES)
+DIST_SOURCES = menudep.c $(xcircuit_SOURCES)
+man1dir = $(mandir)
+MANS = $(man_MANS)
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+DIST_ARCHIVES = $(distdir).zip
+
+XC_CFLAGS =
+XC_LIBS =
+XC_OBJECT =
+XC_INCLUDES =
+
+!if "$(BUILD_TYPE)" == "win32"
+WIN32_OBJECTS = xcwin32.$(OBJEXT) xtfuncs.$(OBJEXT) xtgui.$(OBJEXT) resources.res
+BUILTINS_DIR = WinBuiltinsDir()
+STARTUP_FILE = startup.script
+XC_CFLAGS = -DHAVE_XPM -D_CRT_SECURE_NO_DEPRECATE
+!if "$(USE_WIN32_COM)" != "0"
+XC_CFLAGS = $(XC_CFLAGS) -DUSE_WIN32_COM
+XC_DEPEND = $(XCCOMDIR)\XCCom.lib
+XC_LIBS = $(XCCOMDIR)\XCCom.lib ole32.lib oleaut32.lib
+!if "$(USE_WIN32_DOTNET)" != "0"
+XC_CFLAGS = $(XC_CFLAGS) -DUSE_WIN32_DOTNET
+!endif
+!endif
+!else
+WIN32_OBJECTS = tclxcircuit.$(OBJEXT) tkSimple.$(OBJEXT) w32x11.$(OBJEXT)
+BUILTINS_DIR = \"$(librarydir:\=/)\"
+SCRIPTS_DIR = \"$(scriptsdir:\=/)\"
+STARTUP_FILE = xcstartup.tcl
+XC_CFLAGS = -DTCL_WRAPPER -D_CRT_SECURE_NO_DEPRECATE
+XC_INCLUDES = -I$(TCLDIR)\include
+XC_LIBS = $(TCLDIR)\lib\tcl$(TCLVERSION).lib $(TCLDIR)\lib\tk$(TCLVERSION).lib
+!endif
+
+
+# Override standard "make" target when compiling under TCL
+ALL_TARGET = all-recursive
+INSTALL_TARGET = install
+
+CC = cl
+CFLAGS = -Zi -DSPICE_EXEC=\"$(SPICE_EXEC:\=/)\" -DHAVE_PUTENV -DGS_EXEC=\"$(GS_EXEC:\=/)\" -DXC_WIN32 -DDOUBLEBUFFER $(XC_CFLAGS)
+CPP = cl
+CPPFLAGS =
+RM = del /q
+RMDIR = rmdir /s /q
+
+# Main compiler arguments
+DEFS = $(PATHNAMES)
+ECHO_C = echo
+ECHO_N = echo
+ECHO_T = echo
+EGREP = egrep
+EXEEXT = .exe
+EXTRA_LIB_SPECS =
+GS_EXEC = $(GSDIR)\bin\gswin32c.exe
+INC_SPECS = -I. $(XC_INCLUDES)
+INSTALL_DATA = copy /y
+INSTALL_PROGRAM = copy /y
+INSTALL_SCRIPT = copy /y
+INSTALL_STRIP_PROGRAM = copy /y
+INTERP_PATH = tcl
+LD = link
+LDDL_FLAGS =
+LDFLAGS =
+LIBS = ws2_32.lib gdi32.lib user32.lib kernel32.lib comdlg32.lib comctl32.lib $(XC_LIBS)
+# imm32.lib shell32.lib comctl32.lib advapi32.lib
+
+LIB_SPECS =
+PP = pp.exe
+
+# Man page
+MAKEINFO = makeinfo
+OBJEXT = obj
+PACKAGE = xcircuit
+PACKAGE_NAME = xcircuit
+PATH_SEPARATOR = \\
+VERSION = 3.7
+REVISION = 21
+SHDLIB_EXT = .dll
+SHLIB_CFLAGS = /LD /ML
+SHLIB_LIB_SPECS =
+SPICE_EXEC = ngspice.exe
+SUBDIRS =
+TCL_LIB_DIR = $(TCLDIR)\lib
+WISH_EXE = $(TCLDIR)\bin\wish$(TCLVERSION).exe
+WRAPPER_SCRIPT =
+XCIRCUIT_TARGET = $(BUILD_TYPE)
+X_EXTRA_LIBS =
+prefix = $(INSTALLDIR)
+bindir = $(prefix)\bin
+datadir = $(prefix)
+exec_prefix = $(prefix)\bin
+includedir = $(prefix)\include
+libdir = $(prefix)\lib
+libexecdir = $(prefix)\bin
+mandir = $(prefix)\doc
+mkdir_p = mkdir
+
+# Temporary directory (if not overridden by environment variable TMPDIR)
+tmpdir = $(TEMPDIR)
+
+# Directories for app-defaults file and manual page
+PATHNAMES = -DPROG_VERSION=$(VERSION) \
+ -DPROG_REVISION=$(REVISION) \
+ -DCAD_DIR=\"$(prefix:\=/)\" \
+ -DTEMP_DIR=\"$(tmpdir:\=/)\" \
+ -DBUILTINS_DIR=$(BUILTINS_DIR) \
+ -DBUILTINS_FILE=\"$(BUILTINS_FILE)\" \
+ -DUSER_RC_FILE=\"$(USER_RC_FILE)\" \
+ -DPROLOGUE_DIR=$(BUILTINS_DIR) \
+ -DPROLOGUE_FILE=\"$(PROLOGUE_FILE)\" \
+ -DSTARTUP_FILE=\"$(STARTUP_FILE)\" \
+ -DLGF_LIB=\"$(LGF_LIB)\"
+
+xcircuit_SOURCES = elements.c events.c filelist.c files.c \
+ flate.c fontfile.c formats.c functions.c graphic.c \
+ help.c keybindings.c libraries.c menucalls.c \
+ netlist.c ngspice.c opengl.c parameter.c python.c \
+ rcfile.c render.c schema.c selection.c text.c undo.c \
+ tclxcircuit.c tkSimple.c xcircuit.c w32x11.c
+
+xcircuit_DEPEND = $(XC_DEPEND)
+xcircuit_LDADD =
+man_MANS = lib/xcircuit.1
+INCLUDES = $(INC_SPECS)
+
+# Library directory and files
+librarydir = $(datadir)\$(PACKAGE)-$(VERSION)
+scriptsdir = $(datadir)\$(PACKAGE)-$(VERSION)
+USER_RC_FILE = .xcircuitrc
+PROLOGUE_FILE = xcircps2.pro
+LGF_LIB = lgf.lps
+SIGNAL_LIB = signal.lps
+MUSIC_LIB = musiclib.lps
+FONTS_LPS = courier courieriso2 courieriso5 helvetica helveticaiso2 \
+ helveticaiso5 myfont symbol times_roman times_romaniso2 \
+ times_romaniso5
+
+FONTS_XFE = courier courieriso courieriso2 courieriso5 helvetica \
+ helveticaiso helveticaiso2 helveticaiso5 myfont symbol \
+ times_roman times_romaniso times_romaniso2 times_romaniso5
+
+SCRIPTS_PY = spice gettext pagebbox
+WRAPPER_INIT = xcircuit.tcl
+WRAPPER_OBJ = xcircuit$(SHDLIB_EXT)
+WRAPPER_SO = xcircuit.dll
+WRAPPER_SH = xcircuit.bat
+CONSOLE = tkcon.tcl
+CONSOLE_SCRIPT = console.tcl
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj .rc .res
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c "$<"
+
+.rc.res:
+ rc -fo$@ $(XC_CFLAGS) /i$(XCCOMDIR) $<
+
+##################
+# Building rules #
+##################
+
+menudep$(EXEEXT): menudep.$(OBJEXT)
+ $(CC) -Fe$@ $**
+
+menudep.h: menudep$(EXEEXT) menus.h
+ .\menudep$(EXEEXT)
+
+xcwrap.obj: xcwrap.c menudep.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFS) $(PATHNAMES) $(INCLUDES) \
+ xcwrap.c -c -Foxcwrap.$(OBJEXT)
+
+lib\tcl\xcircuit$(SHDLIB_EXT): xcwrap.$(OBJEXT) $(xcircuit_OBJECTS) $(xcircuit_DEPEND)
+ -$(RM) lib\xcircuit$(SHDLIB_EXT)
+ $(CC) $(CFLAGS) $(SHLIB_CFLAGS) -Fe$@ $(LDDL_FLAGS) xcwrap.$(OBJEXT) \
+ $(xcircuit_OBJECTS) $(xcircuit_LDADD) $(LDFLAGS) \
+ $(X_EXTRA_LIBS) $(EXTRA_LIBS) $(LIBS) $(EXTRA_LIB_SPECS) \
+ $(SHLIB_LIB_SPECS)
+
+xcircuit$(EXEEXT): $(xcircuit_OBJECTS) $(xcircuit_DEPEND)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCLUDES) $(xcircuit_OBJECTS) \
+ -Fe$@ $(LDFLAGS) $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS) shell32.lib \
+ /link /SUBSYSTEM:CONSOLE
+
+xcircexec$(EXEEXT): xcircexec.$(OBJEXT)
+ -$(RM) .\xcircexec$(EXEEXT)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(PATHNAMES) $(INCLUDES) \
+ xcircexec.c -Fe$@ $(LDFLAGS) \
+ $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS)
+
+xcircuit-win32$(EXEEXT): xcircuit-win32.c resources.res
+ $(CC) $(CFLAGS) $(CPPFLAGS) \
+ -DWISH_EXE=L\"$(WISH_EXE:\=/)\" \
+ -DBUILTINS_DIR=L$(BUILTINS_DIR) \
+ $(INCLUDES) xcircuit-win32.c resources.res \
+ -Fe$@ $(LDFLAGS) $(LIBS) $(LIB_SPECS) $(EXTRA_LIB_SPECS) shell32.lib advapi32.lib
+
+tcl:
+ @echo Making tcl library object
+ $(MAKE) lib\tcl\xcircuit$(SHDLIB_EXT)
+ $(MAKE) lib\$(INTERP_PATH)\$(WRAPPER_SH)
+ $(MAKE) lib\$(INTERP_PATH)\$(WRAPPER_INIT)
+ $(MAKE) xcircexec$(EXEEXT)
+ $(MAKE) xcircuit-win32$(EXEEXT)
+
+win32:
+ @echo Making win32
+!if "$(USE_WIN32_COM)" != "0"
+ cd $(XCCOMDIR) && $(MAKE) && cd ..
+!endif
+ $(MAKE) xcircuit$(EXEEXT)
+
+help.c: menudep.h
+menucalls.c: menudep.h
+rcfile.c: menudep.h
+schema.c: menudep.h
+xcircuit.c: menudep.h
+parameter.c: menudep.h
+python.c: menudep.h
+tclxcircuit.c: menudep.h
+resources.rc: lib/pixmaps/xcircuit.ico
+
+$(PP): pp.c
+ $(CC) -Zi pp.c
+
+lib\$(INTERP_PATH)\$(WRAPPER_SH): $(PP) lib\$(INTERP_PATH)\$(WRAPPER_SH).in
+ $(PP) $(PATHNAMES) -DXCLIBDIR=\"$(librarydir:\=/)\" \
+ -DWRAPPER_INIT=\"$(WRAPPER_INIT)\" -DCONSOLE=\"$(CONSOLE)\" \
+ -DCONSOLE_SCRIPT=\"$(CONSOLE_SCRIPT)\" \
+ -DTCLLIBDIR=\"$(TCL_LIB_DIR:\=/)\" \
+ -DWISH_EXE=\"$(WISH_EXE:\=/)\" \
+ lib/$(INTERP_PATH)/$(WRAPPER_SH).in > $@
+
+lib\$(INTERP_PATH)\$(WRAPPER_INIT): $(PP) lib\$(INTERP_PATH)\$(WRAPPER_INIT).in
+ $(PP) $(PATHNAMES) -DLIBDIR=\"$(librarydir:\=/)\" \
+ lib/$(INTERP_PATH)/$(WRAPPER_INIT).in > $@
+
+lib\xcircuit.1: $(PP) lib\xcircuit.1.in
+ $(PP) -DLIBDIR=\"$(libdir)\" \
+ -DSCRIPTSDIR=\"$(scriptsdir)\" \
+ -DLGF=1 -DPYTHON=0 -DTCL=1 -DNOINTERP=0 \
+ lib\xcircuit.1.in > $@
+
+install-data-local: lib/xcircuit.1
+ @echo "Installing library files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)
+ cd lib
+ for %i in ($(PROLOGUE_FILE) *.lps) do $(INSTALL_DATA) %i $(DESTDIR)$(librarydir)
+ cd ..
+ cd lib\$(INTERP_PATH)
+ for %i in ($(STARTUP_FILE)) do $(INSTALL_DATA) %i $(DESTDIR)$(librarydir)
+ cd ..\..
+ @echo "Installing .lps font files"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)\fonts
+ for %i in ($(FONTS_LPS)) do $(INSTALL_DATA) lib\fonts\%i.lps $(DESTDIR)$(librarydir)\fonts
+ @echo "Installing .xfe font files"
+ for %i in ($(FONTS_XFE)) do $(INSTALL_DATA) lib\fonts\%i.xfe $(DESTDIR)$(librarydir)\fonts
+ @echo "Installing scripts (if option enabled)"
+
+# Note that MacOS/Fink uses SHDLIB_EXT = .dylib but Tcl expects .so anyway.
+# So we make a symbolic link if SHDLIB_EXT != .so
+
+install-tcl: xcircexec$(EXEEXT) lib/$(INTERP_PATH)/$(WRAPPER_OBJ) lib/$(INTERP_PATH)/$(WRAPPER_SH) lib/$(INTERP_PATH)/$(WRAPPER_INIT) xcircuit-win32$(EXEEXT)
+ if exist $(prefix) $(RMDIR) $(prefix)
+ @echo "Installing standard XCircuit library files"
+ $(MAKE) $(AM_MAKEFLAGS) install-data-local
+ @echo "Installing Tcl files"
+ cd lib\$(INTERP_PATH)
+ for %i in ($(WRAPPER_OBJ) *.tcl) do $(INSTALL_DATA) %i $(DESTDIR)$(librarydir)
+ cd ..\..
+ $(INSTALL_DATA) xcircexec$(EXEEXT) $(DESTDIR)$(librarydir)
+ @echo "Installing pixmap images"
+ $(mkinstalldirs) $(DESTDIR)$(librarydir)\pixmaps
+ cd lib\pixmaps
+ for %i in (*.gif *.xbm) do $(INSTALL_DATA) %i $(DESTDIR)$(librarydir)\pixmaps
+ cd ..\..
+ @echo "Installing shell script as xcircuit executable"
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) lib\$(INTERP_PATH)\$(WRAPPER_SH) $(DESTDIR)$(bindir)
+ $(INSTALL_DATA) xcircuit-win32$(EXEEXT) $(DESTDIR)$(bindir)
+
+install-win32: xcircuit$(EXEEXT)
+ if exist $(prefix) $(RMDIR) $(prefix)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-local "librarydir=$(prefix)"
+ $(INSTALL_DATA) xcircuit$(EXEEXT) $(DESTDIR)$(prefix)
+
+clean:
+ -$(RM) lib\$(INTERP_PATH)\$(WRAPPER_OBJ) lib\$(INTERP_PATH)\$(WRAPPER_SH)
+ -for %e in (ilk exp pdb lib) do @if exist lib\$(INTERP_PATH)\xcircuit.%e $(RM) lib\$(INTERP_PATH)\xcircuit.%e
+ -$(RM) lib\$(INTERP_PATH)\$(WRAPPER_INIT)
+ -for %f in (*.$(OBJEXT) xcircexec$(EXEEXT) lib\xcircuit.1 xcircuit$(EXEEXT) xcircuit.suo) do $(RM) %f
+ -for %e in (aps res) do $(RM) resources.%e
+ -for %e in (ilk exp pdb lib) do @if exist xcircexec.%e $(RM) xcircexec.%e
+ -for %e in (ilk exp pdb lib) do @if exist xcircuit.%e $(RM) xcircuit.%e
+ -for %e in (ilk exp pdb lib) do @if exist pp.%e $(RM) pp.%e
+ -for %e in (ilk exp pdb lib exe) do @if exist xcircuit-win32.%e $(RM) xcircuit-win32.%e
+ -$(RM) menudep$(EXEEXT) menudep.h
+ -$(RM) pp$(EXEEXT)
+ -$(RM) *.pdb
+ -$(RM) *~
+!if "$(BUILD_TYPE)" == "win32" && "$(USE_WIN32_COM)" != "0"
+ cd $(XCCOMDIR) && $(MAKE) clean && cd ..
+!endif
+
+$(ALL_TARGET):
+ $(MAKE) $(XCIRCUIT_TARGET)
+
+$(INSTALL_TARGET):
+ (MAKE) install-tcl
+
+examples: all
+!if "$(BUILD_TYPE)" == "win32" && "$(USE_WIN32_COM)" != "0"
+ cd $(XCCOMDIR) && $(MAKE) examples && cd ..
+!endif
+
+!if "$(BUILD_TYPE)" == "win32"
+xcircuit.h: xcwin32.h
+xcwin32.c: xcircuit.h
+!else
+xcircuit.h: tkwin32.h
+!endif
+elements.c: xcircuit.h
+events.c: xcircuit.h
+filelist.c: xcircuit.h
+files.c: xcircuit.h
+flate.c: xcircuit.h
+fontfile.c: xcircuit.h
+formats.c: xcircuit.h
+functions.c: xcircuit.h
+graphic.c: xcircuit.h
+help.c: xcircuit.h
+keybindings.c: xcircuit.h
+libraries.c: xcircuit.h
+menucalls.c: xcircuit.h
+netlist.c: xcircuit.h
+ngspice.c: xcircuit.h
+opengl.c: xcircuit.h
+parameter.c: xcircuit.h
+python.c: xcircuit.h
+rcfile.c: xcircuit.h
+render.c: xcircuit.h
+schema.c: xcircuit.h
+selection.c: xcircuit.h
+text.c: xcircuit.h
+undo.c: xcircuit.h
+xcircuit.c: xcircuit.h
+xtgui.c: xcircuit.h
+xtfuncs.c: xcircuit.h
+!if "$(BUILD_TYPE)" == "win32" && "$(USE_WIN32_COM)" != "0"
+resources.rc: $(XCCOMDIR)/XCCom.tlb
+!endif
diff --git a/README b/README
new file mode 100644
index 0000000..d2d3c55
--- /dev/null
+++ b/README
@@ -0,0 +1,316 @@
+XCircuit v3.8
+-----------------------------------------------------------------------------
+
+An X11 drawing program [especially for circuit schematics]
+(c) 2013 Tim Edwards (see copyright notice in ./COPYRIGHT)
+August 1993 -- January 2013
+-----------------------------------------------------------------------------
+
+Compilation/Installation notes:
+(Online version at http://opencircuitdesign.com/xcircuit/install.html)
+
+1) All compile-time features are set during the ./configure process.
+ Run "./configure --help" for a list of configure options. For most
+ users, the relevant options are the following:
+
+ --with-tcl Configure xcircuit as an extension to Tcl/Tk. Tcl
+ becomes the default interpreter. Option is mutually
+ exclusive with "--with-python". A feature of this
+ version is that the interpreter is available from
+ the calling terminal concurrently with the GUI.
+ Another feature of this version is that the graphics
+ are handled by Tk widgets instead of the troublesome
+ "Xw" widgets in the distribution. As of version
+ 3.1.7 where most of the bugs have been resolved,
+ use of this option is highly encouraged.
+
+ --with-python Configure xcircuit with the embedded Python
+ interpreter. Option "--with-python" is disabled
+ by default, and has no effect if "--with-tcl" has
+ been selected. The python interface is less
+ well-developed than the Tcl interface. If you do
+ not intend to make use of the interpreter
+ command-line interface, there is probably no reason
+ to select this.
+
+ --prefix=PREFIX Location to install xcircuit. Defaults to
+ /usr/local/. The executable goes to /usr/local/bin/,
+ man pages to /usr/local/man/man1/, and everything
+ else to /usr/local/lib/xcircuit-VERSION/. Defaults
+ can be separated by explicitly declaring
+ --exec-prefix=DIR, --mandir=DIR, and --libdir=DIR.
+
+ The following option is experimental at present and will be changed to
+ be enabled by default when the package is deemed stable:
+
+ --enable-asg Configure XCircuit with the automatic schematic
+ generation (ASG) package. This package allows
+ XCircuit to read SPICE decks and produce schematics
+ from them. Future functions include reading EDIF
+ netlists (from Verilog and/or VHDL), and automatially
+ routing layouts.
+
+ The following options are probably not worth messing with:
+
+ --disable-lgf Save space by not compiling the compatibility with
+ "analog" and "diglog" .lgf-format files.
+
+ --disable-schema Don't compile the schematic capture system. This
+ is a major feature of xcircuit, so disabling it is
+ not recommended. However, you may do so if you
+ anticipate having no need for circuit netlists.
+
+ There are some other options which can be supplied to the "configure"
+ command-line which should only be needed in rare circumstances. Most
+ users can ignore these.
+
+ --with-tcl=DIR Tcl can be enabled with "--with-tcl" or
+ "--with-tcl=yes", and the Tcl library and include
+ directories will be automatically searched. For
+ Tcl/Tk installations which cannot be found by the
+ automatic search, DIR should be the directory
+ containing "tclConfig.sh".
+
+ --with-tk=DIR Enabling Tcl for XCircuit implies "--with-tk".
+ However, for Tk installations which cannot be
+ found by automatic search and which cannot be
+ found by specifying "--with-tcl=DIR", DIR should
+ point to the directory containing "tkConfig.sh".
+
+ --with-python=DIR If the configure step cannot find a Python
+ interpreter, it can be explicitly referenced.
+ Requires the Python library (libpythonVERSION.a
+ or libpythonVERSION.so) and the python include
+ file Python.h. The Python option uses the Python
+ language as an interpreter for xcircuit.
+
+ --disable-double-buffer
+ This option is almost wholly deprecated due to the
+ speed of modern processors. However, if you have
+ problems with slow rendering, you might find it
+ useful.
+
+ --with-xpm=DIR If the configure step cannot find the XPM package,
+ it can be explicitly referenced. The XPM package
+ enables the toolbar and an icon when xcircuit is
+ iconified.
+
+ --with-gs=DIR If the configure step cannot find ghostscript,
+ it can be explicitly referenced. The Ghostscript
+ option allows any PostScript file to be rendered
+ on the xcircuit background and saved with the
+ xcircuit file.
+
+ NOTE: When xcircuit went from "imake" to GNU make, the default install
+ directory changed from /usr/local/lib to /usr/local/share/. Since all
+ the other CAD tools xcircuit works with install by default to
+ /usr/local/lib, xcircuit version 3.1 has reverted to /usr/local/lib for
+ reasons of compatibility. See item (4) below, "uninstall".
+
+2) Compile with the usual GNU-compile steps:
+
+ ./configure
+ make
+ make install
+
+ The final step must be done as root if you are installing to default
+ locations (/usr/local/lib and /usr/local/bin). XCircuit can be run
+ in test mode before installation (see item (3), below).
+ For the Tcl/Tk version the make steps are the same, assuming that
+ Tcl/Tk libraries and include files can be found on the system. If
+ you specifically *don't* want the Tcl/Tk version, then do:
+
+ ./configure --without-tcl
+ make
+ make install
+
+ If you want to test before installing, do the following (csh/tcsh
+ version; see item (3) for changes to line 4 for bash/ksh/sh):
+
+ ./configure
+ make
+ setenv XCIRCUIT_LIB_DIR ./lib
+ setenv XCIRCUIT_SRC_DIR ./lib/tcl
+ lib/tcl/xcircuit.sh
+
+ after which, if all goes well, you can do "make install".
+
+3) NOTE: To test xcircuit before installation, set environment variable
+
+ setenv XCIRCUIT_LIB_DIR ./lib (csh, tcsh)
+ setenv XCIRCUIT_SRC_DIR ./lib/tcl
+
+ export XCIRCUIT_LIB_DIR=./lib (bash)
+ export XCIRCUIT_SRC_DIR=./lib/tcl
+
+ before running the xcircuit executable.
+
+4) Uninstall:
+ If you have compiled previous versions of xcircuit, the only thing you
+ need to do to uninstall these versions is to remove the directory tree
+ at /usr/local/share/xcircuit-(version) or /usr/local/lib/xcircuit-(version)
+ for any version numbers which are not current.
+
+5) HP/IRIX users: If the "make" process dies with an error creating the man
+ page, something like
+
+ /usr/ccs/bin/m4:xcircuit.1.m4:911 more than 4096 chars of argument text
+
+ be sure to use GNU m4. This can be done during the configure process
+ (using appropriate substitutions) with the following command:
+
+ M4=<path to GNU m4> ./configure [options]
+
+6) 64-bit system users: Proper compile may require specifically using
+ configure option "--x-libraries=" to point to 64-bit libraries.
+ This has been fixed for the AMD Opteron under Fedora Core; other
+ 64-bit systems are untested.
+
+-----------------------------------------------------------------------------
+
+Shared Python Library:
+
+ NOTE: The XCircuit build will be *much* smaller if you have a shared
+ python library. However, the build instructions as of Python-2.1c2
+ don't include instructions for building a shared library under linux.
+ Here's how you do it:
+ 1) In the Makefile: set
+ LDLIBRARY=libpython2.1.so
+ 2) Also in the Makefile:
+ Add a case for libpython$(VERSION).so which looks
+ exactly like the case statement for unixware:
+
+ linux) \
+ $(LDSHARED) -o $@ $(LIBRARY_OBJS) \
+ ;; \
+
+ 3) Make until error (can't find libpython2.1.so)
+ 4) Copy or move libpython2.1.so to /usr/local/lib or /usr/lib
+ 5) Run (as root!) ldconfig -v -n /usr/local/lib (or whereever
+ you just put the shared library) and confirm that it
+ found libpython2.1.so.
+ 6) Finish "make" (should run to normal completion).
+
+ On my system, this is the difference between a 4MB xcircuit executable
+ and a 1.5MB executable. That's a big difference! Of course, Python
+ purists would say I should be embedding xcircuit in python, not the
+ other way around, then what need do I have for a shared library,
+ anyway?
+
+ Python source (and other information relating to Python) can be found
+ at www.python.org. The Python interpreter is recommended, as XCircuit
+ eventually will rely on Python to handle writing netlists, for
+ flexibility in formatting.
+
+-----------------------------------------------------------------------------
+
+Extras:
+
+ The file examples/.xcircuitrc shows how to make a home-directory file
+to alter the behavior of xcircuit on startup. It shows how to change the
+color scheme, add new fonts, override the default libraries, and change
+the editing behavior for polygons. Note that if xcircuit is built with
+embedded Python, the syntax for .xcircuitrc will be Python syntax, and
+may use any Python commands in addition to the commands which hook into
+xcircuit functions. The file examples/test.py is a sample Python script
+which features use of Python to create animated graphics within the
+xcircuit window, shows how to access on-screen elements and change
+their properties, and contains convenience function definitions for
+manipulating xcircuit elements.
+
+ Other files in the examples directory show how xcircuit can be
+used to draw various things, from a simple circuit schematic
+(vcoblock.ps) to an entire publishable-quality page of music
+(prelude.ps), plus an example of a fancy page border for slide
+presentations.
+
+ The files psfiles/signal.lps and psfiles/musiclib.lps are examples
+of alternate or additional object libraries. The library file lgf.lps
+is used primarily by the lgf-to-ps conversion routines, but has some
+different circuit objects in it.
+
+ The file psfiles/fonttest.ps is a short PostScript program you can
+use to get your printer to give you the names of all the built-in fonts
+that it knows about, which is useful because if you add a font name to
+xcircuit, the spelling has to be exactly correct or else the printer
+won't recognize it.
+
+ The file examples/gettext.py is a sample Python script which adds
+a Python command called "gettext(filename)". gettext(filename) reads
+in file "filename", which should be an ASCII text file, and turns it
+into a label in XCircuit positioned at the cursor position.
+
+-----------------------------------------------------------------------------
+
+X Resources:
+
+ The Tcl/Tk version of XCircuit does not use the X resources but
+picks up resources from the file "resource.tcl" in the run-time
+library path (e.g., /usr/local/lib/xcircuit-3.8/resource.tcl). The
+resource names are the same as those described below but are specified
+using the Tk "option add" command.
+
+ The color scheme of xcircuit has a default setup, but accepts
+alternate color schemes using the following keywords which can be put
+in the X Defaults (.Xdefaults, .Xresources) file:
+
+ Resource name Description Default
+ ------------------- ---------------------------- -------
+ xcircuit*foreground color of buttons and popups; White
+ xcircuit*background background of buttons & popups; DarkSlateGray
+ xcircuit.foreground drawing area foreground; White
+ xcircuit.background drawing area background; Black
+ xcircuit*gridcolor color of the grid lines; Gray40
+ xcircuit*snapcolor color of the snap-to points; Red
+ xcircuit*selectcolor color of a selected object; Gold
+ xcircuit*querycolor to differentiate multiple objects; Turquoise
+ xcircuit*axescolor color of the x, y axes; NavajoWhite4
+ xcircuit*offbuttoncolor text color of an inoperable button; Gray70
+ xcircuit*auxiliarycolor text cursor and other things Green
+ xcircuit*barcolor color of panning bars Tan
+
+A secondary color scheme (for example, black-on-white) can be specified by
+adding "2" to each of the above resource names. For example:
+
+ xcircuit*foreground2 color of every object drawn; Black
+ xcircuit*background2 screen background color; White
+
+Other resources accepted by xcircuit are:
+
+ xcircuit*width width of the drawing area (pixels); 600
+ xcircuit*height height of the drawing area; 500
+
+Normally, you will want to put the defaults in /usr/lib/X11/app-defaults.
+If you do not have root access, you will want to have them in your own
+home .Xdefaults file. If the file is not found by xcircuit, the program
+will use its default color schemes, the main one being black-on-white,
+and the alternate being white-on-dark-gray.
+
+-----------------------------------------------------------------------------
+
+Altering, Copying, and/or Redistributing XCircuit:
+
+ XCircuit is distributed under the GNU GPL (General Public Licence). See
+ the file COPYRIGHT in the top-level directory for details.
+
+-----------------------------------------------------------------------------
+
+XCircuit Home Page:
+ "http://opencircuitdesign.com/xcircuit/"
+
+Online tutorial:
+ "http://opencircuitdesign.com/xcircuit/tutorial/tutorial.html"
+
+Schematic capture tutorial:
+ "http://opencircuitdesign.com/xcircuit/tutorial/tutorial2.html"
+
+-----------------------------------------------------------------------------
+
+Contact address (check the website above for a current address):
+ R. Timothy Edwards
+ 22815 Timber Creek Lane
+ Clarksburg, MD 20871
+
+ Phone: (301) 528-5030 (home)
+
+-----------------------------------------------------------------------------
diff --git a/README.ISOLatin2 b/README.ISOLatin2
new file mode 100644
index 0000000..6b17aa0
--- /dev/null
+++ b/README.ISOLatin2
@@ -0,0 +1,108 @@
+-------------------------------------------------------------------
+ISO-Latin2 through ISO-Latin6 encoded fonts in xcircuit
+-------------------------------------------------------------------
+
+Xcircuit supports ISO-Latin2 encoding (Eastern Europe) since
+version 2.0a9. This feature is not set up by default because
+PostScript output is not (yet) possible without the use of the
+program "ogonkify". This support has been extended to other
+Latin encodings: ISO-Latin5 (Turkish) version 2.0a10 (6/14/99).
+
+Here's how to get ISO-Latin2 and other Latin encodings in
+xcircuit:
+
+-------------------------------------------------------------------
+
+1) Edit file lib/startup.script. Uncomment (remove the leading
+ '%' from) lines 15-17 (the ISO-Latin2 font encoding files). Do
+ this before "make install"; otherwise, the file will be in
+ (depending on the definition of XCIRCUIT_LIB_DIR in the
+ Makefile) /usr/local/lib/xcircuit-3.6/startup.script.
+ In the Tcl/Tk version, this file is lib/tcl/xcstartup.tcl,
+ or, after installation, /usr/local/lib/xcircuit-3.6/xcstartup.tcl.
+
+2) When creating text, be sure to select "Text->Encoding->
+ ISO-Latin2" from the menu. This can be enabled by default
+ simply by having a .xcircuitrc file in your home directory
+ containing a line such as:
+
+ set default font Times-RomanISO2
+
+3) To get proper PostScript output on a printer, you will need to
+ have the (separate) program "ogonkify", found at:
+
+ http://www.dcs.ed.ac.uk/home/jec/ogonkify/
+ ftp://ftp.dcs.ed.ac.uk/pub/jec/programs
+
+ "ogonkify" is necessary because PostScript does not contain
+ ISO-Latin2 encoding by default. The accents such as the caron
+ and ogonek exist in the font definition, but the correct
+ alignments for putting them together need to be provided.
+ Ogonkify does this best.
+
+4) Every file containing ISO-Latin2 text must be postprocessed
+ through "ogonkify" using the following command, before it will
+ print correctly on a PostScript printer:
+
+ ogonkify -e L2 -ATH file.ps | perl -ne \
+ 's/StandardEncoding/ISOLatin2Encoding/g;\
+ s/ exch defi/ISO2 exch defi/g;print' > file.out.ps
+
+ Switches: -A does Courier, -T does Times-Roman, and -H does
+ Helvetica; use only what's necessary to keep the output file
+ smaller. "-e L2" signifies Latin2 encoding; this is not
+ strictly necessary as ogonkify defaults to L2. All other
+ Latin encodings require the -e switch.
+
+ Note that the output is piped through a couple of perl
+ commands. This may seem overly complicated; the first
+ substitution corrects a bug in ogonkify output (which may
+ disappear from releases of ogonkify in the future). The
+ second substitution allows xcircuit to specify the ISO-Latin2
+ encodings separately from ISO-Latin1 and Adobe Standard
+ encodings, so that any and all encodings can be "mixed and
+ matched" in the same file and even the same label.
+
+5) In a nutshell: xcircuit defines each ISO-Latin2 font name as
+ the original name followed by the string "ISO2". Xcircuit
+ can then load the file and interpret the font encodings
+ unambiguously. However, the new ISO-Latin2 font names are not
+ defined by PostScript. Running "ogonkify" in the manner shown
+ above will add a true PostScript definition for each of the
+ ISO-Latin2 fonts. Without "ogonkify", a PostScript printer
+ or interpreter will either produce an error or else substitute
+ a default font for the unrecognized one.
+
+6) The "ogonkification" of the file will not affect xcircuit's
+ ability to read it back into the program. xcircuit will
+ continue to display the ISO-Latin2 text correctly regardless of
+ whether or not the file has been run through "ogonkify".
+ However, the header material inserted by "ogonkify" will be
+ lost every time xcircuit writes the file back out.
+
+7) Other ISO-LatinX encodings: Currently ISO-Latin5 is supported,
+ and additional encodings will be created as I get requests for
+ them. Follow the instructions above for ISO-Latin2, but replace
+ all occurences of "2" with "5".
+
+ e.g.,
+
+ ogonkify -e L5 -ATH file.ps | perl -ne \
+ 's/StandardEncoding/ISOLatin5Encoding/g;\
+ s/ exch defi/ISO5 exch defi/g;print' > file.out.ps
+
+ and add lines
+
+ % times_romaniso5.xfe loadfontencoding
+ % courieriso5.xfe loadfontencoding
+ % helveticaiso5.xfe loadfontencoding
+
+ to psfiles/builtins.lps (or /usr/local/lib/xcircuit-2.0/builtins.lps, if
+ already installed).
+
+8) Version 3.6.36 corrects a long-existing mistake in which only X11 keysyms
+ 0-255 are accepted as keyboard-entry. By converting the X11 keysyms to
+ keycodes, ISO-Latin2 characters can be typed directly into XCircuit from
+ the keyboard. It would be nice, though, if XCircuit would auto-detect
+ the expected encoding from the keysym and insert the proper font switch,
+ loading fonts if necessary.
diff --git a/README.Tcl b/README.Tcl
new file mode 100644
index 0000000..9a78bc7
--- /dev/null
+++ b/README.Tcl
@@ -0,0 +1,732 @@
+Tcl command summary (ASCII text version)
+-------------------------------------------------
+This list can be found in HTML format at URL:
+ http://opencircuitdesign.com/xcircuit/tcl.html
+-------------------------------------------------
+
+I. Built-in commands (C source)
+--------------------------------
+A. Elements: Main command to create and manipulate objects. "element" is
+ partly a superset of the individual elements, when the command is
+ given a <handle> value and the element type is unknown. A <handle>
+ is an integer pointer to the element's location in memory. The
+ notation <handle...> represents a list of handles to elements.
+ <handle> can also be the keyword "selected", in which case it
+ implies all selected elements. The <handle> is represented as a
+ new Tcl type called "handle", and has an "H" followed by an 8-digit
+ hexidecimal number. This distinguishes it from integers and
+ allows the command line to be parsed correctly. It also discourages
+ the practice of manipulating handles, as arithmetic cannot be
+ performed directly on handle types.
+
+ One option, "type", does not apply to individual elements.
+ When no <handle> is supplied, the option operates on all currently
+ selected elements in the drawing. If no <handle> is supplied and
+ no elements are currently selected, then the program goes into an
+ interactive mode, prompting for an element to select and apply the
+ option to. Option "deselect" behaves differently in that
+
+ 1. element [<handle...>] type
+ Returns the type of the element, which may be one of "label",
+ "polygon", "instance", "spline", "path", or "arc".
+
+ 2. <element> [<handle...>] <option>
+ Where <element> may be any of "element", "label", "polygon",
+ "instance", "spline", "path", or "arc".
+ Options are:
+
+ <element> [<handle...>] deselect
+ deselect the indicated element(s).
+ <element> [<handle...>] parameter <option...>
+ Option may be one of the following:
+ a) allowed
+ List the parameter types which are allowed for the
+ indicated element type.
+ b) make <type> [<key>]
+ Generate a parameter of the indicated type for
+ the indicated element. <type> may be one of:
+ "position", "substring", "x position", "y position",
+ "style", "justification", "start angle", "end angle",
+ "radius", "minor axis", "rotation", "scale", "linewidth",
+ or "color". Items with more than one word must be
+ quoted. The initial value given to the parameter is
+ the default. <key> is a unique name given to the
+ parameter. It is necessary for substring parameters but
+ may be omitted for other parameter types.
+ c) set <key> <value> [-forward]
+ Change the value of the parameter with key <key>. This
+ assumes that the parameter exists; if not, option "make"
+ must be used.
+ c) get [<type|key>] [-forward]
+ List the parameters of the indicated element(s). If
+ <type> is given, get the instance value of the parameter(s)
+ of type <type>. If <key> is given, then get the instance
+ value of the parameter with key <key>. If the parameter
+ takes the default value, a null list is returned. If the
+ parameter type does not exist for the element, an error is
+ generated.
+ e) default <type|key> [-forward]
+ Get the default value of the indicated parameter, if <key>
+ specified, or all parameters of the indicated type, if
+ <type> is specified.
+ f) forget <type|key> [-forward]
+ Delete the indicated parameter, if <key> is specified, or
+ delete all parameters of the indicated type, if <type> is
+ specified. The parameter is removed entirely from the
+ object.
+
+ Note that several commands take the optional argument "-forward".
+ The "-forward" argument applied only to selected object
+ instances, and indicates a forward-referenced parameter, that is,
+ a parameter belonging to the object of the selected instance,
+ and not the top-level object.
+ <element> [<handle...>] delete
+ Deletes the indicated element(s).
+ <element> [<handle...>] copy [relative] <position>
+ Makes a copy of the indicated element(s). <position> is a list of
+ 2 elements representing absolute X and Y positions, unless the
+ keyword "relative" is present, in which case they represent positions
+ relative to the current element position. If more than one element
+ is specified, the position *must* be indicated as relative.
+ <element> [<handle...>] move [relative] <position>
+ Moves the indicated element(s). <position> is a list of
+ 2 elements representing absolute X and Y positions, unless the
+ keyword "relative" is present, in which case they represent positions
+ relative to the current element position. If more than one element
+ is specified, the position *must* be indicated as relative.
+ <element> [<handle...>] flip horizontal|vertical [<position>]
+ Flips the indicated element(s) around the horizontal or vertical axis.
+ If <position> is specified, then element or element group will be
+ flipped around the indicated point. <position> may be a single
+ number, representing an X value for horizontal flips and a Y value
+ for vertical flips.
+ <element> [<handle...>] rotate <angle> [<position>]
+ Rotates the indicated element(s) by the specified angle (in degrees).
+ Positive angles are clockwise, negative angles are counterclockwise.
+ If <position> is specified, then element or element group will be
+ rotated around the indicated point.
+ <element> [<handle...>] edit
+ Puts the specified element(s) into interactive edit mode.
+ <element> [<handle...>] select
+ Selects the specified element(s).
+ <element> [<handle...>] snap [<direction>]
+ Snaps the indicated elements onto the snap grid. If <direction> is
+ specified (n, s, e, w, ne, nw, se, or sw), elements will be snapped
+ in that direction. Otherwise, elements will be snapped to the
+ closest point.
+ <element> [<handle...>] raise [<number>]
+ Raise the position of the indicated element(s) toward the drawing
+ front (end of list; last to be drawn). If <number> is specified,
+ it is raised in front of the next <number> elements in the list.
+ If no <number> is specified, it is raised to the front of the drawing.
+ <element> [<handle...>] lower [<number>]
+ Lower the position of the indicated element(s) toward the drawing
+ back (beginning of list; first to be drawn). If <number> is specified,
+ it is lowered behind the next <number> elements in the list. If no
+ <number> is specified, it is lowered to the back of the drawing.
+ <element> [<handle1> [<handle2>]] exchange
+ Exchanges the positions of the two elements in the list. If no
+ handles are specified, then exactly one or two objects must be
+ previously selected. If only one handle is specified or only
+ one object previously selected, the behavior is to raise it to the
+ front of the drawing, unless it is already at the front of the
+ drawing, in which case it is moved to the back.
+ <element> [<handle...>] color [<idx>]
+ Sets the color of the specified element(s) to value <idx>, an index
+ into xcircuit's color table. With no arguments, returns the color
+ of the indicated element.
+
+ 3. <path_element> [<handle...>] <option>
+ Where <path_element> may be any of "polygon", "spline", "arc", or "path".
+ Options are:
+ <path_element> [<handle...>] border [<value>]
+ Set the border linewidth scaling to floating-point value <value>,
+ or return the current scale if <value> is not given.
+ <path_element> [<handle...>] border [<type>]
+ Set the border style of the indicated element(s) to <type>, or return
+ the type (or list of types) if <type> is not given. <type> may be one
+ of "solid", "dashed", "dotted", or "closed"
+ <path_element> [<handle...>] fill [<type>]
+ Set the fill style of the indicated element(s) to <type>, or return
+ the type (or list of types) if <type> is not given. <type> may be
+ a fill percentage (representing a stipple pattern) or the keyword
+ "opaque".
+
+ 4. <segmented_element> [<handle...>] point <option>
+ Where <segmented_element> may be any of "polygon", "spline", or "path".
+ Options are:
+ <segmented_element> [<handle...>] point [<number>] insert [after|before]
+ [relative] [<position>]
+ Insert a new point before or after point <number> or the current
+ point if editing interactively. If non-interactive, the point must
+ be given a position as a list of size 2, which is either an absolute
+ position, or a relative position if the keyword "relative" is given.
+ <segmented_element> [<handle...>] point [<number>] delete [<number>]
+ Delete point <number>, or the current point if editing interactively.
+ <segmented_element> [<handle...>] point [<number>] parameter
+ Parameterize the position of point <number>, or the current point
+ if editing interactively.
+ <segmented_element> [<handle...>] point [<number>] break
+ Break the element at point <number>, or at the current point if
+ editing interactively. Returns a handle to the new element
+ generated by the break.
+ <segmented_element> [<handle...>] point [<number>] next
+ Return the point following point <number>, if specified, or move
+ to the next point if editing interactively.
+ <segmented_element> [<handle...>] point [<number>] snap [<direction>]
+ Snap the indicated point <number> to the snap-to grid. Snapping
+ is in the indicated direction, if supplied, or the closest point,
+ if not. <direction> may be one of "n", "s", "e", "w", "ne", "nw",
+ "se", or "sw".
+
+ 4. instance [<handle...>] <option>
+ instance make <object_name> [<position>]
+ instance [<handle>] push
+ Edit the indicated instance by "pushing" down in the hierarchy.
+ Exactly one handle must be specified or one object instance
+ selected prior to executing the command. This command operates
+ like "object push" except that if any values in the object are
+ parameterized, the instance values will be changed, not the default
+ values.
+ instance [<handle...>] scale [<value>]
+ Change the scale of the indicated instance to <value>. If no value
+ is specified, return the current scale of the instance.
+ 5. label [<handle...>] <option>
+ label make
+ Interactively create a new label element.
+ label make [pin|global|info] <string_list> <position>
+ Create a new label element with the text specified by <string_list>
+ and origin at <position>. Optional keywords "pin", "global", or
+ "info" make the label a schematic pin type. <string_list> is a
+ list of string parts or a single string. String parts
+ label [<handle...>] append <string_list>
+ Add <string_list> to the end of the indicated label.
+ label [<handle...>] insert <position> <string_list>
+ Insert <string_list> into the indicated label at the indicated position.
+ label [<handle...>] delete <start> <end>
+ Delete a substring of the indicated label beginning at position <start>
+ and ending before position <end>.
+ label [<handle...>] get <start> <end>
+ Return the substring (list) between beginning at position <start> and
+ ending before position <end>
+ label [<handle...>] scale [<value>]
+ Change the scale of the indicated label. Return the scale if <value>
+ is not specified.
+ label [<handle...>] justify [<hjust>] [<vjust>]
+ Change the justification of the indicated label, where <hjust> may be
+ one of "left", "center", "right", and <vjust> may be one of "top",
+ "middle", or "bottom". If neither <hjust> nor <vjust> is specified,
+ command returns a list of size 2 containing the horizontal and
+ vertical justifications.
+ label [<handle...>] flipinvariant [true|false]
+ Set the flip-invariance of the indicated label. If no value is
+ supplied, return the state of the flip-invariance on the label.
+ label [<handle...>] style [<font_style>]
+ Set the label style to <font_style>, which may be one of "normal",
+ "bold", "italic", or "bolditalic". If no style is specified,
+ return the current font style.
+ label [<handle...>] family [<font_family>]
+ Set the label font family to <font_family>. If no font family
+ is specified, return the current font family.
+ label [<handle...>] encoding [<font_encoding>]
+ Set the label encoding to <font_encoding>, which may be one of
+ "standard", "special", or "ISO-Latin1" through "ISO-Latin6".
+ If no font encoding is specified, return the current font encoding.
+ 6. polygon [<handle...>] <option>
+ polygon make [box]
+ Interactively create a new polygon element. A rectangle is
+ created if "box" is specified. Otherwise, the polygon is
+ generated point by point, in wire-drawing mode.
+ polygon make <N> <position1> <position2> ... <positionN>
+ Create a new polygon element with <N> points. Each <position>
+ is a list of size 2 with X, Y coordinates.
+ polygon make box <position1> <position2> <position3> <position4>
+ Create a new polygon element with 4 points and with border style
+ "closed". Each <position> is a list of size 2 with X, Y
+ coordinates.
+ 7. spline [<handle...>] <option>
+ spline make
+ Interactively create a new spline element.
+ spline make [<position1> <position2> <position3> <position4>]
+ Create a new spline object with endpoints <position1> and
+ <position4> and control points <position2> and <position3>.
+ 8. arc [<handle...>] <option>
+ arc make
+ Interactively create a new arc element.
+ arc make [<position> <radius> [<minor>] [<angle1> <angle2>]]
+ Create a new arc element with the indicated values.
+ By default, <minor> is set to the value of <radius>, <angle1>
+ is zero, and <angle2> is 360. Angle values are in degrees.
+ arc [<handle...>] radius|minor [<value>]
+ Specify the major or minor axis radius for the indicated arc.
+ arc [<handle...>] angle start|end [<value>]
+ Specify the start and end angles for the indicated arc.
+ 9. path [<handle...>] <option>
+ path make [<handles...>]
+ Generate a path element from the indicated components.
+ 10. object [<handle...>|<name...>] <option>
+ object make [<handle...>] [<library>] [<name>]
+ Creates a new object out of the elements specified by <handle...>,
+ or from the selected elements if <handle...> is not specified.
+ The new object is placed into library <library>, or the User
+ Library, if not specified. The object is given the name <name>,
+ if specified; otherwise the user is prompted for a name
+ object [<handle|name>] push
+ Edit the indicated object. This is like an instance edit except
+ that it is the library object itself, with default values for
+ parameters, that is edited. If the object takes no parameters,
+ then there is no difference between editing an object and editing
+ any of its instances.
+ object [<handle|name>] center [<position>]
+ Set the object's origin to <position> (a list of X, Y values).
+ If <position> is not specified, then return the coordinates of
+ the center of the object's bounding box.
+ object [<handle|name>] copy [<library>] [<name>]
+ A copy of the object is made and placed in the named <library>, or
+ in the User Library if not specified. The new copy is given the
+ name <name>, or the original name prepended with an underscore if
+ the name is not specified. If the originating and destination
+ libraries are the same, the copy will be a "virtual" copy.
+ object [<handle>] move [<library>]
+ Move the object to the indicated library, or the User Library if
+ <library> is not specified.
+ object [<handle>] hide
+ Hide the object from view in its library, unless hiding the object
+ would render the object unaccessible.
+
+B. Pages
+ 1. page
+ Returns the current page
+ 2. page directory
+ Go to the page directory listing (interactive command)
+ 3. page [<number>|<name>]
+ Same as " page [<number>|<name>] goto" (see below)
+ 4. page make [<name>]
+ Make a new page, giving it the optional name <name> if supplied,
+ or "Page X" where X is the page number. Generate a new menu button
+ entry for the indicated page. Go to the indicated page.
+ 4. page [<number>|<name>] <option>
+ Where the page may be specfied either by page number or by page
+ name (page label). If neither number or name is supplied, then
+ the current page is assumed. Options are:
+
+ load <filename...>
+ Load the xcircuit file named <filename> into the indicated page.
+ import <filename...>
+ Import the xcircuit file named <filename> into the indicated page.
+ background <filename>
+ Read the PostScript file named <filename> into the indicated page
+ as a background image.
+ save [<filename>]
+ Save the indicated page as <filename>. Normally, <filename> is
+ not specified and the filename given to the page by the "filename"
+ command is used.
+ goto
+ Go to the page directory listing (interactive command)
+ reset
+ Resets (clears) the indicated page, or the current page if no
+ arguements are given.
+ links
+ Returns the page labels of all pages which have the same filename
+ as the current or indicated page.
+ fit [true|false]
+ If "true" or "false" is given, sets or clears the auto-fit
+ function for the current page. If no value is given, then
+ it rescales the drawing to fit the output page. Only valid
+ in "full page" mode.
+ filename [<name>]
+ Sets the filename of the current page to <name>. With no argument,
+ returns the filename of the current page.
+ label [<name>]
+ Sets the name (page label) of the current page to <name>. With no
+ argument, returns the page label of the current page.
+ scale [<value>]
+ Sets the scale of the current page to <value>. With no argument,
+ returns the scale of the current page.
+ width [<value>]
+ Sets the scale of the current page such that the width is <value>.
+ With no argument, returns the width of the object in the current
+ page.
+ height [<value>]
+ Sets the scale of the current page such that the height is <value>
+ With no argument, returns the height of the object in the current
+ page.
+ size [<dimension>]
+ Sets the size of the output page for full-page mode to the given
+ dimension, which can be a list of size 2 containing the page
+ width and height, or a string in the format "width x height".
+ With no argument, returns the size of the current page as a
+ string in the format "width x height".
+
+C. Libraries
+ 1. library
+ Returns the current library, or "none" if none is being viewed.
+ 2. library directory
+ Go to the library directory (interactive command).
+ 3. library make [<name>]
+ Make a new library, giving it the optional name <name> if supplied,
+ or "Library: X" where X is the library number. Generate a new
+ menu button entry for the indicated library.
+ 4. library [<number>|<name>] <option>
+ Where the library is specified by number or by name. If no
+ library is specified, then the current library is assumed if
+ a library page is currently in the xcircuit drawing window,
+ or the User Library is assumed if not. Options are:
+ load <filename>
+ Load the library from file <filename> into the indicated library.
+ save <filename>
+ Save the indicated library to the file <filename>.
+ goto
+ Go to the indicated library (interactive command).
+ 5. library <filename> [<number>]
+ Backward compatibility; same as "library [<number>] load <filename>"
+
+D. Actions: Actions are described under the "element" command. These
+ commands are exactly like the "element" subcommands except that the
+ arguments are rearranged: "element [<handle...>] <command> <options...>"
+ becomes "<command> [<handle...>] <options...>". In addition, these
+ commands can take a position list <position> (list of size 2 containing X
+ and Y values) in place of the handle, in which case the command attempts
+ to select an element at the indicated position and apply the command to
+ that element.
+
+ 1. delete [<handle...>|here] <options>
+ 2. undelete [<handle...>|here] <options>
+ 3. select [<handle...>|here|get] <options>
+ The additional subcommand "get" returns a handle or list of handles
+ of all currently selected elements.
+ 4. deselect [<handle...>|here] <options>
+ 5. copy [<handle...>|here] <options>
+ 6. edit [<handle...>|here] <options>
+ 7. parameter [<handle...>|here] <options>
+ 8. push [<handle...>|here] <options>
+ 9. pop [<handle...>|here] <options>
+ 10. rotate [<handle...>|here] <options>
+ 11. flip [<handle...>|here] <options>
+
+E. Options
+ 1. config <option> [value...]
+ Main option setting. Options are:
+ config axis|axes [on|off]
+ Turn axis drawing on or off. If no argument supplied,
+ toggle the state of axis drawing.
+ config grid [on|off]
+ Turn grid drawing on or off. If no argument supplied,
+ toggle the state of grid drawing.
+ config grid spacing <value>
+ Set the grid spacing to <value>. <value> is a number
+ representing distance in the current coordinate system.
+ Currently, coordinate system specifiers like "in" and "cm"
+ may be included but are ignored.
+ config snap [on|off]
+ Turn snap point drawing on or off. If no argument supplied,
+ toggle the state of snap point drawing.
+ config snap spacing <value>
+ Set the snap spacing to <value>. <value> is a number
+ representing distance in the current coordinate system.
+ Currently, coordinate system specifiers like "in" and "cm"
+ may be included but are ignored.
+ config bbox [on|off]
+ Turn bounding box drawing on or off. If no argument supplied,
+ toggle the state of bounding box drawing.
+ config editinplace [on|off]
+ Turn edit-in-place on or off. If no argument supplied,
+ toggle the state of edit-in-place. If "on", when the
+ drawing hierarchy is descended, the entire drawing is drawn
+ from the top level, but everything above the current edit
+ level is drawn in gray.
+ config pinpositions [on|off]
+ Turn pin position drawing on or off. If no argument supplied,
+ toggle the state of pin position drawing. If "on", pin
+ positions inside an object instance appear in levels of the
+ drawing hierarchy outside of the object.
+ config linewidth <value>
+ Set global line scaling. All linewidths in the drawing are
+ determined relative to this overall scaling value (default
+ 1.0).
+ config colorscheme normal|inverse
+ Set the overall colorscheme. "normal" is black-on-white.
+ "inverse" is white-on-dark gray.
+ config drawingscale <scale>
+ Set the drawing scale. <scale> is represented as
+ <divisor>:<multiplier>. Positions reported in the message
+ bars are scaled by <multiplier>/<divisor> with respect to
+ the scale of the actual output.
+ config manhattan [on|off]
+ Sets the style of polygon drawing. When "on", lines can
+ only be drawn vertical and horizontal. If no argument is
+ supplied, the current polygon drawing mode is toggled.
+ config boxedit manhattan|rhomboidx|rhomboidy|rhomboida|normal
+ Sets the style of polygon editing. "manhattan" forces
+ lines to remain vertical or horizontal, but does not
+ affect lines which are already diagonal. "normal"
+ places no restrictions on line position. The "rhomboid"
+ styles place manhattan restrictions on horizontal or vertical
+ lines, but not both, and are of limited practicality.
+ config coordstyle "decimal inches"|"fractional inches"|centimeters
+ Sets the coordinate measurement system to metric or standard.
+ "fractional inches" reports values in whole number fractions
+ when possible.
+ 2. color [<option>]
+ Where option is one of:
+ a) set inherit|<idx>
+ Sets color to the indicated color index (from xcircuit's
+ color table). "inherit" is the same as <idx>=-1, and
+ represents a color which is inherited from the parent
+ element in the drawing hierarchy.
+ b) get
+ Returns the color of the currently selected element,
+ or the default color if nothing is selected.
+ c) add <name>
+ Adds a new color to the color index table (including
+ adding an entry to the GUI color selection menu).
+ Color may be specified by name (a la rgb.txt) or by
+ "#RRGGBB" notation.
+
+ 3. fill [<option>|<fillfactor>]
+ Given an integer between 0 and 100 inclusive, sets the fill style
+ to the given fillfactor. Values are rounded to the nearest known
+ fillfactor value. Know values are 0, 12, 25, 37, 50, 62, 75, 87,
+ and 100. Other options include "solid" (equivalent to "100"),
+ "opaque", and "transparent". With no arguments, returns a list
+ of all the fill styles of the currently selected element, or the
+ default fill style if nothing is selected.
+
+ 4. border [<option>]
+ Sets the border style to the given option, which is one of "solid",
+ "dashed", "dotted", "unbordered", "bounding box", "closed", and
+ "unclosed". The two-word "bounding box" must be quoted or in
+ braces ({}). "bounding box" takes an additional argument, "true"
+ or "false". With no option, returns a list of all border styles
+ of the currently selected element, or the default border style
+ if nothing is selected.
+
+F. Netlists
+ 1. netlist <option>
+ Perform various netlist functions. Options are:
+ a) write <format>
+ Generate a netlist output file in one of the following
+ formats: "spice", "spiceflat", "sim", or "pcb".
+ b) highlight
+ Highlight connectivity of any selected network element
+ (wire or pin), or start an interactive method for
+ selecting a network to highlight.
+ c) make
+ Generates and returns a Tcl list element representing
+ the netlist for the current circuit schematic. The
+ list is heavily nested. The outermost list contains
+ four elements: The string "globals", a list of
+ global networks, the string "circuit", and a list of
+ circuit netlists. These are further subdivided into
+ hierarchical lists, a description of which is not
+ contained here.
+ d) autonumber
+ Automatically substitues indices for unnumbered
+ circuit components.
+ 2. schematic <option>
+ Perform various netlist functions. Options are:
+ a) associate [<name>]
+ Associate the schematic with the symbol named <name>.
+ If <name> is not specified, xcircuit starts an interactive
+ method for selecting a symbol for association.
+ b) disassociate
+ Disassociate any existing symbol from the schematic.
+ c) make [<name>]
+ Generate a new symbol associated with the current
+ schematic. The new symbol will be named after the
+ page. If the current page has not been named, then
+ option <name> must be provided.
+ d) goto
+ Change the current page to the associated symbol, if
+ it exists
+ e) get
+ Return the name of the associated symbol, or {}
+ (empty list) if no symbol is associated.
+ f) type [<value>]
+ Return the type of the current page, which may be one
+ of "schematic", "symbol", "trivial", or "fundamental".
+ If "value" is specified, change the current type to
+ "value". It is only possible to change types between
+ "symbol", "trivial", and "fundamental", which are all
+ symbol classes. It is not possible to change symbols
+ to schematics and vice versa.
+ 3. symbol
+ "symbol" is simply an alias for "schematic". Whether the command
+ operates on a symbol or a schematic is determined purely from
+ context.
+
+
+G. GUI
+ 1. refresh
+ Redraws the current window.
+ Automatically substitues indices for unnumbered
+ circuit components.
+ 2. zoom [in [<amount>]|out [<amount>]|box|view|factor [<amount>]]
+ With no option, same as "zoom view".
+ Options:
+ in [<amount>]: Zoom in by current zoom factor or by [<amount>].
+ out [<amount>]: Zoom out by current zoom factor or by [<amount>].
+ box: prompt for zoom box. Zoom occurs as soon as box is drawn and
+ the mouse button is released.
+ view: Fits the drawing to the xcircuit window.
+ factor: Returns the current zoom factor.
+ factor <amount>: Sets the current zoom factor to <amount>.
+ <amount> is a floating-point number representing a scale multiplier.
+ Values greater than 1.0 imply a zoom "in", while values less than one
+ imply a zoom "out". Zero or negative values not allowed.
+ 3. pan [here|<position>]
+ Center the drawing window on the indicated position. If "here",
+ position is centered on the cursor. Otherwise, <position> is a
+ list of size 2 with X and Y values.
+ 4. quit
+ Quit xcircuit, with a prompt if any files with outstanding changes
+ have not been saved.
+ 5. promptsavepage [<page_number>]
+ Start the page output dialog. Currently, <page_number>, if present,
+ must be the current page number.
+ 6. here
+ Returns a list size two with the X and Y position of the cursor
+ relative to the XCircuit coordinate system.
+
+H. Files
+ 1. loadfont <fontname>
+ Loads an xcircuit font. Expects to see file <fontname>.xfe (Xcircuit
+ Font Encoding) in the default system library path.
+
+ 2. filerecover
+ Recovers files from a crash or Ctrl-C exit that are left in the /tmp
+ directory.
+
+I. General
+ 1. quitnocheck
+ Immediate exit from xcircuit
+ 2. start <args>
+ XCircuit startup. Usually called internally from the wrapper
+ script. However, for purposes of debugging problems, it can
+ be called manually from the Tcl command after loading the
+ shared object file "xcircuit.so".
+ 3. simple <pathname>
+ This is a Tk extension which generates a "simple" window, a blank
+ area into which a C-source application is supposed to draw.
+ 4. image create xpm <name> -file <filename.xpm>
+ This is an extension to the Tk "image" command which allows images
+ to be generated from "xpm"-format files. Since xpm files contain
+ all color and size information, the options are fixed (although it
+ might be nice to add things like color substitutions).
+ 5. tag <name> [<procedure>]
+ Attach a procedure to a command, such that the procedure is
+ executed after every call to the command "name". The procedure
+ may name a Tcl procedure or it may be entirely inline.
+ "procedure" may make use of several escape sequence substitutions,
+ as follows:
+ %0 through %5: Substitute the argument passed to <name>.
+ %r: Substitute the Tcl result from <name>. The result
+ is transparent; any result produced by the tag
+ procedure will be ignored and the calling function
+ will get back the original result (%r).
+ %R: Substitute the Tcl result from <name>. The result
+ is absorbed, and the tag function generates a new
+ result which is passed back to the calling function.
+ %%: Substitute a single percent character.
+ All other uses of the percent character within the tag procedure
+ will be evaluated as-is.
+ With only one argument, <name>, the "tag" command will return
+ the procedure currently attached to that command.
+ Tagging a procedure to a command which is already tagged will
+ cause the new tag procedure to overwrite the old one.
+ Any tag procedure which calls the function to which it is tagged
+ should wrap the entire procedure inside
+ if {[info level] <= 1} {...}
+ to prevent infinite recursion.
+
+
+II. Scripted commands (Tcl source)
+----------------------------------
+
+A. Namespace (Toolscript)
+ 1. pushnamespace <namespace>
+ Makes all commands in <namespace> available in the current namespace.
+ Conflicting commands names are not pushed.
+ 2. popnamespace <namespace>
+ Revert command names back to original set.
+
+B. Dialogs
+ 1. promptobjectsize
+ Dialog to ask for object size
+ 2. promptborderwidth
+ Dialog to ask for element border width
+ 3. promptlinewidth
+ Dialog to ask for overall linewidth scaling
+ 4. promptgridspace
+ Dialog to ask for grid spacing
+ 5. promptdrawingscale
+ Dialog to ask for drawing scale
+ 6. promptsnapspace
+ Dialog to ask for snap spacing
+ 7. promptmakeobject
+ Dialog to ask for object name before making new library entry
+ 8. promptsavelib <library_number>|<library_name>
+ Dialog to ask for filename of library to save.
+ 9. promptloadlibrary
+ Dialog to ask for filename of library to load
+ 10. promptaddlibrary
+ Dialog to ask for filename of library to add to current library page
+ 11. promptloadfile
+ Dialog to ask for filename of xcircuit file to load
+ 12. promptimportfile
+ Dialog to ask for filename of xcircuit file to add to current page
+ 13. promptimportbackground
+ Dialog to ask for filename of PostScript file to use as background
+ 14. promptexecscript
+ Dialog to ask for filename of Tcl file to execute
+ 15. prompttextsize
+ Dialog to ask for label scaling
+ 16. promptnewfont
+ Dialog to ask for name of font to load
+ 17. promptkern
+ Dialog to ask for X Y kerning values inside a label
+ 18. promptmakesymbol
+ Dialog to ask for a name for a page, if the page has not yet been
+ named, before generating a matching symbol of the same name.
+
+C. Menu manipulation: These functions should only be called from inside
+ xcircuit, as they change only the menu appearance and callbacks
+ and not xcircuit's internal data structures.
+
+ 1. newcolorbutton <r> <g> <b> <idx>
+ Adds a new button to the color menu
+ <r> <g> and <b> are color components, and <idx> is the position in
+ xcircuit's color table.
+ 2. newencodingbutton <encodingname>
+ Adds a new button to the font encoding menu. Valid encoding names
+ are "special", "standard", and "ISO-Latin1" through "ISO-Latin6".
+ 3. newfontbutton <familyname>
+ Adds a new button to the font family menu.
+ 4. newlibrarybutton <libraryname>
+ Adds a new button to the library menu with a callback to switch to
+ the indicated library.
+ 5. newpagebutton <pagename>
+ Adds a new button to the page menu with a callback to switch to the
+ indicated page.
+ 6. renamelib <number> <libraryname>
+ Changes the name and callback function of the indicated library menu button.
+ <number> is the index position of the button in the library menu.
+ 7. renamepage <number> <pagename>
+ Changes the name and callback function of the indicated page menu button
+ <number> is the index position of the button in the page menu.
+ 8. xschema true|false
+ Turns the netlisting functions on or off.
+ 9. toolbar true|false
+ Turns the toolbar functions on or off.
+
+D. Command tag callbacks: These functions are attached to specific xcircuit
+ commands using the "tag" command, and execute after the tagged
+ command has executed. This keeps the GUI synchronized with commands
+ called from the command-line.
+
+ 1. pageupdate [subcommand]
+ Updates the file output window to match the current page status.
+ 2. setsymschem
+ Updates the schematic and symbol buttons, and the netlist menu
+ options, to match the current page.
+
diff --git a/README.ngspice b/README.ngspice
new file mode 100644
index 0000000..f1aa9d1
--- /dev/null
+++ b/README.ngspice
@@ -0,0 +1,54 @@
+XCircuit as a front-end GUI to ng-spice
+------------------------------------------------------
+XCircuit can work as an ng-spice front-end. However,
+there is the problem that ng-spice can't handle being
+used interactively through a read-write pipe. The
+problem is that ngspice auto-detects whether standard
+input is a tty, and if standard input is not (such as
+when it is an I/O pipe), ngspice switches to batch
+mode. I submitted the patch below to the ngspice
+project at SourceForge. Hopefully it will get into
+the distribution.
+
+To test whether ngspice is patched, run XCircuit, and
+type this command into the console: "spice start".
+If you get a delay followed by an error message:
+
+ ngspice: invalid option -- p
+
+then your version of ngspice is not patched, and you
+need to apply the patch file below to the ngspice
+source and recompile.
+
+File pipemode.patch: Put in directory ng-spice-rework-17 and
+apply with the command "patch -p1 < pipemode.patch".
+
+-------------------cut here----------------------------------------------------------
+--- ng-spice-rework-17.orig/src/main.c 2006-04-05 10:52:26.060853760 -0700
++++ ng-spice-rework-17/src/main.c 2006-04-05 11:02:53.581165821 -0700
+@@ -516,6 +516,7 @@
+ " -i, --interactive run in interactive mode\n"
+ " -n, --no-spiceinit don't load the local or user's config file\n"
+ " -o, --output=FILE set the outputfile\n"
++ " -p, --pipe run in I/O pipe mode\n"
+ " -q, --completion activate command completion\n"
+ " -r, --rawfile=FILE set the rawfile output\n"
+ " -s, --server run spice as a server process\n"
+@@ -738,6 +739,7 @@
+ {"interactive", 0, 0, 'i'},
+ {"no-spiceinit", 0, 0, 'n'},
+ {"output", 0, 0, 'o'},
++ {"pipe", 0, 0, 'p'},
+ {"completion", 0, 0, 'q'},
+ {"rawfile", 1, 0, 'r'},
+ {"server", 0, 0, 's'},
+@@ -745,7 +747,7 @@
+ {0, 0, 0, 0}
+ };
+
+- c = getopt_long (argc, argv, "hvbc:ihno:qr:st:",
++ c = getopt_long (argc, argv, "hvbc:ihno:pqr:st:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
diff --git a/README.notes b/README.notes
new file mode 100644
index 0000000..f91da46
--- /dev/null
+++ b/README.notes
@@ -0,0 +1,345 @@
+XCircuit v3.8
+-----------------------------------------------------------------------------
+
+An X11 drawing program [especially for circuit schematics]
+Copyright (c) 2013 Tim Edwards
+August 1993 -- January 2013
+-----------------------------------------------------------------------------
+
+This README file contains additional notes about the program which may or may
+not be of interest to anyone.
+-----------------------------------------------------------------------------
+
+ASG:
+
+ Versions beginning with 3.2 can be compiled with the ASG package,
+or "Automatic Schematic Generation". The package is derived from SPAR,
+written by Stephen Frezza (currently at Gannon University). SPAR is
+based on the same "corner-stitched tile" structures used by the EDA
+tool "magic", modified to encompass the probabilistic nature of auto-
+routing. The ASG package currently supports (to a limited extent)
+reading of SPICE files, but will eventually support EDIF netlist output
+from Verilog (and possibly VHDL) for turning netlists into schematics.
+Also, the ASG package will handle constrained moving, re-routing networks
+in response to moving elements around the schematic drawing.
+
+Toolscript:
+
+ Versions beginning with 3.0 are part of a methodology known as
+"ScriptEDA", a call to put major open-source EDA tools into a similar
+framework under an interpreter, where most upper-level functions can be
+written as scripts. My more narrowly-defined version of ScriptEDA is
+called "toolscript". The rationale behind "toolscript" is to allow a
+single interpreter to launch multiple EDA tools, such that a
+single script can control multiple programs, bringing together layout
+tools, schematic capture, simulation, and so forth, in a highly
+integrated manner. "Toolscript" requires that each EDA tool should be
+a shared-object library of routines, that each tool should have its
+own command namespace, that each tool should launch itself from a
+"start" command in its namespace, and that the "start" command
+should return control to the interpreter such that the interpreter is
+always available from the calling terminal. Applications are encouraged
+to rely heavily on scripts for functions which do not require fast
+execution. In particular, scripts should handle most input/output
+functions, so that users can easily change file formats to suit their
+needs. The GUI for toolscript applications should be written in Tk,
+which integrates the graphics event loop with the interpreter, greatly
+simplifying handling of the interaction between the two. To synchronize
+the GUI with commands called from the command-line, each program should
+have a "command tag" function which can associate a script procedure
+with each command. These callback procedures can then be defined within
+the GUI script to update the GUI in response to commands. Finally,
+each application should redefine "printf" output statements to call the
+corresponding output method for the intperpreter (e.g., "Tcl_Eval" for
+compatibility with the "tkcon" console). This allows error and standard
+output to be handled independently. Within "tkcon", stdout and stderr
+are printed in blue and red, respectively, making the program output
+easier to read.
+
+ The "toolscript" concept is ideally interpreter-independent. However,
+due mostly to ease of implementation and syntactical issues, TCL has
+ended up as the only supported interpreter. TCL calls are heavily
+embedded in the source code, making it somewhat difficult to simply
+add another interpreter. While XCircuit can be compiled with the Python
+interpreter, it is embedded, not extended, and so does not follow the
+principles of "toolscript".
+
+Rationale:
+
+ This program was written with a number of things in mind. The major
+point in writing it was that I found all of the drawing programs freely
+distributed at the usual X11 ftp sources (ftp.uu.net, export.lcs.mit.edu,
+etc.), which includes xpic and xfig, and even some other programs like
+idraw and commercial programs like framemaker, were lacking in some manner.
+Some of them, like xpic, are missing fundamental parts, while others, like
+xfig and framemaker, have a cumbersome user interface and require
+inordinately large amounts of time to create simple pictures. The really
+powerful programs like Adobe Illustrator are, naturally, expensive.
+There has been a long-standing tradition of making MacDraw lookalikes which
+I find particularly disturbing, since a number of features of that GUI are
+fundamentally screwed up, including the dependence on a black-and-white color
+scheme for things such as grid lines and edit points which can make the screen
+cluttered and difficult to work with. I have chosen to freely ignore all such
+standards in cases where they seem to hinder rather than help the user.
+ Disclaimers: The above comments refer to versions of the abovementioned
+programs available as of 1993 and do not necessarily reflect the programs'
+current status. Particularly the latest (from 1995 or so) version of xfig
+is quite good, though it continues to have a "MacDraw" feel to it. XCircuit's
+schematic capture has always been secondary to its use for drawing, and
+users may prefer programs such as "gschem" (by Ales Hvezda, part of gEDA)
+that are more in keeping with "normal" standards for EDA software. Because
+such programs exist, XCircuit's schematic capture, like its basic drawing
+functions, often deviate from the norm to explore radical ideas. Among
+XCircuit's "radical ideas" are automatic port finding, its parameterization
+method, embedded output formatting directives, and (a recent addition)
+automatic schematic (re)generation.
+
+The principles of XCircuit are as follows:
+
+A) Structural backbone
+ 1) There are six drawing elements which are considered "primary".
+ These are as follows:
+
+ a) polygon (multiple lines which may or may not be closed and filled)
+ b) arc (ellipse segment which may be closed and/or filled as above)
+ c) label (any text)
+ d) curve (based on the PostScript "curveto" algorithm)
+ e) graphic (graphic image, e.g., from a PPM file)
+ f) object instance (see below)
+
+ 2) There are two drawing elements which are considered "secondary", which
+ is to say, contain instances of primary elements. These are:
+
+ a) path (a connected series of polygons, arcs, and/or curves)
+ b) object (something containing polygons, arcs, labels,
+ curves, paths, and instances of other objects)
+
+ Each object is instanced by a primary element called the "object
+ instance", a self-contained unit which allows an object to be scaled,
+ rotated, and translated within another object. Since objects contain
+ object instances and object instances point to objects, there is a
+ two-step recursion which is central to the concept of xcircuit.
+
+ 3) There is one primary object instance called the TopObject, which is
+ the program window, and its associated object, which is whatever
+ appears on the screen. TopObject is a pointer, so that any object
+ in memory may be the top object, allowing a push/pop edit stack.
+ All other objects are organized in an array of pointers called the
+ Library. The Library is filled on startup with the contents of a
+ Library file, and is expanded whenever a new object is created.
+
+ Actually, there are many different TopObjects, called "pages",
+ which can be switched between at will by typing the number of
+ the page, 1 through 9 and 0 for page 10, or through the "Page"
+ menu command, which allows access to as many pages as are
+ defined. The "load" and "save" commands act only on the
+ present page (unless multiple pages are loaded at a time), as
+ do all the drawing commands.
+
+ 4) All elements allocate memory as they are created and release the
+ memory as they are destroyed, so the only limit on the number of
+ elements in a drawing is the memory of the workstation.
+
+B) Input/Output
+
+ 1) All input and output is in PostScript, albeit a version of PostScript
+ with extremely restricted syntax: xcircuit is in no sense a PS
+ interpreter! The primary element types are defined as procedures
+ in the PostScript prologue; all secondary elements are defined as
+ "def" structures in PostScript, the only restriction being that no
+ definition can be called before it is defined.
+
+ 2) Output can be encapsulated or non-encapsulated ("full page"), and
+ can have multiple pages. All pages which declare the same
+ "filename" on the "output properties" window will be saved to
+ the same file.
+
+ 3) The current state of the program is captured from time to time
+ (default 10 minutes or 20 "significant" changes to the drawing)
+ in a temporary file. If XCircuit crashes, work can be recovered
+ by running "xcircuit" without arguments (i.e., without a specific
+ filename on the command line). This method makes the filename
+ transparent to the user, but the file can be found (on most
+ systems) as /tmp/XC??? where ??? is a randomly-generated number
+ that uniquely identifies the file.
+
+ 4) Text is vector-drawn, in order to best match the flexibility of
+ PostScript, which unlike X11 allows text to be scaled to any size
+ and rotated to any orientation (modern font renderers can do this,
+ but are not good at fast on-the-fly rendering needed for a drawing
+ The quality of the vector-drawn text on the screen is relatively
+ poor; however, the end product of xcircuit is the PostScript file,
+ which does not suffer from those limitations. Text vectors are
+ xcircuit elements read from an xcircuit library file, with
+ encoding information read from a separate file.
+
+ 5) X11 does not have any capability for generalized curves (splines).
+ Therefore, splines are constructed by an N-segment approximation
+ which internally looks like a polygon. The PostScript output is a
+ smooth curve instead of the approximation.
+
+ 6) X11 does not have any capability for generalized ellipses (ellipses
+ under any rotation). Similarly to the splines, arcs are constructed
+ by an N-segment approximation.
+
+ 7) Implementing all arcs and curves as N-segment approximation allows
+ the possibility of general paths, or sequences of polygons, arc
+ sections, and curves which form a path that can be bordered, closed
+ and/or filled like an individual arc, curve, or polygon.
+
+ 8) Other than the qualitative appearance of the text, the screen output
+ of xcircuit is meant to be the closest possible match to the
+ rendering of the PostScript output. A PostScript hack allows
+ stipple pattern fills to be effectively "transparent" (something
+ that PostScript does not do naturally). However, the effect is
+ *extremely* device-dependent because it overrides the printer's
+ halftoning operators. One effect of this is that halftoning
+ will look abnormally large when viewed at screen resolutions,
+ e.g., with GhostScript.
+
+C) User Interface
+
+ 1) The mouse button system and the object library are based on the
+ Caltech circuit-simulation program "log" (either "analog" or "diglog").
+ As is usual for most applications, mouse button 1 is used to select
+ things or cycle between selections, button 2 usually terminates a
+ command, and button 3 will abort a command. In addition, button 1
+ has a function called "hold", which occurs after the button has
+ been continually pressed for a short length of time (about 1/5 second).
+ As the name implies, "hold" grabs hold of an element which can then
+ be moved around the screen.
+
+ Because this program is tailored to circuit drawing, the most common
+ functions are drawing lines and moving object instances. Therefore,
+ these two functions are made directly available from the mouse
+ button 1 (after a "tap" or a "hold", respectively). The next most
+ common function is selection of elements singly or in groups.
+ Button 2 can be used to select an item if tapped, and if pressed
+ and held down, a box will be drawn and everything inside that box
+ selected when the button is released. All other commands are
+ available from the pulldown menus and/or from the keyboard as
+ single-key macros. Keyboard macros are quicker, since they act
+ on the present cursor position, whereas menu commands require an
+ extra step.
+
+ From version 3.4, buttons and keys are handled identically by the
+ interface, with the "hold" function becoming a modifier like "shift"
+ or "control". All XCircuit functions can be arbitrarily bound to
+ any button or key. The button 1 binding corresponds to the drawing
+ mode. If button 1 is bound to function "Wire", then it works as
+ described above. If it is bound to "Arc", then button 1 can be
+ used to draw arcs, while the other functions remain the same.
+
+ 2) The libraries are intended to provide a convenient way to store and
+ retrieve elements of a picture which will be used more than once.
+ For the application of circuit drawing, a built-in library provides
+ basic objects such as transistors, amplifiers, resistors, capacitors,
+ arrows, circles, power and ground symbols, and the like. This file
+ ("builtins.lps") is loaded on startup; the program first looks in
+ the current directory, and then searches in a given global directory
+ (something like ~cad/lib/xcircuit/) if it could not find it initially.
+ Thus each user can add to or modify the file of builtins to reflect
+ personal taste. Since the PostScript output contains all object
+ definitions, these changes to the built-in functions are inherently
+ transferrable. The program checks objects with the same name for
+ equivalence of their contents, and changes names as necessary to
+ avoid conflicts.
+
+ An additional library, the user library, contains all of the
+ objects which are created (using the "make object" command)
+ during a session or objects which are loaded from a file but
+ do not belong to the built-in library. The user library can
+ be saved by itself and reloaded later either into the user
+ library or into the built-in library. This is the way to
+ create a personalized built-in library set.
+
+ 3) In the non-TCL-based version of XCircuit, the special file
+ "startup.script" can be edited to include lines such as the
+ following:
+
+ filename loadlibrary
+
+ The loadlibrary command will automatically include another
+ library file. This method makes it convenient to divide up
+ libraries into separate files according to (for instance)
+ function (digital, analog, clip art, etc.), and use the
+ loadlibrary commands to choose which ones will be loaded
+ on startup. Caveat: If the order of loading is such that
+ an object contains an instance of another object which has
+ not yet been loaded, xcircuit will complain.
+
+ In the TCL-based version of XCircuit, the equivalent file is
+ "xcstartup.tcl" and the syntax is:
+
+ library n load filename
+
+ where "filename" is the name of the library file (e.g.,
+ "digital.lps"), and "n" is the library page number. By
+ specifying the same page as an existing library, a set of
+ objects can be appended to that library. "n" may also refer
+ to a library by name.
+
+ By default, libraries have the extension ".lps". As they
+ contain only macros, they cannot be displayed with any
+ PostScript interpreter.
+
+ 4) Xcircuit has a strict sense of zooming and snap-to grid. Objects
+ scale absolutely; line widths and text sizes will increase/decrease
+ proportionally with the zoom, as well as dot/dash spacing and all
+ other features. Xcircuit does have a minimum integer grid in
+ coordinate space, which translates to 0.005 inches at an output scale
+ of 1. The maximum zoom scale gives a screen size translating to
+ about 100 by 100 inches at an output scale of 1. The effective
+ scale can be varied by changing the output scale (reached from the
+ "File/Write" menu selection) in order to fit a drawing to a page or
+ to get a grid matched to a specific dimension. A separate scale
+ parameter changes the scale of the reported position relative to
+ the output scale (as it will appear on a printed page).
+
+ 5) The snap-to grid is an all-important feature for circuit drawing,
+ wherein it is critical that wires line up properly with one another.
+ In xcircuit, there is no way to get off the snap-to grid except by
+ turning the snap function off and physically pushing elements off
+ the grid. In any case, objects can always be returned to the snap
+ grid with the "snap" function (key 'S').
+
+D) Schematic Capture
+
+ XCircuit implements a sophisticated schematic capture. Unlike
+ virtually all schematic capture software currently available,
+ xcircuit allows the designer to draw the circuit in a "natural"
+ way, making use both of schematic hierarchies and simple
+ hierarchies created simply by grouping elements together. If
+ the chosen netlist format is hierarchical (like SPICE), both
+ hierarchical forms will be retained in the output. For element
+ grouping, input/output ports connecting into to the group will
+ be determined automatically, from context.
+
+ Individual networks can be queried (key 'Alt-W') to highlight
+ the entire visible part of the network, with the network name
+ printed in the message window.
+
+ Any schematic can cover multiple pages. One page is marked as
+ "primary" and the others marked as "secondary". Netlists are
+ generated in the primary page object only, but incorporate
+ information from all the schematic pages. All pages which have
+ the same "page label" are considered to be part of the same
+ schematic.
+
+-----------------------------------------------------------------------------
+
+Xcircuit reference:
+ Local: See the xcircuit manpage ("man xcircuit")
+ Online: http://opencircuitdesign.com/xcircuit/features.html
+
+-----------------------------------------------------------------------------
+
+Online tutorials: See
+ Standard: http://opencircuitdesign.com/xcircuit/tutorial/tutorial.html
+ Schematic capture: http://opencircuitdesign.com/xcircuit/tutorial/tutorial2.html
+
+-----------------------------------------------------------------------------
+
+Things to do: See the file "TODO"
+
+-----------------------------------------------------------------------------
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..7cc570a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,66 @@
+Xcircuit v3.x Things To Do (file TODO)
+----------------------------------------------------------------------
+Bugs to fix:
+
+1) Positional parameters cause incorrect redisplay during polygon/path
+ edit (display reverts to original value). Insertion of points must
+ renumber parameterized points.
+
+2) Position parameters have serious consequences for netlisting, in
+ that they can cause an object's netlist to change on a per-instance
+ basis. This should be either dealt with or prevented.
+
+3) Substring selection in labels is backwards when the "flip
+ invariance" feature has rotated the text string 180 degrees.
+
+4) Colormap installation may be incomplete if xcircuit runs out
+ of colors in the middle of running the program (minor problem;
+ unlikely to happen).
+
+5) Color and Page menus run off the top and bottom of the screen
+ if the lists get to be too long.
+
+----------------------------------------------------------------------
+Features to add or change:
+
+1) Graphic element, still to be addressed:
+
+ A) Incorporate raw PostScript by using ghostscript to generate
+ PPM data, and handling it like a PPM file, but treating it
+ in file input/output as an encapsulated PostScript block.
+ This should replace the current background rendering code.
+
+ B) Rewrite the image processing routines to clip the size of
+ the target image when outside screen bounds. Cropped
+ images must be declared invalid on pan operations.
+
+ C) Page saves for backup should not write the graphic image,
+ or at least should not write it more than once (write it
+ to a separate file?)
+
+2) Create a Tcl command to return the value of countchanges(), and make
+ "quitcheck" a Tcl script, avoiding all the Tcl_Eval() calls there.
+
+3) Allow page label to be changed from the label on the bottom message bar.
+
+4) Vectored font output in PostScript.
+
+5) Proper cornering on dot/dashed boxes (maybe easier to
+ do in xcircuit and enforce WYSIWYG in PostScript?)
+
+6) Switch to all-floating-point internal units? ---probably not
+ necessary, but converting all XPoints to structures with ints
+ would be helpful.
+
+7) Comprehensive dependency list for allowing/disallowing
+ menu functions (key function dependencies have been dealt
+ with).
+
+8) Page indices need to be separated from the pagelist indices, so
+ that schematic library objects can be loaded and manipulated
+ without having to be displayed in the page list.
+
+9) Need to translate the Python routines for handling the "generic"
+ netlist output to Tcl.
+
+----------------------------------------------------------------------
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..9722aed
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+3.8.78
diff --git a/Xw/BBoard.c b/Xw/BBoard.c
new file mode 100644
index 0000000..ceab3e5
--- /dev/null
+++ b/Xw/BBoard.c
@@ -0,0 +1,353 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: BBoard.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code and class record for Bulletin Board Widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/BBoard.h>
+#include <Xw/BBoardP.h>
+
+
+static void Initialize();
+static XtGeometryResult GeometryManager();
+static void ChangeManaged();
+
+
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+XwBulletinClassRec XwbulletinClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwmanagerClassRec,
+ /* class_name */ "XwBulletinBoard",
+ /* widget_size */ sizeof(XwBulletinRec),
+ /* class_initialize */ NULL,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ (XtInitProc) Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ _XwRealize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ NULL,
+ /* resize */ NULL,
+ /* expose */ NULL,
+ /* set_values */ NULL,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ NULL,
+ XtInheritDisplayAccelerator, NULL,
+ },{
+/* composite_class fields */
+ /* geometry_manager */ (XtGeometryHandler) GeometryManager,
+ /* change_managed */ (XtWidgetProc) ChangeManaged,
+ /* insert_child */ XtInheritInsertChild, /* from superclass */
+ /* delete_child */ XtInheritDeleteChild, /* from superclass */
+ NULL,
+ },{
+/* constraint_class fields */
+ /* resource list */ NULL,
+ /* num resources */ 0,
+ /* constraint size */ 0,
+ /* init proc */ NULL,
+ /* destroy proc */ NULL,
+ /* set values proc */ NULL,
+ NULL
+ },{
+/* manager_class fields */
+ /* traversal handler */ (XwTraversalProc) XtInheritTraversalProc,
+ /* translations */ NULL,
+ },{
+/* bulletin board class - none */
+ /* no new fields */ 0
+ }
+};
+
+WidgetClass XwbulletinWidgetClass = (WidgetClass)&XwbulletinClassRec;
+WidgetClass XwbulletinBoardWidgetClass = (WidgetClass)&XwbulletinClassRec;
+
+
+
+/*************************************<->*************************************
+ *
+ * CalcSize
+ *
+ * Description:
+ * -----------
+ * Figure out how much size we need.
+ *
+ *************************************<->***********************************/
+
+static Boolean CalcSize(bb, width, height, replyWidth, replyHeight)
+ XwBulletinWidget bb;
+ Dimension width, height;
+ Dimension *replyWidth, *replyHeight;
+{
+ Cardinal i, j, numItems;
+ Dimension minWidth, minHeight;
+ Widget box; /* Current item */
+
+
+ /*
+ * If there are no items then any space will work
+ */
+
+ if ((numItems=bb->manager.num_managed_children) <= 0)
+ {
+ if ((replyWidth != NULL) && (replyHeight != NULL))
+ {
+ *replyWidth = 10;
+ *replyHeight = 10;
+ }
+ return(TRUE);
+ }
+
+
+
+ /*
+ * Compute the minimum width & height for this box
+ * by summing the rectangles of all children.
+ */
+
+ minWidth = minHeight = 0;
+
+ for (i=0; i < numItems; i++)
+ {
+ box = (Widget) bb->manager.managed_children[i];
+ minWidth = Max (minWidth, (box->core.x + 2*box->core.border_width +
+ box->core.width));
+ minHeight = Max (minHeight, (box->core.y + 2*box->core.border_width +
+ box->core.height));
+ }
+
+
+
+ if (bb->manager.layout == XwMAXIMIZE)
+ {
+ minWidth = Max (minWidth, width);
+ minHeight = Max (minHeight, height);
+ }
+
+
+ if (replyWidth != NULL) *replyWidth = minWidth;
+ if (replyHeight != NULL) *replyHeight = minHeight;
+
+
+ if ((width < minWidth) || (height < minHeight)) return (FALSE);
+
+ return (TRUE);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * DoLayout
+ *
+ * Description:
+ * -----------
+ * Try to do a new layout within the current width and height;
+ * if that fails try to do it within the box returned by CalcSize
+ *
+ *
+ *************************************<->***********************************/
+static Boolean DoLayout(bb)
+ XwBulletinWidget bb;
+{
+ Dimension width, height;
+ XtWidgetGeometry request, reply;
+
+ (void) CalcSize(bb, bb->core.width, bb->core.height, &width, &height);
+
+ if ((bb->manager.layout == XwIGNORE) || /* don't care if it fits */
+ ((bb->core.width == width) && (bb->core.height == height) &&
+ bb->manager.layout != XwSWINDOW))
+ return (TRUE); /* Same size & NOT special case */
+
+
+ if (bb->manager.layout == XwMAXIMIZE)
+ {
+ width = Max (bb->core.width, width);
+ height = Max (bb->core.height, height);
+ }
+
+ switch (XtMakeResizeRequest
+ ((Widget) bb, width, height, &width, &height))
+ {
+ case XtGeometryYes:
+ return (TRUE);
+
+ case XtGeometryNo:
+ return (FALSE);
+
+ case XtGeometryAlmost: /* TAKE WHAT YOU CAN GET! */
+ (void) XtMakeResizeRequest((Widget) bb, width, height,
+ NULL, NULL);
+ return (TRUE);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ * Description:
+ * -----------
+ * Make sure height and width are not set to zero at initialize time.
+ *
+ *************************************<->***********************************/
+static void Initialize (request, new)
+XwBulletinWidget request, new;
+
+{
+ /* DON'T ALLOW HEIGHT/WIDTH TO BE 0, BECAUSE X DOESN'T HANDLE THIS WELL */
+ if (new->core.width == 0) new->core.width = 10;
+ if (new->core.height == 0) new->core.height = 10;
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * GeometryManager(w, request, reply)
+ *
+ *
+ *************************************<->***********************************/
+
+static XtGeometryResult GeometryManager(w, request, reply)
+ Widget w;
+ XtWidgetGeometry *request;
+ XtWidgetGeometry *reply; /* RETURN */
+
+{
+ Dimension width, height, borderWidth, junk;
+ XwBulletinWidget bb;
+ Boolean geoFlag;
+ XtGeometryHandler manager;
+ XtGeometryResult returnCode;
+
+ /*
+ * IF LAYOUT MODE IS XwSWINDOW ( PARENT HAD BETTER BE A SUBCLASS OF
+ * SCROLLED WINDOW) THEN SIMPLY PASS THIS REQUEST TO MY PARENT AND
+ * RETURN ITS RESPONSE TO THE REQUESTING WIDGET.
+ */
+
+ bb = (XwBulletinWidget) w->core.parent;
+ if (bb->manager.layout == XwSWINDOW)
+ {
+ manager = ((CompositeWidgetClass) (bb->core.parent->core.widget_class))
+ ->composite_class.geometry_manager;
+ returnCode = (*manager)(w, request, reply);
+ return(returnCode);
+ }
+
+ /* Since this is a bulletin board, all position requests
+ * are accepted.
+ */
+ if (request->request_mode & (CWX | CWY))
+ XtMoveWidget( w, ((request->request_mode & CWX) == 0)
+ ? w->core.x : request->x ,
+ ((request->request_mode & CWY) == 0)
+ ? w->core.y : request->y );
+
+
+ /* Fill out entire request record */
+ if ((request->request_mode & CWWidth) == 0)
+ request->width = w->core.width;
+ if ((request->request_mode & CWHeight) == 0)
+ request->height = w->core.height;
+ if ((request->request_mode & CWBorderWidth) == 0)
+ request->border_width = w->core.border_width;
+
+ /* Save current size and set to new size */
+ width = w->core.width;
+ height = w->core.height;
+ borderWidth = w->core.border_width;
+ w->core.width = request->width;
+ w->core.height = request->height;
+ w->core.border_width = request->border_width;
+
+ geoFlag = DoLayout(bb);
+
+ w->core.width = width;
+ w->core.height = height;
+ w->core.border_width = borderWidth;
+
+ if (geoFlag)
+ {
+ XtResizeWidget(w, request->width, request->height,
+ request->border_width);
+ return(XtGeometryDone);
+ }
+ return (XtGeometryNo);
+
+ }
+
+/*************************************<->*************************************
+ *
+ * ChangeManaged
+ *
+ * Description:
+ * -----------
+ * Restructure the manager's "managed children" list. Then re-lay
+ * out children.
+ *
+ *************************************<->***********************************/
+static void ChangeManaged(bb)
+ XwBulletinWidget bb;
+{
+
+ /* Put "managed children" info together again */
+
+ _XwReManageChildren ((XwManagerWidget)bb);
+
+ /* Reconfigure the bulletinboard */
+
+ (void) DoLayout(bb);
+}
+
+
diff --git a/Xw/BBoard.h b/Xw/BBoard.h
new file mode 100644
index 0000000..67705e3
--- /dev/null
+++ b/Xw/BBoard.h
@@ -0,0 +1,52 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: BBoard.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for the bulletin board widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * BulletinBoard Widget (subclass of ManagerClass)
+ *
+ ***********************************************************************/
+
+
+/* Class record constants */
+
+extern WidgetClass XwbulletinWidgetClass;
+
+typedef struct _XwBulletinClassRec *XwBulletinWidgetClass;
+typedef struct _XwBulletinRec *XwBulletinWidget;
+
+
+/* synonyms added for consistent naming conventions */
+
+extern WidgetClass XwbulletinBoardWidgetClass;
+
+typedef struct _XwBulletinClassRec *XwBulletinBoardWidgetClass;
+typedef struct _XwBulletinRec *XwBulletinBoardWidget;
+
+
+
+
diff --git a/Xw/BBoardP.h b/Xw/BBoardP.h
new file mode 100644
index 0000000..258450f
--- /dev/null
+++ b/Xw/BBoardP.h
@@ -0,0 +1,71 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: BBoardP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for widgets which are
+ ** subclasses of bulletin board or which
+ ** need to access directly the instance/class
+ ** fields of the bulletin board widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/***********************************************************************
+ *
+ * BulletinBoard Widget Private Data
+ *
+ ***********************************************************************/
+
+/* New fields for the BulletinBoard widget class record */
+typedef struct {
+ int mumble; /* No new procedures */
+} XwBulletinClassPart;
+
+/* Full class record declaration */
+typedef struct _XwBulletinClassRec {
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwBulletinClassPart bulletin_board_class;
+} XwBulletinClassRec;
+
+extern XwBulletinClassRec XwbulletinClassRec;
+
+/* New fields for the Bulletin widget record */
+typedef struct {
+ int mumble; /* No new fields */
+} XwBulletinPart;
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwBulletinRec {
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwBulletinPart bulletin_board;
+} XwBulletinRec;
+
diff --git a/Xw/Button.c b/Xw/Button.c
new file mode 100644
index 0000000..f495380
--- /dev/null
+++ b/Xw/Button.c
@@ -0,0 +1,786 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Button.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code/Definitions for Button widget meta class.
+ **
+ ****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>************************************/
+
+
+/*
+ * Include files & Static Routine Definitions
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/StringDefs.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xatom.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+
+static Boolean SetValues();
+static void ButtonDestroy();
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: resource list for class: Button
+ * -----------
+ *
+ * Provides default resource settings for instances of this class.
+ * To get full set of default settings, examine resouce list of super
+ * classes of this class.
+ *
+ *************************************<->***********************************/
+
+static XtResource resources[] =
+{
+
+ {
+ XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset (XwButtonWidget, button.font), XtRString, "Fixed"
+ },
+
+ {
+ XtNlabel, XtCLabel, XtRString, sizeof (caddr_t),
+ XtOffset (XwButtonWidget, button.label), XtRString, NULL
+ },
+
+ {
+ XtNlabelLocation, XtCLabelLocation, XtRLabelLocation, sizeof(int),
+ XtOffset (XwButtonWidget, button.label_location), XtRString, "right"
+ },
+
+ {
+ XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
+ XtOffset (XwButtonWidget, button.internal_height), XtRString, "2"
+ },
+
+ {
+ XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
+ XtOffset (XwButtonWidget, button.internal_width), XtRString, "2"
+ },
+
+ {
+ XtNset, XtCSet, XtRBoolean, sizeof (Boolean),
+ XtOffset (XwButtonWidget, button.set), XtRString, "False"
+ },
+
+ {
+ XtNsensitiveTile, XtCSensitiveTile, XtRTileType, sizeof (int),
+ XtOffset(XwButtonWidget, button.sensitive_tile),
+ XtRString, "foreground"
+ },
+
+ {
+ XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
+ XtOffset(XwButtonWidget,core.border_width), XtRString, "0"
+ },
+};
+
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: global class record for instances of class: Button
+ * -----------
+ *
+ * Defines default field settings for this class record. Note that
+ * while Button needs a special type converter, it doesn't need to
+ * register that converter since Primitive takes care of registering
+ * all of the converters for the X Widgets library and Button is a
+ * subclass of Primitive.
+ *
+ *************************************<->***********************************/
+
+XwButtonClassRec XwbuttonClassRec =
+{
+ {
+ (WidgetClass) &XwprimitiveClassRec, /* superclass */
+ "XwButton", /* class_name */
+ sizeof(XwButtonRec), /* widget_size */
+ NULL, /* class_initialize */
+ NULL, /* class part initialize */
+ FALSE, /* class_inited */
+ _XwInitializeButton, /* initialize */
+ NULL, /* initialize hook */
+ NULL, /* realize */
+ NULL, /* actions */
+ 0, /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ TRUE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ ButtonDestroy, /* destroy */
+ NULL, /* resize */
+ NULL, /* expose */
+ SetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* toolkit version */
+ NULL, /* PRIVATE callback */
+ NULL, /* tm_table */
+ NULL, /* query_geometry */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+
+ /* Inherit procedures for handling traversal and selection */
+ {
+ (XtWidgetProc) XtInheritBorderHighlight,
+ (XtWidgetProc) XtInheritBorderUnhighlight,
+ (XwEventProc) XtInheritSelectProc,
+ (XwEventProc) XtInheritReleaseProc,
+ (XwEventProc) XtInheritToggleProc,
+ },
+
+ {
+ 0, /* Button class part - unused */
+ }
+};
+
+WidgetClass XwbuttonWidgetClass = (WidgetClass) &XwbuttonClassRec;
+
+
+
+/*************************************<->*************************************
+ *
+ * ButtonDestroy (bw)
+ *
+ * Description:
+ * -----------
+ * Free up the space taken by the button's label and free up the
+ * button's graphic contexts.
+ *
+ *
+ * Inputs:
+ * ------
+ * bw = button (or subclass of button) to be destroyed.
+ *
+ *************************************<->***********************************/
+static void ButtonDestroy (bw)
+ XwButtonWidget bw;
+{
+ if (bw->button.label)
+ XtFree (bw->button.label);
+ XtDestroyGC (bw->button.normal_GC);
+ XtDestroyGC (bw->button.inverse_GC);
+}
+
+/*************************************<->*************************************
+ *
+ * SetValues(current, request, new, last)
+ *
+ * Description:
+ * -----------
+ * This is the set values procedure for the button class.
+ *
+ *
+ * Inputs:
+ * ------
+ * current = original widget;
+ * request = copy of current (?);
+ * new = copy of request which reflects changes made to it by
+ * set values procedures of its superclasses;
+ * last = TRUE if this is the last set values procedure to be called.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues(current, request, new)
+ Widget current, request, new;
+{
+ XwButtonWidget curcbox = (XwButtonWidget) current;
+ XwButtonWidget newcbox = (XwButtonWidget) new;
+ Boolean flag = FALSE; /* our return value */
+ int GCflag = 0;
+
+#define NewNormal 1
+#define NewInverse 2
+
+
+ /************************************************************
+ * If the button setting has been changed then set flag so that
+ * button will be redisplayed. NOTE THAT IF THE APPLICATION
+ * WANTS THE CALLBACKS ASSOCIATED WITH THE BUTTON TO BE INVOKED
+ * IT WILL HAVE TO DIRECTLY CALL XTCALLCALLBACKS.
+ ************************************************************/
+ if (curcbox->button.set != newcbox->button.set) flag = TRUE;
+
+
+ /************************************************************
+ * If the font has been changed then we need to
+ * recompute the text width and height. We'll also have
+ * to change other things, see below...
+ ************************************************************/
+ if (curcbox->button.font != newcbox->button.font)
+ {
+ _XwSetTextWidthAndHeight(newcbox);
+ flag = TRUE;
+ }
+
+
+ /**************************************************************
+ * If a new label has been provided then we'll need to copy it
+ * into our data space.
+ * Free up any space previously allocated for the label name.
+ * NOTE: We allow them to specify a NULL label.
+ ***************************************************************/
+ if (curcbox->button.label != newcbox->button.label)
+ {
+ /* Set label length, height and width */
+ _XwSetTextWidthAndHeight(newcbox);
+
+ if (newcbox->button.label)
+ newcbox->button.label = strcpy(
+ XtMalloc((unsigned) newcbox->button.label_len + 1),
+ newcbox->button.label);
+
+ if (curcbox->button.label)
+ XtFree ((char *) curcbox->button.label);
+ flag = TRUE;
+ }
+
+
+
+ /**********************************************************************
+ * If the label location flag has changed set the redisplay flag TRUE
+ * and check that it has a valid setting. If its invalid, then issue
+ * a warning.
+ ********************************************************************/
+ if (curcbox->button.label_location != newcbox->button.label_location)
+ {
+ flag = TRUE;
+ if ((newcbox->button.label_location != XwLEFT) &&
+ (newcbox->button.label_location != XwRIGHT) &&
+ (newcbox->button.label_location != XwCENTER))
+ {
+ XtWarning("SetValues: Invalid Label Location Setting.");
+ newcbox->button.label_location =
+ curcbox->button.label_location;
+ }
+ }
+
+ /*********************************************************************
+ * If the sensitive tile has changed, validate it. Then, if the
+ * foreground or background or font or sensitive tile has changed
+ * then recompute/get a new (In)sensitive GC.
+ ********************************************************************/
+ if (newcbox->button.sensitive_tile != XwFOREGROUND)
+ {
+ newcbox->button.sensitive_tile = curcbox->button.sensitive_tile;
+ XtWarning("SetValues: Invalid sensitive tile setting.");
+ }
+
+ if (curcbox->primitive.foreground != newcbox->primitive.foreground ||
+ curcbox->core.background_pixel != newcbox->core.background_pixel)
+ {
+ /* GET ALL NEW GC's */
+ GCflag = NewNormal | NewInverse;
+ }
+
+ if (curcbox->button.font->fid != newcbox->button.font->fid)
+ {
+ /* GET NEW GC's FOR normal & inverse */
+ GCflag = NewNormal | NewInverse;
+ }
+
+ if ((curcbox->button.sensitive_tile != newcbox->button.sensitive_tile) &&
+ (! newcbox->core.sensitive || ! newcbox->core.ancestor_sensitive))
+ {
+ /* GET NEW normal GC */
+ GCflag |= NewNormal;
+ }
+
+ if ((newcbox->core.sensitive != curcbox->core.sensitive) &&
+ ((newcbox->core.sensitive && newcbox->core.ancestor_sensitive) ||
+ (!newcbox->core.sensitive && curcbox->core.ancestor_sensitive)))
+ {
+ /* GET NEW normal GC */
+ GCflag |= NewNormal;
+ }
+ else if (newcbox->core.sensitive &&
+ (curcbox->core.ancestor_sensitive != newcbox->core.ancestor_sensitive))
+ {
+ /* GET NEW normal GC */
+ GCflag |= NewNormal;
+ }
+
+
+
+ if (GCflag & NewNormal)
+ {
+ XtDestroyGC(curcbox->button.normal_GC);
+ _XwGetNormalGC(newcbox);
+ flag = TRUE;
+ }
+ if (GCflag & NewInverse)
+ {
+ XtDestroyGC(curcbox->button.inverse_GC);
+ _XwGetInverseGC(newcbox);
+ flag = TRUE;
+ }
+
+
+ /********************************************************************
+ * NOTE THAT SUBCLASSES OF BUTTON WILL HAVE TO CHECK FOR CHANGES IN
+ * internal_width, internal_height AND DETERMINE WHAT SHOULD BE DONE.
+ * WE'RE JUST BEING GOOD CITIZENS HERE AND FLAGING THAT IT WILL HAVE
+ * TO BE REDISPLAYED BECAUSE OF THE CHANGE.
+ *********************************************************************/
+ if ((curcbox->button.internal_width
+ != newcbox->button.internal_width) ||
+ (curcbox->button.internal_height
+ != newcbox->button.internal_height)) flag = TRUE;
+
+
+ return( flag );
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * void _XwSetTextWidthAndHeight (aButton)
+ *
+ * Description:
+ * -----------
+ * Calculate width and height of displayed text in pixels.
+ * Sets the following fields in the button portion of a button
+ * instance record:
+ *
+ * label_len
+ * label_height
+ * label_width
+ *
+ * Inputs:
+ * ------
+ * aButton = XwButtonWidget
+ *
+ * Procedures Called
+ * -----------------
+ * XwStrlen() [a macro: #define XwStrlen(s) ((s) ? strlen(s) : 0) ]
+ * XTextWidth()
+ *************************************<->***********************************/
+
+void _XwSetTextWidthAndHeight(aButton)
+ XwButtonWidget aButton;
+{
+ register XFontStruct *fs = aButton->button.font;
+
+ aButton->button.label_height =
+ fs->max_bounds.ascent + fs->max_bounds.descent;
+
+ if (aButton->button.label)
+ {
+ aButton->button.label_len = XwStrlen(aButton->button.label);
+
+ aButton->button.label_width = XTextWidth(
+ fs, aButton->button.label,
+ (int) aButton->button.label_len);
+ }
+ else
+ {
+ aButton->button.label_len = 0;
+ aButton->button.label_width = 0;
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * void _XwGetNormalGC(aButton)
+ * XwButtonWidget aButton;
+ *
+ * Description:
+ * -----------
+ * Uses the widget specific foreground to generate the "normal"
+ * graphic context. Note that this is a XToolkit sharable GC.
+ * Creates the needed GC and sets ptr. in instance record.
+ *
+ * Inputs:
+ * ------
+ * aButton = widget instance.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtGetGC
+ *************************************<->***********************************/
+
+void _XwGetNormalGC(aButton)
+ XwButtonWidget aButton;
+{
+ XGCValues values;
+
+ values.foreground = aButton->primitive.foreground;
+ values.background = aButton->core.background_pixel;
+ values.font = aButton->button.font->fid;
+
+ values.line_width = 1;
+ aButton->button.normal_GC = XtGetGC((Widget)aButton,
+ (unsigned) GCForeground |
+ (unsigned) GCBackground |
+ GCLineWidth |
+ GCFont,
+ &values);
+}
+
+/*************************************<->*************************************
+ *
+ * void _XwGetInverseGC(aButton)
+ * XwButtonWidget aButton;
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ * aButton = widget instance.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XwGetGC
+ *************************************<->***********************************/
+
+void _XwGetInverseGC(aButton)
+ XwButtonWidget aButton;
+{
+ XGCValues values;
+ values.foreground = aButton->core.background_pixel;
+ values.background = aButton->primitive.foreground;
+ values.font = aButton->button.font->fid;
+ values.line_width = 1;
+
+ aButton->button.inverse_GC = XtGetGC((Widget)aButton,
+ (unsigned) GCForeground | (unsigned) GCBackground |
+ GCLineWidth | GCFont, &values);
+}
+
+/*************************************<->*************************************
+ *
+ * _XwInitializeButton (request, new)
+ *
+ * Description:
+ * -----------
+ * This is the button instance initialize procedure. Make sure
+ * that the button has a label, compute its height and width fields;
+ * set the appropriate graphic contexts.
+ *
+ * Inputs:
+ * ------
+ * request = original instance record;
+ *
+ * new = instance record with modifications induced by
+ * other initialize routines, changes are made to this
+ * record;
+ *
+ * args = argument list specified in XtCreateWidget;
+ *
+ * num_args = argument count;
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+void _XwInitializeButton (request, new)
+Widget request, new;
+
+{
+ XwButtonWidget aButton = (XwButtonWidget) new;
+
+ /*
+ * NOTE: we don't allow a NULL string for our button label.
+ * If we do find a NULL at initialize time then we will use the
+ * button name. The rationale for this is that this allows someone
+ * to change the button label in the .Xdefaults file, whereas if
+ * the application programmer hardwired the name into an arg list
+ * it would be impossible to change. However, if you really want
+ * a NULL string, do a SetValues and change the label to NULL.
+ *
+ * We need to malloc space for this string and copy it to our
+ * space. The toolkit simply copies the pointer to the string.
+ */
+ if (aButton->button.label == NULL) aButton->button.label =
+ aButton->core.name;
+
+ aButton->button.label = strcpy( XtMalloc((unsigned)
+ (XwStrlen(aButton->button.label)+1)),
+ aButton->button.label);
+
+
+ /*
+ * make sure that sensitive_tile is valid
+ */
+ if (aButton->button.sensitive_tile != XwFOREGROUND)
+ {
+ aButton->button.sensitive_tile = XwFOREGROUND;
+ XtWarning("Initialize: Invalid sensitive tile setting.");
+ }
+
+
+ _XwGetInverseGC(aButton);
+ _XwGetNormalGC(aButton);
+
+ _XwSetTextWidthAndHeight(aButton);
+
+ aButton->primitive.display_sensitive = FALSE;
+ aButton->primitive.highlighted = FALSE;
+
+
+} /* _XwInitializeButton */
+
+
+/*************************************<->*************************************
+ *
+ * _XwRealize
+ *
+ * Description:
+ * -----------
+ * This is a generalize routine used by both subclasses of Primitive
+ * and Manager. It sets bit gravity to NW for managers and to Forget
+ * for others, but for Buttons is sets it according to the setting of
+ * label location.
+ *
+ * Inputs
+ * ------
+ * w = widget to be realized.
+ *
+ * valueMask = contains event mask for this window/widget.
+ *
+ * attributes = window attributes for this window/widget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XCreateWindow()
+ *************************************<->***********************************/
+
+void _XwRealize(w, p_valueMask, attributes)
+ register Widget w;
+ Mask *p_valueMask;
+ XSetWindowAttributes *attributes;
+{
+ Mask valueMask = *p_valueMask;
+ valueMask |= CWBitGravity;
+
+ if (XtIsSubclass(w, XwprimitiveWidgetClass)) {
+ register XwPrimitiveWidget pw = (XwPrimitiveWidget) w;
+ if (pw->primitive.cursor != None) valueMask |= CWCursor;
+ attributes->cursor = pw->primitive.cursor;
+ }
+
+ if (XtIsSubclass(w, XwmanagerWidgetClass))
+ attributes->bit_gravity = NorthWestGravity;
+ else
+ if (w->core.widget_class != XwbuttonWidgetClass)
+ attributes->bit_gravity = ForgetGravity;
+ else
+ switch (((XwButtonWidget)w)->button.label_location)
+ {
+ case XwRIGHT:
+ attributes->bit_gravity = EastGravity; break;
+ case XwLEFT:
+ attributes->bit_gravity = WestGravity; break;
+ case XwCENTER:
+ attributes->bit_gravity = CenterGravity; break;
+ }
+
+ XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent,
+ valueMask, attributes);
+
+ _XwRegisterName(w); /* hang widget name as property on window */
+
+} /* _XwRealize */
+
+
+/*************************************<->*************************************
+ *
+ * _XwResizeButton(w)
+ *
+ * Description:
+ * -----------
+ * A resize event has been generated. Recompute location of button
+ * elements.
+ *
+ * USED BY CHECKBOX AND PUSHBUTTON CLASSES.
+ *
+ * Inputs:
+ * ------
+ * w = widget to be resized.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+
+void _XwResizeButton(w)
+ Widget w;
+{
+ register XwButtonWidget aButton = (XwButtonWidget) w;
+ int direction = aButton->button.label_location;
+
+ switch (direction)
+ {
+ case XwCENTER:
+ aButton->button.label_x = ((int)aButton->core.width + 1 -
+ (int)aButton->button.label_width) / 2;
+ break;
+
+ case XwRIGHT:
+ aButton->button.label_x = (int)aButton->core.width -
+ (int)aButton->button.internal_width -
+ aButton->primitive.highlight_thickness -
+ (int)aButton->button.label_width;
+ break;
+
+ default:
+ aButton->button.label_x = aButton->button.internal_width +
+ aButton->primitive.highlight_thickness;
+ }
+
+ aButton->button.label_y =
+ (((int)aButton->core.height - (int)aButton->button.label_height) >> 1)
+ + aButton->button.font->max_bounds.ascent;
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * This procedure is used to store the name of the widget as a
+ * property on the widget's window. The property name is the
+ * string "XW_NAME". Note that we do not malloc space for the
+ * widget's name, we merely use the pointer to this string which
+ * is already in core.name. This shouldn't be a problem since
+ * the name will remain as long as the widget exists.
+ *
+ * We only want to do this one time, thus the hokey method of
+ * initializing a static boolean which prevents us from registering
+ * this atom more than once on the server.
+ *
+ * If possible, we should put this together with other functions done
+ * once. Also, WILL THIS BE A PROBLEM WHEN THE TOOLKIT ALLOWS MORE
+ * THAN ONE DISPLAY TO BE OPENED?????
+ *
+ * Inputs:
+ * ------
+ * w = widget being created.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Atom widget_name;
+static Boolean first=True;
+
+void _XwRegisterName(w)
+ Widget w;
+{
+ if (first)
+ {
+ widget_name = XInternAtom (XtDisplay(w), "XW_NAME", False);
+ first = False;
+ }
+ XChangeProperty (XtDisplay(w), XtWindow(w), widget_name, XA_STRING, 8,
+ PropModeReplace, w->core.name,
+ XwStrlen(w->core.name)+1);
+}
+
+
+/*************************************<->*************************************
+ * Boolean
+ * _XwRecomputeSize(current, new)
+ *
+ * Description:
+ * -----------
+ * Used during SetValues for PButton and Toggle.
+ * If the font has changed OR the label has changed OR
+ * the internal spacing has changed OR the highlight
+ * thickness has changed AND the recompute flag is TRUE
+ * (in the new widget) return TRUE, else return FALSE.
+ *
+ *
+ * Inputs:
+ * ------
+ * current = current version of widget
+ * new = new version of widget
+ *
+ * Outputs:
+ * -------
+ * TRUE if resize is needed and okay, FALSE otherwise.
+ *
+ *************************************<->***********************************/
+ Boolean _XwRecomputeSize(current, new)
+ XwButtonWidget current, new;
+{
+ if (((new->button.font != current->button.font) ||
+ (new->button.label != current->button.label) ||
+ (new->primitive.highlight_thickness !=
+ current->primitive.highlight_thickness) ||
+ (new->button.internal_height != current->button.internal_height) ||
+ (new->button.internal_width != current->button.internal_width)) &&
+ (new->primitive.recompute_size == TRUE))
+ return(TRUE);
+ else
+ return(FALSE);
+}
+
+
+
diff --git a/Xw/Cascade.c b/Xw/Cascade.c
new file mode 100644
index 0000000..b84ec01
--- /dev/null
+++ b/Xw/Cascade.c
@@ -0,0 +1,1374 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Cascade.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code and class record for Cascade widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/CascadeP.h>
+#include <Xw/Cascade.h>
+#include <Xw/MenuBtnP.h>
+#include <Xw/MenuBtn.h>
+#include <ctype.h>
+
+static void Initialize();
+static void Realize();
+static void Resize();
+static void Redisplay();
+static void InsertChild();
+static void Select();
+static void Leave();
+static Boolean SetValues();
+static XtGeometryResult GeometryManager();
+static void ChangeManaged();
+static void GetFontGC();
+static void SetTitleAttributes();
+static void Visibility();
+static void Unmap();
+
+/* The following are used for layout spacing */
+
+#define PADDING_TO_LEFT 2
+#define PADDING_TO_RIGHT 2
+#define PADDING_FROM_ABOVE 2
+#define PADDING_FROM_BELOW PADDING_FROM_ABOVE
+#define PADDING_FOR_UNDERLINE 0 /* No longer used */
+#define DOUBLE_LINES 4
+
+
+/****************************************************************
+ *
+ * Default translation table for class: MenuPane manager
+ *
+ ****************************************************************/
+
+static char defaultTranslations[] =
+ "<Btn1Down>: select()\n\
+ <Visible>: visible()\n\
+ <Unmap>: unmap()\n\
+ <LeaveWindow>: leave()";
+
+
+/****************************************************************
+ *
+ * Action list for class: MenuPane manager
+ *
+ ****************************************************************/
+
+static XtActionsRec actionsList[] = {
+ {"select", (XtActionProc) Select},
+ {"visible", (XtActionProc) Visibility},
+ {"unmap", (XtActionProc) Unmap},
+ {"leave", (XtActionProc) Leave},
+};
+
+
+/****************************************************************
+ *
+ * MenuPane Resources
+ *
+ ****************************************************************/
+
+static XtResource resources[] = {
+ {XtNtitlePosition, XtCTitlePosition, XtRTitlePositionType, sizeof(int),
+ XtOffset(XwCascadeWidget, cascade.titlePosition),XtRString,"top"},
+};
+
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+XwCascadeClassRec XwcascadeClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwmenupaneClassRec,
+ /* class_name */ "XwCascade",
+ /* widget_size */ sizeof(XwCascadeRec),
+ /* class_initialize */ NULL,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actionsList,
+ /* num_actions */ XtNumber(actionsList),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ NULL,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* PRIVATE cb list */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },{
+/* composite_class fields */
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ ChangeManaged,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ NULL
+ },{
+/* constraint class fields */
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ sizeof (Boolean),
+ /* initialize */ (XtInitProc)XtInheritMenuPaneConstraintInit,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ NULL
+ },{
+/* manager_class fields */
+ /* traversal handler */ (XwTraversalProc)XtInheritTraversalProc,
+ /* translations */ NULL
+ },{
+/* menu pane class - none */
+ /* setTraversalFlag */ XtInheritSetTraversalFlagProc
+ },{
+/* cascade class - none */
+ /* mumble */ 0
+ }
+};
+
+WidgetClass XwcascadeWidgetClass = (WidgetClass)&XwcascadeClassRec;
+
+
+/*************************************<->*************************************
+ *
+ * Select ()
+ *
+ * Description:
+ * -----------
+ * Called upon receipt of a 'select' action; simple invokes callbacks.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Select (w, event)
+
+ Widget w;
+ XEvent * event;
+
+{
+ Widget parent, grandparent;
+
+ if ((parent = XtParent(w)) &&
+ (grandparent = XtParent(parent)) &&
+ (XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
+ {
+ /* Ask the menu mgr if we should process or ignore the select */
+ if ((*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ processSelect) (grandparent, w, event) == FALSE)
+ {
+ return;
+ }
+ }
+
+ XtCallCallbacks (w, XtNselect, NULL);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Leave()
+ *
+ * Description:
+ * -----------
+ * Called upon receipt of a LeaveNotify event; this is a NOOP, whose
+ * purpose is to simply prevent us from using the LeaveNotify handler
+ * supplied by the Manager class. The Manager's action routine does
+ * an XSetInputFocus() to root, which is not what we want here.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Leave (w, event)
+
+ Widget w;
+ XEvent * event;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * GetIdealSize
+ *
+ * Description:
+ * -----------
+ * Returns the minimum height and width into which the menu pane will fit.
+ * replyHeight and replyWidth are set to the minimum acceptable size.
+ * Also, the maxCascadeWidth, maxLabel and largestButtonWidth fields are
+ * set in the widget structure.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static GetIdealSize(mw, replyWidth, replyHeight)
+
+ XwCascadeWidget mw;
+ Dimension *replyWidth, *replyHeight; /* RETURN */
+
+{
+ Cardinal i;
+ Dimension minWidth, minHeight, largestButtonWidth;
+ XwMenuButtonWidget menuButton; /* Current button */
+ Dimension idealWidth;
+
+
+ /*
+ * First, compute the minimum width (less padding) needed for
+ * these items; include the title in these calculations.
+ */
+
+ minWidth = largestButtonWidth = 0;
+ minHeight = mw->manager.highlight_thickness << 1;
+
+ if (mw->menu_pane.title_showing && !mw->menu_pane.title_override)
+ {
+ if (mw->menu_pane.title_type == XwSTRING)
+ {
+ minWidth = mw->cascade.title_width +
+ PADDING_TO_LEFT +
+ PADDING_TO_RIGHT;
+ largestButtonWidth = minWidth;
+ if (mw->cascade.titlePosition & XwTOP)
+ {
+ minHeight += mw->cascade.title_height +
+ PADDING_FROM_ABOVE +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ {
+ minHeight += mw->cascade.title_height +
+ PADDING_FROM_BELOW +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+ }
+ else
+ {
+ minWidth = mw->cascade.title_width +
+ PADDING_TO_LEFT +
+ PADDING_TO_RIGHT;
+ largestButtonWidth = minWidth;
+ if (mw->cascade.titlePosition & XwTOP)
+ {
+ minHeight += mw->cascade.title_height +
+ PADDING_FROM_ABOVE +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ {
+ minHeight += mw->cascade.title_height +
+ PADDING_FROM_BELOW +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+ }
+ }
+
+ minWidth += mw->manager.highlight_thickness << 1;
+
+
+ /*
+ * Determine the ideal size for each button; keep track of largest button
+ */
+
+ for (i=0; i < mw->manager.num_managed_children; i++)
+ {
+ menuButton = (XwMenuButtonWidget) mw->manager.managed_children[i];
+
+ /*
+ * If we are in the middle of a geometry request from one of
+ * our children, then we need to use the ideal size of the
+ * requesting widget, instead of the current widget. Otherwise,
+ * ask the widget for its ideal size.
+ */
+ if ((Widget) menuButton == mw->cascade.georeqWidget)
+ idealWidth = mw->cascade.georeqWidth;
+ else if (XtIsSubclass ((Widget)menuButton, XwmenubuttonWidgetClass))
+ {
+ (*(((XwMenuButtonWidgetClass)XtClass(menuButton))->
+ menubutton_class.idealWidthProc))((Widget)menuButton, &idealWidth);
+ }
+ else
+ idealWidth = menuButton->core.width;
+
+ minWidth = Max (minWidth, idealWidth +
+ (mw->manager.highlight_thickness << 1) +
+ (menuButton->core.border_width << 1));
+ largestButtonWidth = Max (largestButtonWidth, idealWidth);
+ minHeight += menuButton->core.height +
+ (menuButton->core.border_width << 1);
+ }
+
+
+ /* Set up return values */
+ if (minWidth == 0) minWidth = 1;
+ if (minHeight == 0) minHeight = 1;
+
+ if (replyWidth != NULL) *replyWidth = minWidth;
+ if (replyHeight != NULL) *replyHeight = minHeight;
+
+ mw->cascade.idealHeight = minHeight;
+ mw->cascade.idealWidth = minWidth;
+ mw->cascade.largestButtonWidth = largestButtonWidth;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * Returns the minimum height and width into which the menu pane will fit.
+ * If the current menu pane size is small than this, then FALSE is
+ * returned; else, TRUE is returned. In all cases, replyHeight and
+ * replyWidth are set to the minimum acceptable size.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean PreferredSize(mw, width, height, replyWidth, replyHeight)
+ XwCascadeWidget mw;
+ Dimension width, height;
+ Dimension *replyWidth, *replyHeight;
+{
+ GetIdealSize(mw, replyWidth, replyHeight);
+
+ return ((*replyWidth <= width) && (*replyHeight <= height));
+}
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * This routine assumes the menu pane size has already been updated in
+ * the core record. It will simply relayout the menu buttons, to fit
+ * the new menu pane size. This is called when XtResizeWidget() is invoked,
+ * and when our own geometry manager tries to change our size because one
+ * of our children is trying to change its size.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Resize(mw)
+
+ XwCascadeWidget mw;
+
+{
+ Cardinal i;
+ Cardinal xPos, yPos;
+ Dimension oldHeight;
+ XwMenuButtonWidget menuButton; /* Current button */
+ Dimension cascadeWidth, labelX;
+
+
+ /* Recalculate where the title string should be displayed */
+ mw->cascade.title_x = ((mw->core.width >> 1) +
+ mw->manager.highlight_thickness) -
+ (mw->cascade.title_width >> 1);
+
+ /* This is a two step process: first move the item, then resize it */
+ xPos = mw->manager.highlight_thickness;
+ yPos = mw->cascade.button_starting_loc;
+
+ for (i = 0; i < mw->manager.num_managed_children; i++)
+ {
+ menuButton = (XwMenuButtonWidget) mw->manager.managed_children[i];
+ XtMoveWidget ((Widget)menuButton, xPos, yPos);
+
+ /*
+ * The following kludge will force the widget's resize routine
+ * to always be called.
+ */
+ oldHeight = menuButton->core.height;
+ menuButton->core.height = 0;
+ menuButton->core.width = 0;
+
+ XtResizeWidget ((Widget)menuButton,
+ mw->cascade.largestButtonWidth,
+ oldHeight,
+ menuButton->core.border_width);
+
+ yPos += menuButton->core.height +
+ (menuButton->core.border_width << 1);
+ }
+
+ SetTitleAttributes (mw, FALSE);
+} /* Resize */
+
+
+/*************************************<->*************************************
+ *
+ * TryNewLayout (parameters)
+ *
+ * Description:
+ * -----------
+ * This determines if the menu pane needs to change size. If it needs to
+ * get bigger, then it will ask its parent's geometry manager; if this
+ * succeeds, then the menu pane window will be resized (NOTE: the menu
+ * buttons are not touched yet). Also, if our resize request succeeded,
+ * the our parent's geometry manager will have updated our size fields
+ * in our core structure. This is called during a Change Manage request,
+ * and when one of our children issues a geometry request.
+ *
+ * NOTE: menu panes ALWAYS use their 'preferred' size.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean TryNewLayout(mw)
+ XwCascadeWidget mw;
+{
+ XtWidgetGeometry request, reply;
+ XtGeometryResult r;
+
+ if ((mw->core.width == mw->cascade.idealWidth) &&
+ (mw->core.height == mw->cascade.idealHeight))
+ {
+ /* Same size */
+ return (TRUE);
+ }
+
+
+ switch (XtMakeResizeRequest ((Widget) mw, mw->cascade.idealWidth,
+ mw->cascade.idealHeight, NULL, NULL))
+ {
+ case XtGeometryYes:
+ return (TRUE);
+
+ case XtGeometryNo:
+ case XtGeometryAlmost:
+ return (FALSE);
+ }
+
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * Invoked when one of our children wants to change its size. This routine
+ * will automatically update the size fields within the child's core
+ * area.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+/*ARGSUSED*/
+static XtGeometryResult GeometryManager(w, request, reply)
+ Widget w;
+ XtWidgetGeometry *request;
+ XtWidgetGeometry *reply; /* RETURN */
+
+{
+ Dimension width, height, borderWidth, junkH, junkW, newHeight;
+ XwCascadeWidget mw;
+ XtGeometryResult result = XtGeometryYes;
+ Boolean isPreferredSize;
+ int i;
+
+ /*
+ * Since the manager is solely responsible for controlling the position
+ * of its children, any geometry request made which attempts to modify
+ * the child's position will not be satified; instead, a compromise will
+ * be returned, with the position bits cleared.
+ */
+ reply->request_mode = 0;
+
+ if (request->request_mode & (CWX | CWY))
+ result = XtGeometryAlmost;
+
+ mw = (XwCascadeWidget) w->core.parent;
+
+
+ /* Size changes must see if the new size can be accomodated */
+ if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
+
+ /* Make all three fields in the request valid */
+ if ((request->request_mode & CWWidth) == 0)
+ request->width = w->core.width;
+ if ((request->request_mode & CWHeight) == 0)
+ request->height = w->core.height;
+ if ((request->request_mode & CWBorderWidth) == 0)
+ request->border_width = w->core.border_width;
+
+ /* Set the new size within the widget */
+ width = w->core.width;
+ height = w->core.height;
+ borderWidth = w->core.border_width;
+ w->core.width = request->width;
+ w->core.height = request->height;
+ w->core.border_width = request->border_width;
+
+ /* Calculate the new height needed to hold the menu */
+ newHeight = mw->core.height - (height + borderWidth) +
+ (request->height + request->border_width);
+
+ /* Let the layout routine know we are in the middle of a geo req */
+ mw->cascade.georeqWidget = w;
+ mw->cascade.georeqWidth = request->width;
+
+ /* See if we can allow this size request */
+ isPreferredSize = PreferredSize (mw, w->core.width +
+ (w->core.border_width << 1) +
+ (mw->manager.highlight_thickness << 1),
+ newHeight, &junkW, &junkH);
+
+ /* Cleanup */
+ mw->cascade.georeqWidget = (Widget) NULL;
+
+ /*
+ * Only allow an item to shrink if it was the largest item.
+ * However, always allow the item to get bigger.
+ */
+
+ if (!isPreferredSize)
+ {
+ /*
+ * The widget is attempting to make itself smaller than is allowed;
+ * therefore, we must return a compromise size, which we know will
+ * succeed.
+ */
+ reply->width = junkW - (mw->manager.highlight_thickness << 1) -
+ (w->core.border_width << 1);
+ reply->height = request->height;
+ reply->border_width = request->border_width;
+ reply->request_mode = CWWidth | CWHeight | CWBorderWidth;
+ result = XtGeometryAlmost;
+
+ /* Restore the previous size values */
+ w->core.width = width;
+ w->core.height = height;
+ w->core.border_width = borderWidth;
+ }
+ else
+ {
+ if (result == XtGeometryAlmost)
+ {
+ /*
+ * Even though the size request succeeded, the request cannot
+ * be satisfied, since someone before us has already set the
+ * result to XtGeometryAlmost; most likely, it was because
+ * an attempt was made to change the X or Y values.
+ */
+ reply->width = request->width;
+ reply->height = request->height;
+ reply->border_width = request->border_width;
+ reply->request_mode = CWWidth | CWHeight | CWBorderWidth;
+
+ /* Restore the previous size values */
+ w->core.width = width;
+ w->core.height = height;
+ w->core.border_width = borderWidth;
+ }
+ else
+ {
+ /*
+ * All components of the geometry request could be satisfied,
+ * so make all necessary adjustments, and return a 'Yes'
+ * response to the requesting widget.
+ */
+ TryNewLayout (mw);
+ Resize (mw);
+ /* SetTitleAttributes (mw, FALSE); */
+ width = w->core.width;
+ height = w->core.height;
+ borderWidth = w->core.border_width;
+ result = XtGeometryDone;
+ }
+ }
+ }; /* if any size changes requested */
+
+ /*
+ * Stacking changes are always allowed. However, if the result has
+ * already been set to XtGeometryAlmost, then some portion of the
+ * request has already failed, so we need to copy the stacking request
+ * back into the 'reply' structure, so that they are not lost.
+ */
+
+ if (result == XtGeometryAlmost)
+ {
+ if (request->request_mode & CWSibling)
+ {
+ reply->request_mode |= CWSibling;
+ reply->sibling = request->sibling;
+ }
+
+ if (request->request_mode & CWStackMode)
+ {
+ reply->request_mode |= CWStackMode;
+ reply->stack_mode = request->stack_mode;
+ }
+ }
+
+ return (result);
+ }
+
+
+/*************************************<->*************************************
+ *
+ * ChangeManaged
+ *
+ * Description:
+ * -----------
+ * Forces the managed_children list to be updated, and then attempts to
+ * relayout the menu buttons. If the menu pane is not large enough, then
+ * it will ask its geometry manager to enlarge it. This is invoked when
+ * a new child is managed, or an existing one is unmanaged. NOTE: only
+ * managed children which also have the mapped_when_managed flag set
+ * are included in the layout calculations.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ChangeManaged (mw)
+ XwCascadeWidget mw;
+{
+ Widget parent, grandparent;
+ Widget menubutton;
+ int i;
+ Boolean * managedConstraintFlag;
+
+ /* Reconfigure the button box */
+ _XwSetMappedManagedChildrenList(mw);
+ SetTitleAttributes (mw, FALSE);
+ GetIdealSize(mw, NULL, NULL);
+ (void) TryNewLayout(mw);
+ Resize(mw);
+
+ /*
+ * Tell the menu manager that the list of mapped & managed children
+ * has changed,
+ */
+ if ((parent = XtParent(mw)) &&
+ (grandparent = XtParent(parent)) &&
+ (XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ paneManagedChildren) (grandparent, (Widget)mw);
+ }
+
+ /*
+ * The constraint record has been updated by the menu manager.
+ */
+}
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ *
+ * Description:
+ * -----------
+ * Initialize the menu_pane fields within the widget's instance structure.
+ * Calls for registering the pane with a menu manager, and for attaching
+ * the pane to a menu button are handled by our meta class.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Initialize (request, new)
+ XwCascadeWidget request, new;
+{
+ Arg args2[2];
+
+ new->cascade.georeqWidget = (Widget) NULL;
+
+ /* Determine the title attributes, and the starting location for our kids */
+ SetTitleAttributes (new, TRUE);
+
+ /* Force our parent shell to be resizable */
+ XtSetArg (args2[0], XtNallowShellResize, TRUE);
+ XtSetArg (args2[1], XtNoverrideRedirect, TRUE);
+ XtSetValues (new->core.parent, args2, XtNumber(args2));
+
+ /* Augment our translations to include the traversal actions */
+ XtAugmentTranslations ((Widget) new,
+ XwmanagerClassRec.manager_class.translations);
+
+ /* KLUDGE!!! This is necessary!!! The shell must be realized so
+ * that the cascades changed_managed routine is called and the
+ * keyboard accelerators are set up for the menu manager.
+ */
+ if (new->core.height > 0)
+ (new->core.parent)->core.height = new->core.height;
+ else
+ (new->core.parent)->core.height = 1;
+
+ if (new->core.width > 0)
+ (new->core.parent)->core.width = new->core.width;
+ else
+ (new->core.parent)->core.width = 1;
+
+ if (XtIsSubclass(new->core.parent, shellWidgetClass))
+ XtRealizeWidget (new->core.parent);
+} /* Initialize */
+
+/*************************************<->*************************************
+ *
+ * Realize
+ *
+ * Description:
+ * -----------
+ * Invoked only when the menu pane is realized. It will create the window
+ * in which the menu pane will be displayed.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Realize(w, p_valueMask, attributes)
+ register Widget w;
+ Mask *p_valueMask;
+ XSetWindowAttributes *attributes;
+{
+ XwCascadeWidget mw;
+ Mask valueMask = *p_valueMask;
+
+ attributes->bit_gravity = ForgetGravity;
+ valueMask |= CWBitGravity;
+ mw = (XwCascadeWidget) w;
+
+ w->core.window =
+ XCreateWindow(XtDisplay(w), w->core.parent->core.window,
+ w->core.x, w->core.y, w->core.width, w->core.height,
+ w->core.border_width, w->core.depth,
+ InputOutput, (Visual *)CopyFromParent,
+ valueMask, attributes);
+
+ _XwRegisterName (w);
+} /* Realize */
+
+
+/*************************************<->*************************************
+ *
+ * SetValues
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues (current, request, new)
+ XwCascadeWidget current, request, new;
+{
+ Boolean redrawFlag = FALSE;
+
+ /*
+ * We never allow our traversal flags to be changed during SetValues();
+ * this is enforced by our superclass.
+ */
+
+ /* Validate the title position, and see if it has changed */
+
+ if ((new->cascade.titlePosition & (XwTOP | XwBOTTOM)) == 0)
+ {
+ new->cascade.titlePosition = current->cascade.titlePosition;
+ XtWarning (
+ "Cascade: Invalid title position; resetting to previous setting");
+ }
+
+ if ((current->cascade.titlePosition & (XwTOP | XwBOTTOM)) !=
+ (new->cascade.titlePosition & (XwTOP | XwBOTTOM)))
+ {
+ redrawFlag = TRUE;
+ }
+
+
+ SetTitleAttributes (new, FALSE);
+ GetIdealSize(new, NULL, NULL);
+ new->core.height = new->cascade.idealHeight;
+ new->core.width = new->cascade.idealWidth;
+
+ /*
+ * If the title position changes, but the size of the menupane
+ * does not (because no other attributes have changed which could
+ * cause the size to change), then we need to force a call to our
+ * resize() procedure, so that the menu buttons get repositioned
+ * relative to the new title position.
+ */
+ if (redrawFlag && (new->core.height == current->core.height) &&
+ (new->core.width == current->core.width))
+ {
+ Resize(new);
+ }
+
+ return (redrawFlag);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Redisplay
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Redisplay (w, event)
+ Widget w;
+ XEvent * event;
+{
+ XwCascadeWidget mw = (XwCascadeWidget) w;
+
+ /* If a title is defined, then redisplay it, if 'showing' flag set */
+ if (mw->menu_pane.title_showing && ! mw->menu_pane.title_override)
+ {
+
+ /* Recalculate the title position */
+ mw->cascade.title_x = (mw->core.width >> 1) +
+ mw->manager.highlight_thickness -
+ (mw->cascade.title_width >> 1);
+
+ if (mw->menu_pane.title_type == XwSTRING)
+ {
+ if (mw->cascade.titlePosition & XwTOP)
+ {
+ XDrawString (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC,
+ mw->cascade.title_x, mw->cascade.top_title_y,
+ mw->menu_pane.title_string,
+ XwStrlen(mw->menu_pane.title_string));
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.top_title_y +
+ mw->menu_pane.title_font->descent +
+ PADDING_FOR_UNDERLINE + 1,
+ mw->core.width,
+ mw->cascade.top_title_y +
+ mw->menu_pane.title_font->descent +
+ PADDING_FOR_UNDERLINE + 1);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.top_title_y +
+ mw->menu_pane.title_font->descent +
+ PADDING_FOR_UNDERLINE + 3,
+ mw->core.width,
+ mw->cascade.top_title_y +
+ mw->menu_pane.title_font->descent +
+ PADDING_FOR_UNDERLINE + 3);
+ }
+
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ {
+ XDrawString (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC,
+ mw->cascade.title_x, mw->cascade.bottom_title_y,
+ mw->menu_pane.title_string,
+ XwStrlen(mw->menu_pane.title_string));
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.bottom_title_y -
+ mw->menu_pane.title_font->ascent -
+ DOUBLE_LINES + 2,
+ mw->core.width,
+ mw->cascade.bottom_title_y -
+ mw->menu_pane.title_font->ascent -
+ DOUBLE_LINES + 2);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.bottom_title_y -
+ mw->menu_pane.title_font->ascent -
+ DOUBLE_LINES,
+ mw->core.width,
+ mw->cascade.bottom_title_y -
+ mw->menu_pane.title_font->ascent -
+ DOUBLE_LINES);
+ }
+ }
+ else if (mw->menu_pane.titleImage)
+ {
+ if (mw->cascade.titlePosition & XwTOP)
+ {
+ XPutImage (XtDisplay(mw), XtWindow(mw), mw->menu_pane.titleGC,
+ mw->menu_pane.titleImage, 0, 0,
+ mw->cascade.title_x, mw->cascade.top_title_y,
+ mw->cascade.title_width, mw->cascade.title_height);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.top_title_y +
+ mw->cascade.title_height +
+ PADDING_FOR_UNDERLINE + 1,
+ mw->core.width,
+ mw->cascade.top_title_y +
+ mw->cascade.title_height +
+ PADDING_FOR_UNDERLINE + 1);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.top_title_y +
+ mw->cascade.title_height +
+ PADDING_FOR_UNDERLINE + 3,
+ mw->core.width,
+ mw->cascade.top_title_y +
+ mw->cascade.title_height +
+ PADDING_FOR_UNDERLINE + 3);
+ }
+
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ {
+ XPutImage (XtDisplay(mw), XtWindow(mw), mw->menu_pane.titleGC,
+ mw->menu_pane.titleImage, 0, 0,
+ mw->cascade.title_x, mw->cascade.bottom_title_y,
+ mw->cascade.title_width, mw->cascade.title_height);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.bottom_title_y -
+ DOUBLE_LINES + 2,
+ mw->core.width,
+ mw->cascade.bottom_title_y -
+ DOUBLE_LINES + 2);
+
+ XDrawLine (XtDisplay(w), XtWindow(w), mw->menu_pane.titleGC, 0,
+ mw->cascade.bottom_title_y -
+ DOUBLE_LINES,
+ mw->core.width,
+ mw->cascade.bottom_title_y -
+ DOUBLE_LINES);
+ }
+ }
+ }
+
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetTitleAttributes
+ *
+ * Description:
+ * -----------
+ * This procedure calculates the height, width, and starting location
+ * for the title string/image. In addition, it uses
+ * this information to determine where the menu buttons should be laid
+ * out within the pane.
+ *
+ *
+ * Inputs:
+ * ------
+ * mw = The menu pane widget whose title attributes are being calculated.
+ *
+ * setCoreFields = A boolean flag, indicating whether the core height
+ * and width fields should be set to their default value.
+ * This flag should only be set to TRUE when this routine
+ * is invoked at initialization time; all other calls must
+ * set this to FALSE.
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetTitleAttributes (mw, setCoreFields)
+
+ XwCascadeWidget mw;
+ Boolean setCoreFields;
+
+{
+
+ if (mw->menu_pane.title_showing && !mw->menu_pane.title_override)
+ {
+ if (mw->menu_pane.title_type == XwSTRING)
+ {
+ /* Determine size of title string */
+ mw->cascade.title_width = XTextWidth (mw->menu_pane.title_font,
+ mw->menu_pane.title_string,
+ XwStrlen(mw->menu_pane.title_string));
+ mw->cascade.title_height = mw->menu_pane.title_font->ascent +
+ mw->menu_pane.title_font->descent;
+ mw->cascade.title_x = PADDING_TO_LEFT +
+ mw->manager.highlight_thickness;
+
+ /* Default size should contain just the title string */
+ if (setCoreFields)
+ {
+ mw->core.width = mw->cascade.title_width +
+ (mw->manager.highlight_thickness << 1) +
+ PADDING_TO_LEFT +
+ PADDING_TO_RIGHT;
+ mw->core.height = mw->manager.highlight_thickness << 1;
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->core.height += mw->cascade.title_height +
+ PADDING_FROM_ABOVE +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ mw->core.height += mw->cascade.title_height +
+ PADDING_FROM_BELOW +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->cascade.top_title_y = PADDING_FROM_ABOVE +
+ mw->manager.highlight_thickness +
+ mw->menu_pane.title_font->ascent;
+ else
+ mw->cascade.top_title_y = 0;
+
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ mw->cascade.bottom_title_y = mw->core.height -
+ mw->manager.highlight_thickness -
+ mw->menu_pane.title_font->descent -
+ PADDING_FROM_ABOVE -
+ PADDING_FOR_UNDERLINE;
+ else
+ mw->cascade.bottom_title_y = mw->core.height -
+ mw->manager.highlight_thickness;
+
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->cascade.button_starting_loc = mw->cascade.top_title_y +
+ mw->menu_pane.title_font->descent +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ else
+ mw->cascade.button_starting_loc = mw->manager.highlight_thickness;
+ }
+ else if (mw->menu_pane.titleImage)
+ {
+ /* Determine size of title image */
+ mw->cascade.title_width = mw->menu_pane.titleImage->width;
+ mw->cascade.title_height = mw->menu_pane.titleImage->height;
+ mw->cascade.title_x = PADDING_TO_LEFT +
+ mw->manager.highlight_thickness;
+
+ /* Default size should contain just the title image */
+ if (setCoreFields)
+ {
+ mw->core.width = mw->cascade.title_width +
+ (mw->manager.highlight_thickness << 1) +
+ PADDING_TO_LEFT +
+ PADDING_TO_RIGHT;
+ mw->core.height = (mw->manager.highlight_thickness << 1);;
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->core.height += mw->cascade.title_height +
+ PADDING_FROM_ABOVE +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ mw->core.height += mw->cascade.title_height +
+ PADDING_FROM_ABOVE +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ }
+
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->cascade.top_title_y = PADDING_FROM_ABOVE +
+ mw->manager.highlight_thickness;
+ else
+ mw->cascade.top_title_y = 0;
+ if (mw->cascade.titlePosition & XwBOTTOM)
+ mw->cascade.bottom_title_y = mw->core.height -
+ mw->manager.highlight_thickness -
+ mw->cascade.title_height -
+ PADDING_FROM_BELOW;
+ else
+ mw->cascade.bottom_title_y = mw->core.height -
+ mw->manager.highlight_thickness;
+
+ if (mw->cascade.titlePosition & XwTOP)
+ mw->cascade.button_starting_loc = mw->cascade.top_title_y +
+ mw->cascade.title_height +
+ PADDING_FOR_UNDERLINE +
+ DOUBLE_LINES;
+ else
+ mw->cascade.button_starting_loc = mw->manager.highlight_thickness;
+ }
+ else
+ {
+ /* No image is present */
+
+ if (setCoreFields)
+ {
+ mw->core.width = (mw->manager.highlight_thickness > 0) ?
+ (mw->manager.highlight_thickness << 1) : 2;
+ mw->core.height = mw->core.width;
+ }
+ mw->cascade.title_width = 0;
+ mw->cascade.title_height = 0;
+ mw->cascade.title_x = 0;
+ mw->cascade.top_title_y = 0;
+ mw->cascade.bottom_title_y = mw->core.height;
+ mw->cascade.button_starting_loc = mw->manager.highlight_thickness;
+ }
+ }
+ else
+ {
+ /* No image or string is present */
+
+ if (setCoreFields)
+ {
+ mw->core.width = (mw->manager.highlight_thickness > 0) ?
+ (mw->manager.highlight_thickness << 1) : 2;
+ mw->core.height = mw->core.width;
+ }
+ mw->cascade.title_width = 0;
+ mw->cascade.title_height = 0;
+ mw->cascade.title_x = 0;
+ mw->cascade.top_title_y = 0;
+ mw->cascade.bottom_title_y = mw->core.height;
+ mw->cascade.button_starting_loc = mw->manager.highlight_thickness;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * Visibility(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Visibility (widget, event)
+
+ Widget widget;
+ XEvent * event;
+
+{
+ /*
+ * Noop; purpose is to prevent Manager's translation from
+ * taking effect.
+ */
+}
+
+
+/*************************************<->*************************************
+ *
+ * Unmap(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Unmap (widget, event)
+
+ Widget widget;
+ XEvent * event;
+
+{
+ /*
+ * Noop; purpose is to prevent Manager's translation from
+ * taking effect.
+ */
+}
diff --git a/Xw/Cascade.h b/Xw/Cascade.h
new file mode 100644
index 0000000..6fe59de
--- /dev/null
+++ b/Xw/Cascade.h
@@ -0,0 +1,41 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Cascade.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for Cascading menupane class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Cascading MenuPane Widget (subclass of MenuPane)
+ *
+ ***********************************************************************/
+
+
+/* Class record constants */
+
+extern WidgetClass XwcascadeWidgetClass;
+
+typedef struct _XwCascadeClassRec *XwCascadeWidgetClass;
+typedef struct _XwCascadeRec *XwCascadeWidget;
+
diff --git a/Xw/CascadeP.h b/Xw/CascadeP.h
new file mode 100644
index 0000000..388a91b
--- /dev/null
+++ b/Xw/CascadeP.h
@@ -0,0 +1,85 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: CascadeP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for Cascading menupane class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Cascading MenuPane Widget Private Data
+ *
+ ***********************************************************************/
+
+/* New fields for the Cascade widget class record */
+typedef struct {
+ int mumble; /* No new procedures */
+} XwCascadeClassPart;
+
+/* Full class record declaration */
+typedef struct _XwCascadeClassRec {
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwMenuPaneClassPart menu_pane_class;
+ XwCascadeClassPart cascade_class;
+} XwCascadeClassRec;
+
+extern XwCascadeClassRec XwcascadeClassRec;
+
+/* New fields for the Cascade widget record */
+typedef struct {
+ /* Internal fields */
+ Position title_x;
+ Position top_title_y;
+ Position bottom_title_y;
+ Dimension title_height;
+ Dimension title_width;
+ Position button_starting_loc;
+ Dimension idealWidth;
+ Dimension idealHeight;
+ Dimension largestButtonWidth;
+ Widget georeqWidget;
+ Dimension georeqWidth;
+
+ /* User settable fields */
+ int titlePosition;
+} XwCascadePart;
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwCascadeRec {
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwMenuPanePart menu_pane;
+ XwCascadePart cascade;
+} XwCascadeRec;
+
diff --git a/Xw/Display.c b/Xw/Display.c
new file mode 100644
index 0000000..79c3860
--- /dev/null
+++ b/Xw/Display.c
@@ -0,0 +1,672 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Display.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code for TextEdit widget ascii sink
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+
+#include <Xw/TextEditP.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+
+#define GETLASTPOS (*(source->scan))(source, 0, XwstLast, XwsdRight, 1, TRUE)
+/* Private Ascii TextSink Definitions */
+
+static unsigned bufferSize = 200;
+
+typedef struct _AsciiSinkData {
+ Pixel foreground;
+ GC normgc, invgc, xorgc;
+ XFontStruct *font;
+ int tabwidth;
+ Pixmap insertCursorOn;
+ XwInsertState laststate;
+} AsciiSinkData, *AsciiSinkPtr;
+
+static unsigned char *buf;
+
+/* XXX foreground default should be XtDefaultFGPixel. How do i do that?? */
+
+static XtResource SinkResources[] = {
+ {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
+ XtOffset(AsciiSinkPtr, font), XtRString, "Fixed"},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof (int),
+ XtOffset(AsciiSinkPtr, foreground), XtRString, "XtDefaultForeground"},
+};
+
+/* Utilities */
+
+/*--------------------------------------------------------------------------+*/
+static int CharWidth (data, x, margin, c)
+/*--------------------------------------------------------------------------+*/
+ AsciiSinkData *data;
+ int x;
+ int margin ;
+ unsigned char c;
+{
+ int width, nonPrinting;
+ XFontStruct *font = data->font;
+
+ if (c == '\t')
+ /* This is totally bogus!! need to know tab settings etc.. */
+ return data->tabwidth - ((x-margin) % data->tabwidth);
+ if (c == LF)
+ c = SP;
+ nonPrinting = (c < SP);
+ if (nonPrinting) c += '@';
+
+ if (font->per_char &&
+ (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
+ width = font->per_char[c - font->min_char_or_byte2].width;
+ else
+ width = font->min_bounds.width;
+
+ if (nonPrinting)
+ width += CharWidth(data, x, margin, '^');
+
+ return width;
+}
+
+/* Sink Object Functions */
+
+#define LBEARING(x) \
+ ((font->per_char != NULL && \
+ ((x) >= font->min_char_or_byte2 && (x) <= font->max_char_or_byte2)) \
+ ? font->per_char[(x) - font->min_char_or_byte2].lbearing \
+ : font->min_bounds.lbearing)
+
+/*--------------------------------------------------------------------------+*/
+static int AsciiDisplayText (w, x, y, pos1, pos2, highlight)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ Position x, y;
+ int highlight;
+ XwTextPosition pos1, pos2;
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ XwTextSource *source = ((XwTextEditWidget)w)->text.source;
+ AsciiSinkData *data = (AsciiSinkData *) sink->data ;
+ int margin = ((XwTextEditWidget)w)->text.leftmargin ;
+
+ XFontStruct *font = data->font;
+ int j, k;
+ Dimension width;
+ XwTextBlock blk;
+ GC gc = highlight ? data->invgc : data->normgc;
+ GC invgc = highlight ? data->normgc : data->invgc;
+
+ y += font->ascent;
+ j = 0;
+ while (pos1 < pos2) {
+ pos1 = (*(source->read))(source, pos1, &blk, pos2 - pos1);
+ for (k = 0; k < blk.length; k++) {
+ if (j >= bufferSize - 5) {
+ bufferSize *= 2;
+ buf = (unsigned char *) XtRealloc(buf, bufferSize);
+ }
+ buf[j] = blk.ptr[k];
+ if (buf[j] == LF)
+ buf[j] = ' ';
+ else if (buf[j] == '\t') {
+ XDrawImageString(XtDisplay(w), XtWindow(w),
+ gc, x - LBEARING(*buf), y, buf, j);
+ buf[j] = 0;
+ x += XTextWidth(data->font, buf, j);
+ width = CharWidth(data, x, margin, '\t');
+ XFillRectangle(XtDisplay(w), XtWindow(w), invgc, x,
+ y - font->ascent, width,
+ (Dimension) (data->font->ascent +
+ data->font->descent));
+ x += width;
+ j = -1;
+ }
+ else
+ if (buf[j] < ' ') {
+ buf[j + 1] = buf[j] + '@';
+ buf[j] = '^';
+ j++;
+ }
+ j++;
+ }
+ }
+ XDrawImageString(XtDisplay(w), XtWindow(w), gc, x - LBEARING(*buf), y,
+ buf, j);
+}
+
+
+# define insertCursor_width 6
+# define insertCursor_height 3
+static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
+
+/*--------------------------------------------------------------------------+*/
+static Pixmap CreateInsertCursor(s)
+/*--------------------------------------------------------------------------+*/
+Screen *s;
+{
+
+ return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
+ insertCursor_bits, insertCursor_width, insertCursor_height));
+}
+
+/*
+ * The following procedure manages the "insert" cursor.
+ */
+
+/*--------------------------------------------------------------------------+*/
+static AsciiInsertCursor (w, x, y, state)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ Position x, y;
+ XwInsertState state;
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ AsciiSinkData *data = (AsciiSinkData *) sink->data;
+
+/*
+ XCopyArea(sink->dpy,
+ (state == XwisOn) ? data->insertCursorOn : data->insertCursorOff, w,
+ data->normgc, 0, 0, insertCursor_width, insertCursor_height,
+ x - (insertCursor_width >> 1), y - (insertCursor_height));
+
+ if (state != data->laststate && XtIsRealized(w))
+ XCopyPlane(XtDisplay(w),
+ data->insertCursorOn, XtWindow(w),
+ data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
+ x - (insertCursor_width >> 1), y - (insertCursor_height), 1);
+*/
+/* This change goes with the cursor hack for the broken server */
+ XCopyArea (XtDisplay(w), data->insertCursorOn, XtWindow (w),
+ data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
+ x - (insertCursor_width >> 1), y - (insertCursor_height));
+
+ data->laststate = state;
+}
+
+/*
+ * Clear the passed region to the background color.
+ */
+
+/*--------------------------------------------------------------------------+*/
+static AsciiClearToBackground (w, x, y, width, height)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ Position x, y;
+ Dimension width, height;
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ AsciiSinkData *data = (AsciiSinkData *) sink->data;
+ XFillRectangle(XtDisplay(w), XtWindow(w), data->invgc, x, y, width, height);
+}
+
+/*
+ * Given two positions, find the distance between them.
+ */
+
+/*--------------------------------------------------------------------------+*/
+static AsciiFindDistance (w, fromPos, fromx, toPos,
+ resWidth, resPos, resHeight)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XwTextPosition fromPos; /* First position. */
+ int fromx; /* Horizontal location of first position. */
+ XwTextPosition toPos; /* Second position. */
+ int *resWidth; /* Distance between fromPos and resPos. */
+ int *resPos; /* Actual second position used. */
+ int *resHeight; /* Height required. */
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ XwTextSource *source = ((XwTextEditWidget)w)->text.source;
+ int margin = ((XwTextEditWidget)w)->text.leftmargin ;
+
+ AsciiSinkData *data;
+ register XwTextPosition index, lastPos;
+ register unsigned char c;
+ XwTextBlock blk;
+
+ data = (AsciiSinkData *) sink->data;
+ /* we may not need this */
+ lastPos = GETLASTPOS;
+ (*(source->read))(source, fromPos, &blk, toPos - fromPos);
+ *resWidth = 0;
+ for (index = fromPos; index != toPos && index < lastPos; index++) {
+ if (index - blk.firstPos >= blk.length)
+ (*(source->read))(source, index, &blk, toPos - fromPos);
+ c = blk.ptr[index - blk.firstPos];
+ if (c == LF) {
+ *resWidth += CharWidth(data, fromx + *resWidth, margin, SP);
+ index++;
+ break;
+ }
+ *resWidth += CharWidth(data, fromx + *resWidth, margin, c);
+ }
+ *resPos = index;
+ *resHeight = data->font->ascent + data->font->descent;
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static TextFit AsciiTextFit (w, fromPos, fromx, width, wrap, wrapWhiteSpace,
+ fitPos, drawPos, nextPos, resWidth, resHeight)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XwTextPosition fromPos; /* Starting position. */
+ int fromx; /* Horizontal location of starting position. */
+ int width; /* Desired width. */
+ int wrap; /* Whether line should wrap at all */
+ int wrapWhiteSpace; /* Whether line should wrap at white space */
+
+ XwTextPosition *fitPos ; /* pos of last char which fits in specified
+ width */
+ XwTextPosition *drawPos ; /* pos of last char to draw in specified
+ width based on wrap model */
+ XwTextPosition *nextPos ; /* pos of next char to draw outside specified
+ width based on wrap model */
+ int *resWidth; /* Actual width used. */
+ int *resHeight; /* Height required. */
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ XwTextSource *source = ((XwTextEditWidget)w)->text.source;
+ int margin = ((XwTextEditWidget)w)->text.leftmargin ;
+ AsciiSinkData *data;
+ XwTextPosition lastPos, pos, whiteSpacePosition;
+ XwTextPosition fitL, drawL ;
+ /* local equivalents of fitPos, drawPos, nextPos */
+ int lastWidth, whiteSpaceWidth, whiteSpaceSeen ;
+ int useAll ;
+ TextFit fit ;
+ unsigned char c;
+ XwTextBlock blk;
+
+ data = (AsciiSinkData *) sink->data;
+ lastPos = GETLASTPOS;
+
+ *resWidth = 0;
+ *fitPos = fromPos ;
+ *drawPos = -1 ;
+ c = 0;
+ useAll = whiteSpaceSeen = FALSE ;
+
+ pos = fromPos ;
+ fitL = pos - 1 ;
+ (*(source->read))(source, fromPos, &blk, bufferSize);
+
+ while (*resWidth <= width)
+ { lastWidth = *resWidth;
+ fitL = pos - 1 ;
+ if (pos >= lastPos)
+ { pos = lastPos ;
+ fit = tfEndText ;
+ useAll = TRUE ;
+ break ;
+ } ;
+ if (pos - blk.firstPos >= blk.length)
+ (*(source->read))(source, pos, &blk, bufferSize);
+ c = blk.ptr[pos - blk.firstPos];
+
+ if (isNewline(c))
+ { fit = tfNewline ;
+ useAll = TRUE ;
+ break ;
+ }
+
+ if (wrapWhiteSpace && isWhiteSpace(c))
+ { whiteSpaceSeen = TRUE ;
+ drawL = pos - 1 ;
+ whiteSpaceWidth = *resWidth;
+ } ;
+
+ *resWidth += CharWidth(data, fromx + *resWidth, margin, c);
+ pos++ ;
+ } /* end while */
+
+ *fitPos = fitL ;
+ *drawPos = fitL ;
+ if (useAll)
+ {
+ *nextPos = pos + 1 ;
+ *resWidth = lastWidth ;
+ }
+ else if (wrapWhiteSpace && whiteSpaceSeen)
+ { *drawPos = drawL ;
+ *nextPos = drawL + 2 ;
+ *resWidth = whiteSpaceWidth ;
+ fit = tfWrapWhiteSpace ;
+ }
+ else if (wrap)
+ {
+ *nextPos = fitL + 1 ;
+ *resWidth = lastWidth ;
+ fit = tfWrapAny ;
+ }
+ else
+ {
+ /* scan source for newline or end */
+ *nextPos =
+ (*(source->scan)) (source, pos, XwstEOL, XwsdRight, 1, TRUE) + 1 ;
+ *resWidth = lastWidth ;
+ fit = tfNoFit ;
+ }
+ *resHeight = data->font->ascent + data->font->descent;
+ return (fit) ;
+}
+
+/*--------------------------------------------------------------------------+*/
+static AsciiFindPosition(w, fromPos, fromx, width, stopAtWordBreak,
+ resPos, resWidth, resHeight)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XwTextPosition fromPos; /* Starting position. */
+ int fromx; /* Horizontal location of starting position. */
+ int width; /* Desired width. */
+ int stopAtWordBreak; /* Whether the resulting position should be at
+ a word break. */
+ XwTextPosition *resPos; /* Resulting position. */
+ int *resWidth; /* Actual width used. */
+ int *resHeight; /* Height required. */
+{
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ XwTextSource *source = ((XwTextEditWidget)w)->text.source;
+ int margin = ((XwTextEditWidget)w)->text.leftmargin ;
+ AsciiSinkData *data;
+ XwTextPosition lastPos, index, whiteSpacePosition;
+ int lastWidth, whiteSpaceWidth;
+ Boolean whiteSpaceSeen;
+ unsigned char c;
+ XwTextBlock blk;
+ data = (AsciiSinkData *) sink->data;
+ lastPos = GETLASTPOS;
+
+ (*(source->read))(source, fromPos, &blk, bufferSize);
+ *resWidth = 0;
+ whiteSpaceSeen = FALSE;
+ c = 0;
+ for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
+ lastWidth = *resWidth;
+ if (index - blk.firstPos >= blk.length)
+ (*(source->read))(source, index, &blk, bufferSize);
+ c = blk.ptr[index - blk.firstPos];
+ if (c == LF) {
+ *resWidth += CharWidth(data, fromx + *resWidth, margin, SP);
+ index++;
+ break;
+ }
+ *resWidth += CharWidth(data, fromx + *resWidth, margin, c);
+ if ((c == SP || c == TAB) && *resWidth <= width) {
+ whiteSpaceSeen = TRUE;
+ whiteSpacePosition = index;
+ whiteSpaceWidth = *resWidth;
+ }
+ }
+ if (*resWidth > width && index > fromPos) {
+ *resWidth = lastWidth;
+ index--;
+ if (stopAtWordBreak && whiteSpaceSeen) {
+ index = whiteSpacePosition + 1;
+ *resWidth = whiteSpaceWidth;
+ }
+ }
+ if (index == lastPos && c != LF) index = lastPos + 1;
+ *resPos = index;
+ *resHeight = data->font->ascent + data->font->descent;
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static int AsciiResolveToPosition (w, pos, fromx, width,
+ leftPos, rightPos)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XwTextPosition pos;
+ int fromx,width;
+ XwTextPosition *leftPos, *rightPos;
+{
+ int resWidth, resHeight;
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+ XwTextSource *source = ((XwTextEditWidget)w)->text.source;
+
+ AsciiFindPosition(w, pos, fromx, width, FALSE,
+ leftPos, &resWidth, &resHeight);
+ if (*leftPos > GETLASTPOS)
+ *leftPos = GETLASTPOS;
+ *rightPos = *leftPos;
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static int AsciiMaxLinesForHeight (w)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+{
+ AsciiSinkData *data;
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+
+ data = (AsciiSinkData *) sink->data;
+ return (int) ((w->core.height
+ - ((XwTextEditWidget) w)->text.topmargin
+ - ((XwTextEditWidget) w)->text.bottommargin
+ )
+ / (data->font->ascent + data->font->descent)
+ );
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static int AsciiMaxHeightForLines (w, lines)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ int lines;
+{
+ AsciiSinkData *data;
+ XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
+
+ data = (AsciiSinkData *) sink->data;
+ return(lines * (data->font->ascent + data->font->descent));
+}
+
+
+/***** Public routines *****/
+
+static Boolean initialized = FALSE;
+static XContext asciiSinkContext;
+
+/*--------------------------------------------------------------------------+*/
+AsciiSinkInitialize()
+/*--------------------------------------------------------------------------+*/
+{
+ if (initialized)
+ return;
+ initialized = TRUE;
+
+ asciiSinkContext = XUniqueContext();
+
+ buf = (unsigned char *) XtMalloc(bufferSize);
+}
+
+/*--------------------------------------------------------------------------+*/
+static Boolean XwAsciiSinkCheckData(self)
+/*--------------------------------------------------------------------------+*/
+ XwTextSink *self ;
+{
+ XwTextEditWidget tew = self->parent ;
+
+ /* make sure margins are big enough to keep traversal highlight
+ from obscuring text or cursor.
+ */
+ { int minBorder ;
+ minBorder = (tew->primitive.traversal_type == XwHIGHLIGHT_OFF)
+ ? RequiredCursorMargin
+ : RequiredCursorMargin + tew->primitive.highlight_thickness ;
+
+ if (tew->text.topmargin < minBorder)
+ tew->text.topmargin = minBorder ;
+ if (tew->text.bottommargin < minBorder)
+ tew->text.bottommargin = minBorder ;
+ if (tew->text.rightmargin < minBorder)
+ tew->text.rightmargin = minBorder ;
+ if (tew->text.leftmargin < minBorder)
+ tew->text.leftmargin = minBorder ;
+ }
+
+ if ((*(self->maxLines))(tew) < 1)
+ XtWarning("TextEdit window too small to display a single line of text.");
+
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwAsciiSinkDestroy (sink)
+/*--------------------------------------------------------------------------+*/
+ XwTextSink *sink;
+{
+ AsciiSinkData *data;
+ data = (AsciiSinkData *) sink->data;
+ XtFree((char *) data);
+ XtFree((char *) sink);
+}
+
+/*--------------------------------------------------------------------------+*/
+XwTextSink *XwAsciiSinkCreate (w, args, num_args)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ ArgList args;
+ Cardinal num_args;
+{
+ XwTextSink *sink;
+ AsciiSinkData *data;
+ unsigned long valuemask = (GCFont | GCGraphicsExposures |
+ GCForeground | GCBackground | GCFunction);
+ XGCValues values;
+ unsigned long wid;
+ XFontStruct *font;
+
+ if (!initialized)
+ AsciiSinkInitialize();
+
+ sink = XtNew(XwTextSink);
+ sink->parent = (XwTextEditWidget) w ;
+ sink->parent->text.sink = sink ; /* disgusting */
+ sink->display = AsciiDisplayText;
+ sink->insertCursor = AsciiInsertCursor;
+ sink->clearToBackground = AsciiClearToBackground;
+ sink->findPosition = AsciiFindPosition;
+ sink->textFitFn = AsciiTextFit;
+ sink->findDistance = AsciiFindDistance;
+ sink->resolve = AsciiResolveToPosition;
+ sink->maxLines = AsciiMaxLinesForHeight;
+ sink->maxHeight = AsciiMaxHeightForLines;
+ sink->resources = SinkResources;
+ sink->resource_num = XtNumber(SinkResources);
+ sink->check_data = XwAsciiSinkCheckData;
+ sink->destroy = XwAsciiSinkDestroy;
+ sink->LineLastWidth = 0 ;
+ sink->LineLastPosition = 0 ;
+ data = XtNew(AsciiSinkData);
+ sink->data = (int *)data;
+
+ XtGetSubresources (w, (caddr_t)data, "display", "Display",
+ SinkResources, XtNumber(SinkResources),
+ args, num_args);
+
+/* XXX do i have to XLoadQueryFont or does the resource guy do it for me */
+
+ font = data->font;
+ values.function = GXcopy;
+ values.font = font->fid;
+ values.graphics_exposures = (Bool) FALSE;
+ values.foreground = data->foreground;
+ values.background = w->core.background_pixel;
+ data->normgc = XtGetGC(w, valuemask, &values);
+ values.foreground = w->core.background_pixel;
+ values.background = data->foreground;
+ data->invgc = XtGetGC(w, valuemask, &values);
+ values.function = GXxor;
+ values.foreground = data->foreground ^ w->core.background_pixel;
+ values.background = 0;
+ data->xorgc = XtGetGC(w, valuemask, &values);
+
+ wid = -1;
+ if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &wid)) || wid <= 0) {
+ if (font->per_char && font->min_char_or_byte2 <= '0' &&
+ font->max_char_or_byte2 >= '0')
+ wid = font->per_char['0' - font->min_char_or_byte2].width;
+ else
+ wid = font->max_bounds.width;
+ }
+ if (wid <= 0) wid = 1;
+ data->tabwidth = 8 * wid;
+ data->font = font;
+
+/* data->insertCursorOn = CreateInsertCursor(XtScreen(w)); */
+
+ {/* Correction from AsciiSink.c on R2 tape */
+ Screen *screen = XtScreen(w);
+ Display *dpy = XtDisplay(w);
+ Window root = RootWindowOfScreen(screen);
+ Pixmap bitmap = XCreateBitmapFromData(dpy, root, insertCursor_bits,
+ insertCursor_width,
+ insertCursor_height);
+ Pixmap pixmap = XCreatePixmap(dpy, root,insertCursor_width,
+ insertCursor_height,
+ DefaultDepthOfScreen(screen));
+ XGCValues gcv;
+ GC gc;
+
+ gcv.function = GXcopy;
+ gcv.foreground = data->foreground ^ w->core.background_pixel;
+ gcv.background = 0;
+ gcv.graphics_exposures = False;
+ gc = XtGetGC(w, (GCFunction | GCForeground | GCBackground |
+ GCGraphicsExposures), &gcv);
+ XCopyPlane(dpy, bitmap, pixmap, gc, 0, 0, insertCursor_width,
+ insertCursor_height, 0, 0, 1);
+ XtDestroyGC(gc);
+ data->insertCursorOn = pixmap;
+ }
+
+ data->laststate = XwisOff;
+ (*(sink->check_data))(sink);
+
+ return sink;
+}
+
diff --git a/Xw/DisplayP.h b/Xw/DisplayP.h
new file mode 100644
index 0000000..205e87a
--- /dev/null
+++ b/Xw/DisplayP.h
@@ -0,0 +1,94 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: DisplayP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for TextEdit widget ascii sink
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#ifndef _XwTextEditDisplayPrivate_h
+#define _XwTextEditDisplayPrivate_h
+
+/*****************************************************************************
+*
+* Constants
+*
+*****************************************************************************/
+
+#define INFINITE_WIDTH 32767
+
+#define applyDisplay(method) (*(self->text.sink->method))
+
+/*****************************************************************************
+*
+* Displayable text management data structures (LineTable)
+*
+*****************************************************************************/
+
+#define RequiredCursorMargin 3
+
+typedef struct {
+ XwTextPosition position, drawPos;
+ Position x, y, endX;
+ TextFit fit ;
+ } XwLineTableEntry, *XwLineTableEntryPtr;
+
+/* Line Tables are n+1 long - last position displayed is in last lt entry */
+typedef struct {
+ XwTextPosition top; /* Top of the displayed text. */
+ XwTextPosition lines; /* How many lines in this table. */
+ XwLineTableEntry *info; /* A dynamic array, one entry per line */
+ } XwLineTable, *XwLineTablePtr;
+
+typedef enum {XwisOn, XwisOff} XwInsertState;
+
+typedef enum {XwselectNull, XwselectPosition, XwselectChar, XwselectWord,
+ XwselectLine, XwselectParagraph, XwselectAll} XwSelectType;
+
+typedef enum {XwsmTextSelect, XwsmTextExtend} XwSelectionMode;
+
+typedef enum {XwactionStart, XwactionAdjust, XwactionEnd} XwSelectionAction;
+
+typedef struct {
+ XwTextPosition left, right;
+ XwSelectType type;
+} XwTextSelection;
+
+#define IsPositionVisible(ctx, pos)\
+ (pos >= ctx->text.lt.info[0].position && \
+ pos <= ctx->text.lt.info[ctx->text.lt.lines].position)
+
+
+#endif
+/* DON'T ADD STUFF AFTER THIS #endif */
+
+
diff --git a/Xw/Form.c b/Xw/Form.c
new file mode 100644
index 0000000..ffe09db
--- /dev/null
+++ b/Xw/Form.c
@@ -0,0 +1,1902 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Form.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains code for the X Widget's Form manager.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/Xlib.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/Form.h>
+#include <Xw/FormP.h>
+#include <X11/StringDefs.h>
+#include <X11/keysymdef.h>
+
+
+/* Constraint resource list for Form */
+
+static XtResource constraintResources[] =
+{
+ {
+ XtNxRefName, XtCXRefName, XtRString, sizeof(caddr_t),
+ XtOffset(XwFormConstraints, x_ref_name), XtRString, (caddr_t) NULL
+ },
+
+ {
+ XtNxRefWidget, XtCXRefWidget, XtRPointer, sizeof(caddr_t),
+ XtOffset(XwFormConstraints, x_ref_widget), XtRPointer, NULL
+ },
+
+ {
+ XtNxOffset, XtCXOffset, XtRInt, sizeof(int),
+ XtOffset(XwFormConstraints, x_offset), XtRString, "0"
+ },
+
+ {
+ XtNxAddWidth, XtCXAddWidth, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, x_add_width), XtRString, "False"
+ },
+
+ {
+ XtNxVaryOffset, XtCXVaryOffset, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, x_vary_offset), XtRString, "False"
+ },
+
+ {
+ XtNxResizable, XtCXResizable, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, x_resizable), XtRString, "False"
+ },
+
+ {
+ XtNxAttachRight, XtCXAttachRight, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, x_attach_right), XtRString, "False"
+ },
+
+ {
+ XtNxAttachOffset, XtCXAttachOffset, XtRInt, sizeof(int),
+ XtOffset(XwFormConstraints, x_attach_offset), XtRString, "0"
+ },
+
+ {
+ XtNyRefName, XtCYRefName, XtRString, sizeof(caddr_t),
+ XtOffset(XwFormConstraints, y_ref_name), XtRString, (caddr_t) NULL
+ },
+
+ {
+ XtNyRefWidget, XtCYRefWidget, XtRPointer, sizeof(caddr_t),
+ XtOffset(XwFormConstraints, y_ref_widget), XtRPointer, NULL
+ },
+
+ {
+ XtNyOffset, XtCYOffset, XtRInt, sizeof(int),
+ XtOffset(XwFormConstraints, y_offset), XtRString, "0"
+ },
+
+ {
+ XtNyAddHeight, XtCYAddHeight, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, y_add_height), XtRString, "False"
+ },
+
+ {
+ XtNyVaryOffset, XtCYVaryOffset, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, y_vary_offset), XtRString, "False"
+ },
+
+ {
+ XtNyResizable, XtCYResizable, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, y_resizable), XtRString, "False"
+ },
+
+ {
+ XtNyAttachBottom, XtCYAttachBottom, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwFormConstraints, y_attach_bottom), XtRString, "False"
+ },
+
+ {
+ XtNyAttachOffset, XtCYAttachOffset, XtRInt, sizeof(int),
+ XtOffset(XwFormConstraints, y_attach_offset), XtRString, "0"
+ }
+};
+
+
+
+/* Static routine definitions */
+
+static void Initialize();
+static void Realize();
+static void Resize();
+static void Destroy();
+static Boolean SetValues();
+
+static void ChangeManaged();
+static XtGeometryResult GeometryManager();
+
+static void ConstraintInitialize();
+static void ConstraintDestroy();
+static Boolean ConstraintSetValues();
+
+static void GetRefWidget();
+static Widget XwFindWidget();
+static XwFormRef * XwGetFormRef();
+static Widget XwFindValidRef();
+static XwFormRef * XwRefTreeSearch();
+static XwFormRef * XwParentRefTreeSearch();
+static void XwMakeRefs();
+static void XwDestroyRefs();
+static void XwProcessRefs();
+static void XwAddRef();
+static void XwRemoveRef();
+static void XwFindDepthAndCount();
+static void XwInitProcessList();
+static void XwConstrainList();
+static void XwFreeConstraintList();
+
+
+/* Static global variable definitions */
+
+static int depth, leaves, arrayIndex;
+
+
+/* The Form class record */
+
+XwFormClassRec XwformClassRec =
+{
+ {
+ (WidgetClass) &XwmanagerClassRec, /* superclass */
+ "XwForm", /* class_name */
+ sizeof(XwFormRec), /* widget_size */
+ NULL, /* class_initialize */
+ NULL, /* class_part_initialize */
+ FALSE, /* class_inited */
+ (XtInitProc) Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ (XtRealizeProc) Realize, /* realize */
+ NULL, /* actions */
+ 0, /* num_actions */
+ NULL, /* resources */
+ 0, /* num_resources */
+ NULLQUARK, /* xrm_class */
+ TRUE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ (XtWidgetProc) Destroy, /* destroy */
+ (XtWidgetProc) Resize, /* resize */
+ NULL, /* expose */
+ (XtSetValuesFunc) SetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback private */
+ NULL, /* tm_table */
+ NULL, /* query_geometry */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+
+ { /* composite class */
+ (XtGeometryHandler) GeometryManager, /* geometry_manager */
+ (XtWidgetProc) ChangeManaged, /* change_managed */
+ XtInheritInsertChild, /* insert_child */
+ XtInheritDeleteChild, /* delete_child (inherited) */
+ NULL,
+ },
+
+ { /* constraint class */
+ constraintResources, /* constraint resource set */
+ XtNumber(constraintResources), /* num_resources */
+ sizeof(XwFormConstraintRec), /* size of the constraint data */
+ (XtInitProc) ConstraintInitialize, /* contraint initilize proc */
+ (XtWidgetProc) ConstraintDestroy, /* contraint destroy proc */
+ (XtSetValuesFunc) ConstraintSetValues, /* contraint set values proc */
+ NULL,
+ },
+
+ { /* manager class */
+ (XwTraversalProc) XtInheritTraversalProc /* traversal handler */
+ },
+
+ { /* form class */
+ 0 /* mumble */
+ }
+};
+
+
+WidgetClass XwformWidgetClass = (WidgetClass) &XwformClassRec;
+
+
+
+
+/************************************************************************
+ *
+ * Initialize
+ * The main widget instance initialization routine.
+ *
+ ************************************************************************/
+
+static void Initialize (request, new)
+XwFormWidget request, new;
+
+{
+ /* Initialize the tree fields to NULL */
+
+ new -> form.width_tree =
+ XwGetFormRef (new, NULL, 0, False, False, True, False, 0, 0, 0);
+ new -> form.height_tree =
+ XwGetFormRef (new, NULL, 0, False, False, True, False, 0, 0, 0);
+
+
+ /* Set up a geometry for the widget if it is currently 0. */
+
+ if (request -> core.width == 0)
+ new -> core.width += 200;
+ if (request -> core.height == 0)
+ new -> core.height += 200;
+}
+
+
+
+
+/************************************************************************
+ *
+ * ConstraintInitialize
+ * The main widget instance constraint initialization routine.
+ *
+ ************************************************************************/
+
+static void ConstraintInitialize (request, new)
+Widget request, new;
+
+{
+ XwFormConstraintRec * constraintRec;
+
+ constraintRec = (XwFormConstraintRec *) new -> core.constraints;
+
+
+ /* Initialize the contraint widget sizes for later processing */
+
+ constraintRec -> set_x = 0;
+ constraintRec -> set_y = 0;
+ constraintRec -> set_width = 0;
+ constraintRec -> set_height = 0;
+
+ constraintRec -> x = new -> core.x;
+ constraintRec -> y = new -> core.y;
+ constraintRec -> width = new -> core.width;
+ constraintRec -> height = new -> core.height;
+
+ constraintRec -> managed = False;
+
+
+ /* Get and save copies of the names of the reference widgets */
+
+ GetRefWidget (&constraintRec -> x_ref_widget,
+ &constraintRec -> x_ref_name, new);
+ GetRefWidget (&constraintRec -> y_ref_widget,
+ &constraintRec -> y_ref_name, new);
+
+}
+
+
+
+
+/************************************************************************
+ *
+ * GetRefWidget
+ * Get and verify the reference widget given.
+ *
+ ************************************************************************/
+
+static void GetRefWidget (widget, name, new)
+Widget * widget;
+char ** name;
+Widget new;
+
+{
+ if (*widget != NULL)
+ {
+ if (*name != NULL)
+ {
+ if (strcmp (*name, (char *) ((*widget) -> core.name)) != 0)
+ {
+ XtWarning
+ ("Form: The reference widget and widget name do not match.");
+ *name = (char *) (*widget) -> core.name;
+ }
+ }
+ else
+ *name = (char *) (*widget) -> core.name;
+
+ if ((*widget) != new -> core.parent &&
+ (*widget) -> core.parent != new -> core.parent)
+ {
+ XtWarning ("Form: The reference widget is not a child of the form");
+ XtWarning (" or the form widget.");
+ *name = new -> core.parent -> core.name;
+ *widget = new -> core.parent;
+ }
+ }
+
+ else if (*name != NULL)
+ {
+ if ((*widget = XwFindWidget ((CompositeWidget)(new->core.parent), *name)) == NULL)
+ {
+ XtWarning ("Form: The reference widget was not found.");
+ *name = new -> core.parent -> core.name;
+ *widget = new -> core.parent;
+ }
+ }
+ else
+ {
+ *name = new -> core.parent -> core.name;
+ *widget = new -> core.parent;
+ }
+
+ *name = strcpy (XtMalloc((unsigned) XwStrlen (*name) + 1), *name);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwFindWidget
+ *
+ ************************************************************************/
+
+static Widget XwFindWidget (w, name)
+CompositeWidget w;
+char * name;
+
+{
+ register int i;
+ register Widget * list;
+ int count;
+
+ if (strcmp (name, w -> core.name) == 0)
+ return ((Widget) w);
+
+ list = w -> composite.children;
+ count = w -> composite.num_children;
+
+ for (i = 0; i < count; i++)
+ {
+ if (strcmp (name, (*list) -> core.name) == 0)
+ return (*list);
+ list++;
+ }
+ return (NULL);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Realize
+ * Create the widget window and create the gc's.
+ *
+ ************************************************************************/
+
+static void Realize (fw, valueMask, attributes)
+XwFormWidget fw;
+XtValueMask * valueMask;
+XSetWindowAttributes * attributes;
+
+{
+ Mask newValueMask = *valueMask;
+ XtCreateWindow ((Widget)fw, InputOutput, (Visual *) CopyFromParent,
+ newValueMask, attributes);
+ _XwRegisterName(fw);
+ XwProcessRefs (fw, False);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Resize
+ *
+ ************************************************************************/
+
+static void Resize (fw)
+XwFormWidget fw;
+
+{
+ if (XtIsRealized ((Widget)fw)) XwProcessRefs (fw, False);
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * Destroy
+ * Deallocate the head structures of the reference trees.
+ * The rest of the tree has already been deallocated.
+ *
+ ************************************************************************/
+
+static void Destroy (fw)
+XwFormWidget fw;
+
+{
+ XtFree ((char *)(fw -> form.width_tree));
+ XtFree ((char *)(fw -> form.height_tree));
+}
+
+
+
+
+/************************************************************************
+ *
+ * ConstraintDestroy
+ * Deallocate the allocated referenence names.
+ *
+ ************************************************************************/
+
+static void ConstraintDestroy (w)
+XwFormWidget w;
+
+{
+ XwFormConstraintRec * constraint;
+
+ constraint = (XwFormConstraintRec *) w -> core.constraints;
+
+ if (constraint -> x_ref_name != NULL) XtFree (constraint -> x_ref_name);
+ if (constraint -> y_ref_name != NULL) XtFree (constraint -> y_ref_name);
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * SetValues
+ * Currently nothing needs to be done. The XtSetValues call
+ * handles geometry requests and form does not define any
+ * new resources.
+ *
+ ************************************************************************/
+
+static Boolean SetValues (current, request, new)
+XwFormWidget current, request, new;
+
+{
+ return (False);
+}
+
+
+
+
+/************************************************************************
+ *
+ * ConstraintSetValues
+ * Process changes in the constraint set of a widget.
+ *
+ ************************************************************************/
+
+static Boolean ConstraintSetValues (current, request, new)
+Widget current, request, new;
+
+{
+ XwFormConstraintRec * curConstraint;
+ XwFormConstraintRec * newConstraint;
+ XwFormConstraintRec * tempConstraint;
+
+
+ curConstraint = (XwFormConstraintRec *) current -> core.constraints;
+ newConstraint = (XwFormConstraintRec *) new -> core.constraints;
+
+
+ /* Check the geometrys to see if new's contraint record */
+ /* saved geometry data needs to be updated. */
+
+ if (XtIsRealized (current))
+ {
+ if (new -> core.x != current -> core.x)
+ newConstraint -> set_x = new -> core.x;
+ if (new -> core.y != current -> core.y)
+ newConstraint -> set_y = new -> core.y;
+ if (new -> core.width != current -> core.width)
+ newConstraint -> set_width = new -> core.width;
+ if (new -> core.height != current -> core.height)
+ newConstraint -> set_height = new -> core.height;
+ }
+
+
+ /* If the reference widget or name has changed, set the */
+ /* opposing member to NULL in order to get the proper */
+ /* referencing. For names, the string space will be */
+ /* deallocated out of current later. */
+
+ if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget)
+ newConstraint -> x_ref_name = NULL;
+ else if (newConstraint -> x_ref_name != curConstraint -> x_ref_name)
+ newConstraint -> x_ref_widget = NULL;
+
+ if (newConstraint -> y_ref_widget != curConstraint -> y_ref_widget)
+ newConstraint -> y_ref_name = NULL;
+ else if (newConstraint -> y_ref_name != curConstraint -> y_ref_name)
+ newConstraint -> y_ref_widget = NULL;
+
+
+ /* Get and save copies of the names of the reference widget names */
+ /* and get the reference widgets. */
+
+ GetRefWidget (&newConstraint -> x_ref_widget,
+ &newConstraint -> x_ref_name, new);
+ GetRefWidget (&newConstraint -> y_ref_widget,
+ &newConstraint -> y_ref_name, new);
+
+
+ /* See if the reference widgets have changed. If so, free the */
+ /* old allocated names and set them to the new names. */
+
+ if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget)
+ {
+ XtFree (curConstraint -> x_ref_name);
+ curConstraint -> x_ref_name = newConstraint -> x_ref_name;
+ }
+
+ if (newConstraint -> y_ref_widget != curConstraint -> y_ref_widget)
+ {
+ XtFree (curConstraint -> y_ref_name);
+ curConstraint -> y_ref_name = newConstraint -> y_ref_name;
+ }
+
+
+ /* See if any constraint data for the widget has changed. */
+ /* Is so, remove the old reference tree elements from the */
+ /* forms constraint processing trees and build and insert */
+ /* new reference tree elements. */
+ /* */
+ /* Once this is finished, reprocess the constraint trees. */
+
+ if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget ||
+ newConstraint -> y_ref_widget != curConstraint -> y_ref_widget ||
+
+ newConstraint -> x_offset != curConstraint -> x_offset ||
+ newConstraint -> y_offset != curConstraint -> y_offset ||
+
+ newConstraint -> x_vary_offset != curConstraint -> x_vary_offset ||
+ newConstraint -> y_vary_offset != curConstraint -> y_vary_offset ||
+
+ newConstraint -> x_resizable != curConstraint -> x_resizable ||
+ newConstraint -> y_resizable != curConstraint -> y_resizable ||
+
+ newConstraint -> x_add_width != curConstraint -> x_add_width ||
+ newConstraint -> y_add_height != curConstraint -> y_add_height ||
+
+ newConstraint -> x_attach_right != curConstraint -> x_attach_right ||
+ newConstraint -> y_attach_bottom != curConstraint -> y_attach_bottom ||
+
+ newConstraint -> x_attach_offset != curConstraint -> x_attach_offset ||
+ newConstraint -> y_attach_offset != curConstraint -> y_attach_offset)
+ {
+ if (XtIsRealized (current) && current -> core.managed)
+ {
+ XwDestroyRefs (current);
+
+ tempConstraint = (XwFormConstraintRec *) current -> core.constraints;
+ current -> core.constraints = new -> core.constraints;
+ XwMakeRefs (current);
+ current -> core.constraints = (caddr_t) tempConstraint;
+ }
+
+ if (XtIsRealized (current)) XwProcessRefs (new -> core.parent, True);
+ }
+
+ return (False);
+}
+
+
+
+
+/************************************************************************
+ *
+ * GeometryManager
+ * Always accept the childs new size, set the childs constraint
+ * record size to the new size and process the constraints.
+ *
+ ************************************************************************/
+
+static XtGeometryResult GeometryManager (w, request, reply)
+Widget w;
+XtWidgetGeometry * request;
+XtWidgetGeometry * reply;
+
+{
+ XwFormWidget fw = (XwFormWidget) w -> core.parent;
+ XwFormConstraintRec * constraint;
+ XwFormRef * xRef;
+ XwFormRef * yRef;
+ int newBorder = w -> core.border_width;
+ Boolean moveFlag = False;
+ Boolean resizeFlag = False;
+
+
+ constraint = (XwFormConstraintRec *) w -> core.constraints;
+
+ if (request -> request_mode & CWX)
+ constraint -> set_x = request -> x;
+
+ if (request -> request_mode & CWY)
+ constraint -> set_y = request -> y;
+
+ if (request -> request_mode & CWWidth)
+ constraint -> set_width = request -> width;
+
+ if (request -> request_mode & CWHeight)
+ constraint -> set_height = request -> height;
+
+ if (request -> request_mode & CWBorderWidth)
+ newBorder = request -> border_width;
+
+
+ /* If the x or the width has changed, find the horizontal */
+ /* reference tree structure for this widget and update it */
+
+ xRef = yRef = NULL;
+ if ((request->request_mode & CWWidth) || (request->request_mode & CWX))
+ {
+ if ((xRef = XwRefTreeSearch (w, fw -> form.width_tree)) != NULL)
+ {
+ if (request->request_mode & CWX)
+ xRef -> set_loc = request -> x;
+ if (request->request_mode & CWWidth)
+ xRef -> set_size = request -> width;
+ }
+ }
+
+
+ /* If the y or the height has changed, find the vertical */
+ /* reference tree structure for this widget and update it */
+
+ if ((request->request_mode & CWHeight) || (request->request_mode & CWY))
+ {
+ if ((yRef = XwRefTreeSearch (w, fw -> form.height_tree)) != NULL)
+ {
+ if (request->request_mode & CWY)
+ yRef -> set_loc = request -> y;
+ if (request->request_mode & CWHeight)
+ yRef -> set_size = request -> height;
+ }
+ }
+
+
+ /* Process the constraints if either of the ref structs have changed */
+
+ if (xRef != NULL || yRef != NULL)
+ {
+ if ((request->request_mode & CWX) || (request->request_mode & CWY))
+ moveFlag = True;
+ if ((request->request_mode & CWWidth) ||
+ (request->request_mode & CWHeight))
+ resizeFlag = True;
+
+ if (moveFlag && resizeFlag)
+ XtConfigureWidget (w, constraint -> set_x, constraint -> set_y,
+ constraint -> set_width, constraint -> set_height,
+ newBorder);
+ else if (resizeFlag)
+ XtResizeWidget (w, constraint -> set_width, constraint -> set_height,
+ newBorder);
+ else if (moveFlag)
+ XtMoveWidget (w, constraint -> set_x, constraint -> set_y);
+
+
+ XwProcessRefs (w -> core.parent, True);
+ }
+
+
+ /* See if an almost condition should be returned */
+
+ if (((request->request_mode & CWX) && w->core.x != request->x) ||
+ ((request->request_mode & CWY) && w->core.y != request->y) ||
+ ((request->request_mode & CWWidth) &&
+ w->core.width != request->width) ||
+ ((request->request_mode & CWHeight) &&
+ w->core.height != request->height))
+ {
+ reply->request_mode = request->request_mode;
+
+ if (request->request_mode & CWX) reply->x = w->core.x;
+ if (request->request_mode & CWY) reply->y = w->core.y;
+ if (request->request_mode & CWWidth) reply->width = w->core.width;
+ if (request->request_mode & CWHeight) reply->height = w->core.height;
+ if (request->request_mode & CWBorderWidth)
+ reply->border_width = request->border_width;
+ if (request->request_mode & CWSibling)
+ reply->sibling = request->sibling;
+ if (request->request_mode & CWStackMode)
+ reply->stack_mode = request->stack_mode;
+
+ return (XtGeometryAlmost);
+ }
+
+ return (XtGeometryDone);
+}
+
+
+
+
+/************************************************************************
+ *
+ * ChangeManaged
+ *
+ ************************************************************************/
+
+static void ChangeManaged (fw)
+XwFormWidget fw;
+
+{
+ Widget child;
+ XwFormConstraintRec * constraint;
+ register int i;
+
+
+ /* If the widget is being managed, build up the reference */
+ /* structures for it, adjust any references, and process the */
+ /* reference set. If unmanaged, remove its reference. */
+
+ for (i = 0; i < fw -> composite.num_children; i++)
+ {
+ child = fw -> composite.children[i];
+ constraint = (XwFormConstraintRec *) child -> core.constraints;
+
+ if (constraint -> set_width == 0)
+ {
+ constraint -> set_x = child -> core.x;
+ constraint -> set_y = child -> core.y;
+ constraint -> set_width = child -> core.width;
+ constraint -> set_height = child -> core.height;
+ }
+
+ if (child -> core.managed != constraint -> managed)
+ {
+ if (child -> core.managed)
+ {
+ if (constraint->width_when_unmanaged != child->core.width)
+ constraint->set_width = child->core.width;
+ if (constraint->height_when_unmanaged != child->core.height)
+ constraint->set_height = child->core.height;
+ XwMakeRefs (child);
+ }
+ else
+ {
+ constraint -> width_when_unmanaged = child->core.width;
+ constraint -> height_when_unmanaged = child->core.height;
+ XwDestroyRefs (child);
+ }
+ constraint -> managed = child -> core.managed;
+ }
+ }
+
+ XwProcessRefs (fw, True);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwMakeRefs
+ * Build up and insert into the forms reference trees the reference
+ * structures needed for the widget w.
+ *
+ ************************************************************************/
+
+static void XwMakeRefs (w)
+Widget w;
+
+{
+ Widget xRefWidget;
+ Widget yRefWidget;
+ XwFormWidget formWidget;
+ XwFormConstraintRec * constraint;
+ XwFormRef * xRefParent;
+ XwFormRef * yRefParent;
+ XwFormRef * xRef;
+ XwFormRef * yRef;
+ XwFormRef * checkRef;
+ register int i;
+
+
+ formWidget = (XwFormWidget) w -> core.parent;
+ constraint = (XwFormConstraintRec *) w -> core.constraints;
+
+
+ /* The "true" reference widget may be unmanaged, so */
+ /* we need to back up through the reference set */
+ /* perhaps all the way to Form. */
+
+ xRefWidget = XwFindValidRef (constraint -> x_ref_widget, XwHORIZONTAL,
+ formWidget -> form.width_tree);
+ yRefWidget = XwFindValidRef (constraint -> y_ref_widget, XwVERTICAL,
+ formWidget -> form.height_tree);
+
+
+ /* Search the referencing trees for the referencing widgets */
+ /* The constraint reference struct will be added as a child */
+ /* of this struct. */
+
+ if (xRefWidget != NULL)
+ xRefParent = XwRefTreeSearch (xRefWidget, formWidget -> form.width_tree);
+
+ if (yRefWidget != NULL)
+ yRefParent = XwRefTreeSearch (yRefWidget, formWidget->form.height_tree);
+
+
+ /* Allocate, initialize, and insert the reference structures */
+
+ if (xRefWidget != NULL)
+ {
+ xRef = XwGetFormRef (w, xRefWidget, constraint->x_offset,
+ constraint->x_add_width, constraint->x_vary_offset,
+ constraint->x_resizable, constraint->x_attach_right,
+ constraint->x_attach_offset,
+ constraint->set_x, constraint->set_width);
+ XwAddRef (xRefParent, xRef);
+ }
+
+ if (yRefWidget != NULL)
+ {
+ yRef = XwGetFormRef(w, yRefWidget, constraint->y_offset,
+ constraint->y_add_height, constraint->y_vary_offset,
+ constraint->y_resizable, constraint->y_attach_bottom,
+ constraint->y_attach_offset,
+ constraint->set_y, constraint->set_height);
+ XwAddRef (yRefParent, yRef);
+ }
+
+
+ /* Search through the parents reference set to get any child */
+ /* references which need to be made child references of the */
+ /* widget just added. */
+
+ for (i = 0; i < xRefParent -> ref_to_count; i++)
+ {
+ checkRef = xRefParent -> ref_to[i];
+ constraint = (XwFormConstraintRec *) checkRef->this->core.constraints;
+
+ if (XwFindValidRef (constraint->x_ref_widget, XwHORIZONTAL,
+ formWidget -> form.width_tree) != xRefWidget)
+ {
+ XwRemoveRef (xRefParent, checkRef);
+ checkRef -> ref = xRef -> this;
+ XwAddRef (xRef, checkRef);
+ }
+ }
+
+ for (i = 0; i < yRefParent -> ref_to_count; i++)
+ {
+ checkRef = yRefParent -> ref_to[i];
+ constraint = (XwFormConstraintRec *) checkRef->this->core.constraints;
+
+ if (XwFindValidRef (constraint->y_ref_widget, XwVERTICAL,
+ formWidget -> form.height_tree) != yRefWidget)
+ {
+ XwRemoveRef (yRefParent, checkRef);
+ checkRef -> ref = yRef -> this;
+ XwAddRef (yRef, checkRef);
+ }
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwDestroyRefs
+ * Remove and deallocate the reference structures for the widget w.
+ *
+ ************************************************************************/
+
+static void XwDestroyRefs (w)
+Widget w;
+
+{
+ Widget xRefWidget;
+ Widget yRefWidget;
+ XwFormWidget formWidget;
+ XwFormConstraintRec * constraint;
+ XwFormRef * xRefParent;
+ XwFormRef * yRefParent;
+ XwFormRef * xRef;
+ XwFormRef * yRef;
+ XwFormRef * tempRef;
+ register int i;
+
+
+ formWidget = (XwFormWidget) w -> core.parent;
+ constraint = (XwFormConstraintRec *) w -> core.constraints;
+
+
+ /* Search through the reference trees to see if the widget */
+ /* is within the tree. */
+
+ xRefWidget = w;
+ yRefWidget = w;
+
+ xRefParent =
+ XwParentRefTreeSearch (xRefWidget, formWidget -> form.width_tree,
+ formWidget -> form.width_tree);
+ yRefParent =
+ XwParentRefTreeSearch (yRefWidget, formWidget -> form.height_tree,
+ formWidget -> form.height_tree);
+
+
+ /* For both the width and height references, if the ref parent was */
+ /* not null, find the reference to be removed within the parents */
+ /* list, remove this reference. Then, for any references attached */
+ /* to the one just removed, reparent them to the parent reference. */
+
+ if (xRefParent != NULL)
+ {
+ for (i = 0; i < xRefParent -> ref_to_count; i++)
+ {
+ if (xRefParent -> ref_to[i] -> this == xRefWidget)
+ {
+ xRef = xRefParent -> ref_to[i];
+ break;
+ }
+ }
+
+ XwRemoveRef (xRefParent, xRefParent -> ref_to[i]);
+
+ while (xRef -> ref_to_count)
+ {
+ tempRef = xRef -> ref_to[0];
+ tempRef -> ref = xRefParent -> this;
+ XwRemoveRef (xRef, tempRef);
+ XwAddRef (xRefParent, tempRef);
+ }
+
+ XtFree ((char *)xRef);
+ }
+
+ if (yRefParent != NULL)
+ {
+ for (i = 0; i < yRefParent -> ref_to_count; i++)
+ {
+ if (yRefParent -> ref_to[i] -> this == yRefWidget)
+ {
+ yRef = yRefParent -> ref_to[i];
+ break;
+ }
+ }
+
+ XwRemoveRef (yRefParent, yRef);
+
+ while (yRef -> ref_to_count)
+ {
+ tempRef = yRef -> ref_to[0];
+ tempRef -> ref = yRefParent -> this;
+ XwRemoveRef (yRef, tempRef);
+ XwAddRef (yRefParent, tempRef);
+ }
+
+ XtFree ((char *)yRef);
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwGetFormRef
+ * Allocate and initialize a form constraint referencing structure.
+ *
+ ************************************************************************/
+
+static XwFormRef *
+XwGetFormRef (this, ref, offset, add, vary,
+ resizable, attach, attach_offset, loc, size)
+Widget this;
+Widget ref;
+int offset;
+Boolean add;
+Boolean vary;
+Boolean resizable;
+Boolean attach;
+int attach_offset;
+
+{
+ XwFormRef * formRef;
+
+ formRef = (XwFormRef *) XtMalloc (sizeof (XwFormRef));
+ formRef -> this = this;
+ formRef -> ref = ref;
+ formRef -> offset = offset;
+ formRef -> add = add;
+ formRef -> vary = vary;
+ formRef -> resizable = resizable;
+ formRef -> attach = attach;
+ formRef -> attach_offset = attach_offset;
+
+ formRef -> set_loc = loc;
+ formRef -> set_size = size;
+
+ formRef -> ref_to = NULL;
+ formRef -> ref_to_count = 0;
+
+ return (formRef);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwFindValidRef
+ * Given an initial reference widget to be used as a constraint,
+ * find a valid (managed) reference widget. This is done by
+ * backtracking through the widget references listed in the
+ * constraint records. If no valid constraint is found, "form"
+ * is returned indicating that this reference should be stuck
+ * immediately under the form reference structure.
+ *
+ ************************************************************************/
+
+static Widget XwFindValidRef (refWidget, refType, formRef)
+Widget refWidget;
+int refType;
+XwFormRef * formRef;
+
+{
+ XwFormConstraintRec * constraint;
+
+ if (refWidget == NULL) return (NULL);
+
+ while (1)
+ {
+ if (XwRefTreeSearch (refWidget, formRef) != NULL) return (refWidget);
+
+ constraint = (XwFormConstraintRec *) refWidget -> core.constraints;
+
+ if (refType == XwHORIZONTAL) refWidget = constraint -> x_ref_widget;
+ else refWidget = constraint -> y_ref_widget;
+
+ if (refWidget == NULL) return (refWidget -> core.parent);
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwRefTreeSearch
+ * Search the reference tree until the widget listed is found.
+ *
+ ************************************************************************/
+
+static XwFormRef * XwRefTreeSearch (w, formRef)
+Widget w;
+XwFormRef * formRef;
+
+{
+ register int i;
+ XwFormRef * tempRef;
+
+ if (formRef == NULL) return (NULL);
+ if (formRef -> this == w) return (formRef);
+
+ for (i = 0; i < formRef -> ref_to_count; i++)
+ {
+ tempRef = XwRefTreeSearch (w, formRef -> ref_to[i]);
+ if (tempRef != NULL) return (tempRef);
+ }
+
+ return (NULL);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwParentRefTreeSearch
+ * Search the reference tree until the parent reference of the
+ * widget listed is found.
+ *
+ ************************************************************************/
+
+static XwFormRef * XwParentRefTreeSearch (w, wFormRef, parentFormRef)
+Widget w;
+XwFormRef * wFormRef;
+XwFormRef * parentFormRef;
+
+{
+ register int i;
+ XwFormRef * tempRef;
+
+ if (parentFormRef == NULL) return (NULL);
+ if (wFormRef -> this == w) return (parentFormRef);
+
+ for (i = 0; i < wFormRef -> ref_to_count; i++)
+ {
+ tempRef =
+ XwParentRefTreeSearch (w, wFormRef -> ref_to[i], wFormRef);
+ if (tempRef != NULL) return (tempRef);
+ }
+
+ return (NULL);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwAddRef
+ * Add a reference structure into a parent reference structure.
+ *
+ ************************************************************************/
+
+static void XwAddRef (refParent, ref)
+XwFormRef * refParent;
+XwFormRef * ref;
+
+{
+ refParent -> ref_to =
+ (XwFormRef **)
+ XtRealloc ((char *) refParent -> ref_to,
+ sizeof (XwFormRef *) * (refParent -> ref_to_count + 1));
+
+ refParent -> ref_to[refParent -> ref_to_count] = ref;
+ refParent -> ref_to_count += 1;
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwRemoveRef
+ * Remove a reference structure from a parent reference structure.
+ *
+ ************************************************************************/
+
+static void XwRemoveRef (refParent, ref)
+XwFormRef * refParent;
+XwFormRef * ref;
+
+{
+ register int i, j;
+
+ for (i = 0; i < refParent -> ref_to_count; i++)
+ {
+ if (refParent -> ref_to[i] == ref)
+ {
+ for (j = i; j < refParent -> ref_to_count - 1; j++)
+ refParent -> ref_to[j] = refParent -> ref_to[j + 1];
+ break;
+ }
+ }
+
+ if (refParent -> ref_to_count > 1)
+ {
+ refParent -> ref_to =
+ (XwFormRef **) XtRealloc ((char *) refParent -> ref_to,
+ sizeof (XwFormRef *) * (refParent -> ref_to_count - 1));
+
+ }
+ else
+ {
+ XtFree ((char *)(refParent -> ref_to));
+ refParent -> ref_to = NULL;
+ }
+
+ refParent -> ref_to_count -= 1;
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwProcessRefs
+ * Traverse throught the form's reference trees, calculate new
+ * child sizes and locations based on the constraints and adjust
+ * the children as is calculated. The resizable flag indicates
+ * whether the form can be resized or not.
+ *
+ ************************************************************************/
+
+static void XwProcessRefs (fw, formResizable)
+XwFormWidget fw;
+Boolean formResizable;
+
+{
+ int formWidth, formHeight;
+ register int i, j;
+
+ int horDepth, horLeaves;
+ int vertDepth, vertLeaves;
+ XwFormProcess ** horProcessList;
+ XwFormProcess ** vertProcessList;
+
+ XtGeometryResult geometryReturn;
+ Dimension replyW, replyH;
+
+ XwFormConstraintRec * constraintRec;
+ Widget child;
+ Boolean moveFlag, resizeFlag;
+
+
+ /* Initialize the form width and height variables */
+
+ if (fw -> manager.layout == XwIGNORE) formResizable = False;
+
+ if (formResizable) formWidth = formHeight = -1;
+ else
+ {
+ formWidth = fw -> core.width;
+ formHeight = fw -> core.height;
+ }
+
+
+ /* Traverse the reference trees to find the depth and leaf node count */
+
+ leaves = 0;
+ depth = 0;
+ XwFindDepthAndCount (fw -> form.width_tree, 1);
+ horDepth = depth;
+ horLeaves = leaves;
+
+ leaves = 0;
+ depth = 0;
+ XwFindDepthAndCount (fw -> form.height_tree, 1);
+ vertDepth = depth;
+ vertLeaves = leaves;
+
+ if (horDepth == 0 && vertDepth == 0)
+ return;
+
+
+ /* Allocate and initialize the constraint array processing structures */
+
+ horProcessList =
+ (XwFormProcess **) XtMalloc (sizeof (XwFormProcess **) * horLeaves);
+ for (i = 0; i < horLeaves; i++)
+ {
+ horProcessList[i] =
+ (XwFormProcess *) XtMalloc (sizeof (XwFormProcess) * horDepth);
+
+ for (j = 0; j < horDepth; j++)
+ horProcessList[i][j].ref = NULL;
+ }
+
+
+ vertProcessList =
+ (XwFormProcess **) XtMalloc (sizeof (XwFormProcess **) * vertLeaves);
+ for (i = 0; i < vertLeaves; i++)
+ {
+ vertProcessList[i] =
+ (XwFormProcess *) XtMalloc (sizeof (XwFormProcess) * vertDepth);
+
+ for (j = 0; j < vertDepth; j++)
+ vertProcessList[i][j].ref = NULL;
+ }
+
+
+ /* Initialize the process array placing each node of the tree into */
+ /* the array such that it is listed only once and its first children */
+ /* listed directly next within the array. */
+
+ arrayIndex = 0;
+ XwInitProcessList (horProcessList, fw -> form.width_tree, 0);
+ arrayIndex = 0;
+ XwInitProcessList (vertProcessList, fw -> form.height_tree, 0);
+
+
+ /* Process each array such that each row of the arrays contain */
+ /* their required sizes and locations to match the constraints */
+
+ XwConstrainList (horProcessList, horLeaves,
+ horDepth, &formWidth, formResizable, XwHORIZONTAL);
+ XwConstrainList (vertProcessList, vertLeaves,
+ vertDepth, &formHeight, formResizable, XwVERTICAL);
+
+
+ /* If the form is resizable and the form width or height returned */
+ /* is different from the current form width or height, then make */
+ /* a geometry request to get the new form size. If almost is */
+ /* returned, use these sizes and reprocess the constrain lists */
+
+ if (formResizable &&
+ (formWidth != fw -> core.width || formHeight != fw -> core.height))
+ {
+ geometryReturn =
+ XtMakeResizeRequest((Widget)fw, formWidth, formHeight, &replyW, &replyH);
+
+ if (geometryReturn == XtGeometryAlmost)
+ {
+ formWidth = replyW;
+ formHeight = replyH;
+
+ XtMakeResizeRequest((Widget)fw, formWidth, formHeight, NULL, NULL);
+
+ XwConstrainList (horProcessList, horLeaves,
+ horDepth, &formWidth, False, XwHORIZONTAL);
+ XwConstrainList (vertProcessList, vertLeaves,
+ vertDepth, &formHeight, False, XwVERTICAL);
+ }
+
+ else if (geometryReturn == XtGeometryNo)
+ {
+ formWidth = fw -> core.width;
+ formHeight = fw -> core.height;
+
+ XwConstrainList (horProcessList, horLeaves,
+ horDepth, &formWidth, False, XwHORIZONTAL);
+ XwConstrainList (vertProcessList, vertLeaves,
+ vertDepth, &formHeight, False, XwVERTICAL);
+ }
+ }
+
+
+ /* Process the forms child list to compare the widget sizes and */
+ /* locations with the widgets current values and if changed, */
+ /* reposition, resize, or reconfigure the child. */
+
+ for (i = 0; i < fw -> composite.num_children; i++)
+ {
+ child = (Widget) fw -> composite.children[i];
+
+ if (child -> core.managed)
+ {
+ constraintRec = (XwFormConstraintRec *) child -> core.constraints;
+
+ moveFlag = resizeFlag = False;
+
+ if (constraintRec -> x != child -> core.x ||
+ constraintRec -> y != child -> core.y)
+ moveFlag = True;
+
+ if (constraintRec -> width != child -> core.width ||
+ constraintRec -> height != child -> core.height)
+ resizeFlag = True;
+
+ if (moveFlag && resizeFlag)
+ XtConfigureWidget (child, constraintRec->x, constraintRec->y,
+ constraintRec->width, constraintRec->height,
+ child -> core.border_width);
+ else if (moveFlag)
+ XtMoveWidget (child, constraintRec->x, constraintRec->y);
+ else if (resizeFlag)
+ XtResizeWidget (child, constraintRec->width,
+ constraintRec->height, child->core.border_width);
+ }
+ }
+
+ XwFreeConstraintList (horProcessList, horLeaves);
+ XwFreeConstraintList (vertProcessList, vertLeaves);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwFreeConstraintList
+ * Free an allocated constraint list.
+ *
+ ************************************************************************/
+
+static void XwFreeConstraintList (processList, leaves)
+XwFormProcess ** processList;
+int leaves;
+
+{
+ register int i;
+
+
+ /* Free each array attached to the list then free the list */
+
+ for (i = 0; i < leaves; i++)
+ XtFree ((char *)(processList[i]));
+
+ XtFree ((char *)processList);
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwFindDepthAndCount
+ * Search a constraint reference tree and find the maximum depth
+ * of the tree and the number of leaves in the tree.
+ *
+ ************************************************************************/
+
+static void XwFindDepthAndCount (node, nodeLevel)
+XwFormRef * node;
+int nodeLevel;
+
+{
+ register int i;
+
+ if (node -> ref_to == NULL) leaves++;
+ else
+ {
+ nodeLevel++;
+ if (nodeLevel > depth) depth = nodeLevel;
+ for (i = 0; i < node -> ref_to_count; i++)
+ XwFindDepthAndCount (node -> ref_to[i], nodeLevel);
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * XwInitProcessList
+ * Search a constraint reference tree and find place the ref node
+ * pointers into the list.
+ *
+ ************************************************************************/
+
+static void XwInitProcessList (processList, node, nodeLevel)
+XwFormProcess ** processList;
+XwFormRef * node;
+int nodeLevel;
+
+{
+ register int i;
+
+ processList[arrayIndex][nodeLevel].ref = node;
+
+ if (node -> ref_to == NULL)
+ {
+ processList[arrayIndex][nodeLevel].leaf = True;
+ arrayIndex++;
+ }
+ else
+ {
+ processList[arrayIndex][nodeLevel].leaf = False;
+ nodeLevel++;
+ for (i = 0; i < node -> ref_to_count; i++)
+ XwInitProcessList (processList, node -> ref_to[i], nodeLevel);
+ }
+}
+
+
+
+/************************************************************************
+ *
+ * XwConstrainList
+ * Process each array such that each row of the arrays contain
+ * their required sizes and locations to match the constraints
+ *
+ ************************************************************************/
+
+static void XwConstrainList (processList, leaves, depth,
+ formSize, varySize, orient)
+XwFormProcess ** processList;
+int leaves;
+int depth;
+int * formSize;
+Boolean varySize;
+int orient;
+
+{
+ register int i, j;
+ register XwFormRef * ref;
+ XwFormConstraintRec * constraint;
+ XwFormConstraintRec * parentConstraint;
+ int heldSize;
+ int sizeDif;
+ int vary, resize;
+ int varyCount, varyAmount;
+ int resizeCount, resizeAmount;
+ int constantSubtract;
+ int addAmount, subtractAmount;
+ int size, separation;
+
+
+
+ heldSize = 0;
+
+
+ for (i = 0; i < leaves; i++) /* Process all array lines */
+ {
+ processList[i][0].size = 0;
+ processList[i][0].loc = 0;
+
+
+ for (j = 1; j < depth; j++) /* Process array line */
+ {
+ ref = processList[i][j].ref;
+
+ if (ref != NULL)
+ {
+ processList[i][j].size = ref -> set_size;
+
+ if (ref -> ref == ref -> this -> core.parent)
+ {
+ if (ref -> offset != 0)
+ processList[i][j].loc = ref -> offset;
+ else
+ processList[i][j].loc = ref -> set_loc;
+ }
+ else
+ {
+ processList[i][j].loc =
+ processList[i][j - 1].loc + ref->offset;
+ if (ref -> add)
+ processList[i][j].loc += processList[i][j - 1].size +
+ processList[i][j].ref -> this -> core.border_width * 2;
+ }
+
+ }
+ else
+ {
+ processList[i][j].ref = processList[i - 1][j].ref;
+ processList[i][j].loc = processList[i - 1][j].loc;
+ processList[i][j].size = processList[i - 1][j].size;
+ processList[i][j].leaf = processList[i - 1][j].leaf;
+ }
+
+ if (processList[i][j].leaf)
+ {
+ if (processList[i][0].size < processList[i][j].size +
+ processList[i][j].ref -> this -> core.border_width * 2 +
+ processList[i][j].loc + ref -> attach_offset)
+ {
+ processList[i][0].size = processList[i][j].size +
+ processList[i][j].ref -> this -> core.border_width * 2 +
+ processList[i][j].loc + ref -> attach_offset;
+ }
+
+ if (processList[i][j].leaf && processList[i][0].size > heldSize)
+ heldSize = processList[i][0].size;
+
+ break;
+ }
+ }
+ }
+
+
+ /* Each array line has now been processed to optimal size. Reprocess */
+ /* each line to constrain it to formSize if not varySize or to */
+ /* heldSize if varySize. */
+
+ if (varySize)
+ *formSize = heldSize;
+
+
+
+ for (i = 0; i < leaves; i++)
+ {
+
+ /* For each array line if the 0th size (calculated form size needed */
+ /* for this array line is less than the form size then increase the */
+ /* seperations between widgets whose constaints allow it. */
+ /* If can't do it by varying separation, but can do it by resizing, */
+ /* then do that. */
+
+ if (processList[i][0].size < *formSize)
+ {
+ sizeDif = *formSize - processList[i][0].size;
+
+ varyCount = 0;
+ resizeCount = 0;
+ for (j = 1; j < depth; j++)
+ {
+ /* Can't vary the first spacing */
+ if (j > 1 && processList[i][j].ref -> vary) varyCount++;
+ if (processList[i][j].ref -> resizable) resizeCount++;
+ if (processList[i][j].leaf) break;
+ }
+
+ addAmount = 0;
+ resizeAmount = 0;
+ if (varyCount == 0)
+ {
+ varyAmount = 0;
+ if (resizeCount != 0)
+ resizeAmount = sizeDif / resizeCount;
+ }
+ else varyAmount = sizeDif / varyCount;
+
+ j = 1;
+
+ while (j < depth)
+ {
+ if (j > 1 && processList[i][j].ref -> vary)
+ addAmount += varyAmount;
+ processList[i][j].loc += addAmount;
+ if (processList[i][j].ref -> resizable)
+ {
+ processList[i][j].size += resizeAmount;
+ addAmount += resizeAmount;
+ }
+
+ if (processList[i][j].leaf) break;
+
+ j++;
+ }
+
+ if (j > 1)
+ {
+ if (processList[i][j].ref -> vary &&
+ processList[i][j].ref -> attach)
+ processList[i][j].loc = *formSize - processList[i][j].size -
+ processList[i][j].ref -> attach_offset;
+ else if (processList[i][j].ref -> vary == False &&
+ processList[i][j].ref -> resizable &&
+ processList[i][j].ref -> attach)
+ {
+ processList[i][j].size =
+ *formSize - processList[i][j].loc -
+ processList[i][j].ref -> this -> core.border_width * 2 -
+ processList[i][j].ref -> attach_offset;
+ }
+ }
+ else
+ {
+ if (processList[i][j].ref -> vary == False &&
+ processList[i][j].ref -> resizable &&
+ processList[i][j].ref -> attach)
+ {
+ processList[i][j].loc = processList[i][j].ref -> offset;
+ processList[i][j].size =
+ *formSize - processList[i][j].loc -
+ processList[i][j].ref -> this -> core.border_width * 2 -
+ processList[i][j].ref -> attach_offset;
+
+ }
+ else if (processList[i][j].ref -> vary &&
+ processList[i][j].ref -> attach)
+ {
+ processList[i][j].loc =
+ *formSize - processList[i][j].size -
+ processList[i][j].ref -> this -> core.border_width * 2 -
+ processList[i][j].ref -> attach_offset;
+ }
+ else if (processList[i][j].ref -> vary &&
+ processList[i][j].ref -> attach == False)
+ {
+ processList[i][j].loc = processList[i][j].ref -> offset;
+ }
+ }
+ }
+
+
+ /* If the form size has gotton smaller, process the vary constraints */
+ /* until the needed size is correct or all seperations are 1 pixel. */
+ /* If separations go to 1, then process the resizable widgets */
+ /* until the needed size is correct or the sizes have gone to 1 */
+ /* pixel. If the size is still not correct punt, cannot find a */
+ /* usable size so clip it. */
+
+ if (processList[i][0].size > *formSize)
+ {
+ sizeDif = processList[i][0].size - *formSize;
+
+ varyAmount = 0;
+ varyCount = 0;
+
+ j = 0;
+ do
+ {
+ j++;
+
+ if (j > 1 && processList[i][j].ref -> vary &&
+ processList[i][j].ref -> offset)
+ {
+ varyAmount += processList[i][j].ref -> offset;
+ varyCount++;
+ }
+ }
+ while (processList[i][j].leaf == False);
+
+
+ resizeAmount = 0;
+ resizeCount = 0;
+ for (j = 1; j < depth; j++)
+ {
+ if (processList[i][j].ref->resizable && processList[i][j].size > 1)
+ {
+ if (processList[i][j].leaf || processList[i][j+1].ref->add)
+ {
+ resizeCount++;
+ resizeAmount += processList[i][j].size - 1;
+ }
+ }
+ if (processList[i][j].leaf) break;
+ }
+
+
+ /* Do we have enough varience to match the constraints? */
+
+ if (varyAmount + resizeAmount > sizeDif)
+ {
+
+ /* first process out the vary amount */
+
+ if (varyCount)
+ {
+ do
+ {
+ subtractAmount = 0;
+
+ for (j = 1; j < depth; j++)
+ {
+ if (j > 1 && processList[i][j].ref -> vary)
+ {
+ vary =
+ processList[i][j].loc - processList[i][j - 1].loc;
+
+ if (processList[i][j].ref -> add)
+ vary = vary - processList[i][j - 1].size - 1 -
+ processList[i][j-1].ref->
+ this->core.border_width * 2;
+ }
+ else vary = 0;
+
+ if (vary > 0) subtractAmount++;
+
+ if (subtractAmount)
+ {
+ processList[i][j].loc -= subtractAmount;
+ sizeDif--;
+ }
+
+ if (processList[i][j].leaf) break;
+ }
+ }
+ while (subtractAmount != 0 && sizeDif > 0);
+ }
+
+
+ /* now process resize constraints if further constraint */
+ /* processing is necessary. */
+
+ if (sizeDif)
+ {
+ if (resizeAmount > sizeDif) resizeAmount = sizeDif;
+ if (resizeCount) constantSubtract = resizeAmount / resizeCount;
+
+ while (resizeAmount > 0)
+ {
+ subtractAmount = 0;
+
+ for (j = 1; j < depth; j++)
+ {
+ if (processList[i][j].ref -> add)
+ processList[i][j].loc -= subtractAmount;
+
+ if (processList[i][j].ref -> resizable)
+ {
+ if (processList[i][j].leaf ||
+ processList[i][j + 1].ref -> add)
+ resize = processList[i][j].size - 1;
+ else
+ resize = 0;
+
+ if (resize > 1)
+ {
+ if (constantSubtract < resize)
+ resize = constantSubtract;
+ subtractAmount += resize;
+ processList[i][j].size -= resize;
+ }
+ }
+
+ if (processList[i][j].leaf) break;
+ }
+
+ resizeAmount -= subtractAmount;
+ constantSubtract = 1;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /* Now each array line is processed such that its line is properly */
+ /* constrained to match the specified form size. Since a single */
+ /* widget reference structure can be referenced in multiple array */
+ /* lines, the minumum constraint for each widget needs to be found. */
+ /* When found, the width and height will be placed into the widgets */
+ /* constraint structure. */
+
+ for (i = 1; i < depth; i++)
+ {
+ ref = NULL;
+
+ for (j = 0; j < leaves + 1; j++) /* loop one to many - for exit */
+ {
+ if (j == leaves || ref != processList[j][i].ref)
+ {
+ if (j == leaves || ref != NULL)
+ {
+ if (ref != NULL)
+ {
+ constraint =
+ (XwFormConstraintRec *) ref -> this -> core.constraints;
+ parentConstraint =
+ (XwFormConstraintRec *) ref -> ref -> core.constraints;
+
+ if (orient == XwHORIZONTAL) constraint -> width = size;
+ else constraint -> height = size;
+
+ if (i > 1)
+ {
+ if (orient== XwHORIZONTAL)
+ constraint -> x = parentConstraint -> x + separation;
+ else
+ constraint -> y = parentConstraint -> y + separation;
+ }
+ else
+ {
+ if (orient == XwHORIZONTAL) constraint -> x = separation;
+ else constraint -> y = separation;
+ }
+ }
+
+ if (j == leaves) break; /* exit out of the inner loop */
+ }
+
+ ref = processList[j][i].ref;
+ separation = 10000000;
+ size = 10000000;
+ }
+
+ if (ref != NULL)
+ {
+ if (size > processList[j][i].size) size = processList[j][i].size;
+
+ if (i > 1)
+ {
+ if (separation > processList[j][i].loc-processList[j][i-1].loc)
+ separation = processList[j][i].loc-processList[j][i-1].loc;
+ }
+ else
+ if (separation > processList[j][i].loc)
+ separation = processList[j][i].loc;
+ }
+ }
+ }
+}
diff --git a/Xw/Form.h b/Xw/Form.h
new file mode 100644
index 0000000..fd48843
--- /dev/null
+++ b/Xw/Form.h
@@ -0,0 +1,34 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Form.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for Form class widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/* Form Widget */
+
+extern WidgetClass XwformWidgetClass;
+
+typedef struct _XwFormClassRec * XwFormWidgetClass;
+typedef struct _XwFormRec * XwFormWidget;
+typedef struct _XwFormConstraintRec * XwFormConstraints;
+
diff --git a/Xw/FormP.h b/Xw/FormP.h
new file mode 100644
index 0000000..7716c51
--- /dev/null
+++ b/Xw/FormP.h
@@ -0,0 +1,140 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: FormP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for the Form class
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/* Form constraint rec */
+
+typedef struct _XwFormConstraintRec
+{
+ String x_ref_name; /* the name of the widget to reference */
+ Widget x_ref_widget; /* the widget to reference */
+ int x_offset; /* the offset (pixels) from the reference */
+ Boolean x_add_width; /* add width of the reference to x coord */
+ Boolean x_vary_offset; /* able to vary the seperation */
+ Boolean x_resizable; /* able to resize in x direction */
+ Boolean x_attach_right; /* attached to the right edge of the form */
+ int x_attach_offset; /* offset (pixels) from attached edge */
+
+ String y_ref_name; /* y constraints are the same as x */
+ Widget y_ref_widget;
+ int y_offset;
+ Boolean y_add_height;
+ Boolean y_vary_offset;
+ Boolean y_resizable;
+ Boolean y_attach_bottom;
+ int y_attach_offset;
+
+
+ Boolean managed; /* whether the widget is managed or not */
+ int x, y; /* location after constraint processing */
+ Dimension width, height; /* size after constraint processing */
+
+ int set_x; /* original y */
+ int set_y; /* original x */
+ Dimension set_width; /* original or set values width of widget */
+ Dimension set_height; /* original or set values height of widget */
+
+ Dimension width_when_unmanaged;
+ Dimension height_when_unmanaged;
+} XwFormConstraintRec;
+
+
+/* Form class structure */
+
+typedef struct _XwFormClassPart
+{
+ int foo; /* No new fields needed */
+} XwFormClassPart;
+
+
+/* Full class record declaration for Form class */
+
+typedef struct _XwFormClassRec
+{
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwFormClassPart form_class;
+} XwFormClassRec;
+
+extern XwFormClassRec XwformClassRec;
+
+
+/* The Form tree structure used for containing the constraint tree */
+
+struct _XwFormRef
+{
+ Widget this; /* the widget these constaints are for */
+ Widget ref; /* the widget this constraint is for */
+ int offset; /* offset (pixels) from parent ref */
+ Boolean add; /* add (width or height) of parent ref */
+ Boolean vary; /* able to vary the seperation */
+ Boolean resizable; /* able to resize */
+ Boolean attach; /* attached to the edge (right or bottom) */
+ int attach_offset; /* offset (pixels) from attached edge */
+
+ int set_loc; /* the initial or set value location */
+ int set_size; /* the initial or set value size */
+
+ struct _XwFormRef ** ref_to; /* child references */
+ int ref_to_count; /* number of child references */
+};
+
+typedef struct _XwFormRef XwFormRef;
+
+
+typedef struct _XwFormProcess
+{
+ XwFormRef * ref;
+ int loc;
+ int size;
+ Boolean leaf;
+} XwFormProcess;
+
+/* The Form instance record */
+
+typedef struct _XwFormPart
+{
+ XwFormRef * width_tree;
+ XwFormRef * height_tree;
+} XwFormPart;
+
+
+/* Full instance record declaration */
+
+typedef struct _XwFormRec
+{
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwFormPart form;
+} XwFormRec;
+
+
+
+
diff --git a/Xw/Imakefile b/Xw/Imakefile
new file mode 100644
index 0000000..f8f5ca9
--- /dev/null
+++ b/Xw/Imakefile
@@ -0,0 +1,99 @@
+# Compile flags
+CC = cc
+# If you wish to compile with gcc:
+#CC = gcc
+
+# cckr is for SGI only (non-ansi-standard switch):
+#CCOPTIONS = -O2 -cckr -Wf,-XNh2000
+# for DEC Alpha:
+#CCOPTIONS = -Olimit 1000 -taso
+# for DEC ULTRIX:
+#CCOPTIONS = -Olimit 1000
+# for Linux:
+#CCOPTIONS = -O2 -w -m486
+# otherwise (Sun, gcc, etc.):
+#CCOPTIONS = -O2 -w
+
+# CDEBUGFLAGS is passed from top-level Imakefile
+
+INCLUDES = -I.. -I$(TOP)
+INSTALLFLAGS = $(INSTINCFLAGS)
+
+HEADERS = \
+ BBoard.h \
+ BBoardP.h \
+ Cascade.h \
+ CascadeP.h \
+ DisplayP.h \
+ Form.h \
+ FormP.h \
+ MenuBtn.h \
+ MenuBtnP.h \
+ PButton.h \
+ PButtonP.h \
+ PopupMgr.h \
+ PopupMgrP.h \
+ SText.h \
+ STextP.h \
+ SourceP.h \
+ TextEdit.h \
+ TextEditP.h \
+ Toggle.h \
+ ToggleP.h \
+ WorkSpace.h \
+ WorkSpaceP.h \
+ Xw.h \
+ XwP.h
+
+SRCS = \
+ BBoard.c\
+ Button.c\
+ Cascade.c\
+ Display.c\
+ Form.c\
+ Manager.c\
+ MapEvents.c\
+ MenuBtn.c\
+ MenuMgr.c\
+ MenuPane.c\
+ PButton.c\
+ PopupMgr.c\
+ Primitive.c\
+ ResConvert.c\
+ SText.c\
+ SourceStr.c\
+ TextEdit.c\
+ Toggle.c\
+ Traversal.c\
+ WorkSpace.c
+
+OBJS = \
+ BBoard.o\
+ Button.o\
+ Cascade.o\
+ Display.o\
+ Form.o\
+ Manager.o\
+ MapEvents.o\
+ MenuBtn.o\
+ MenuMgr.o\
+ MenuPane.o\
+ PButton.o\
+ PopupMgr.o\
+ Primitive.o\
+ ResConvert.o\
+ SText.o\
+ SourceStr.o\
+ TextEdit.o\
+ Toggle.o\
+ Traversal.o\
+ WorkSpace.o
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(xcXw,$(OBJS))
+DependTarget()
+
+clean::
+ rm *.o
+veryclean::
+ rm *.o libxcXw.a
diff --git a/Xw/Makefile.am b/Xw/Makefile.am
new file mode 100644
index 0000000..73039ca
--- /dev/null
+++ b/Xw/Makefile.am
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+EXTRA_DIST = sub.c
+
+INCLUDES = -I..
+
+SUBDIRS =
+SUBLIB =
+
+# Requirements for Xw library
+noinst_LIBRARIES = libxcXw.a
+
+libxcXw_a_SOURCES = BBoard.c Button.c Cascade.c Display.c Form.c \
+ Manager.c MapEvents.c MenuBtn.c MenuMgr.c MenuPane.c \
+ PButton.c PopupMgr.c Primitive.c ResConvert.c SText.c \
+ SourceStr.c TextEdit.c Toggle.c Traversal.c WorkSpace.c
diff --git a/Xw/Makefile.in b/Xw/Makefile.in
new file mode 100644
index 0000000..2c586b8
--- /dev/null
+++ b/Xw/Makefile.in
@@ -0,0 +1,617 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = Xw
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libxcXw_a_AR = $(AR) $(ARFLAGS)
+libxcXw_a_LIBADD =
+am_libxcXw_a_OBJECTS = BBoard.$(OBJEXT) Button.$(OBJEXT) \
+ Cascade.$(OBJEXT) Display.$(OBJEXT) Form.$(OBJEXT) \
+ Manager.$(OBJEXT) MapEvents.$(OBJEXT) MenuBtn.$(OBJEXT) \
+ MenuMgr.$(OBJEXT) MenuPane.$(OBJEXT) PButton.$(OBJEXT) \
+ PopupMgr.$(OBJEXT) Primitive.$(OBJEXT) ResConvert.$(OBJEXT) \
+ SText.$(OBJEXT) SourceStr.$(OBJEXT) TextEdit.$(OBJEXT) \
+ Toggle.$(OBJEXT) Traversal.$(OBJEXT) WorkSpace.$(OBJEXT)
+libxcXw_a_OBJECTS = $(am_libxcXw_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libxcXw_a_SOURCES)
+DIST_SOURCES = $(libxcXw_a_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_TARGET = @ALL_TARGET@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_LIB_SPECS = @EXTRA_LIB_SPECS@
+GREP = @GREP@
+GS_EXEC = @GS_EXEC@
+HAVE_LGF = @HAVE_LGF@
+INC_SPECS = @INC_SPECS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTALL_TARGET = @INSTALL_TARGET@
+INTERPRETER = @INTERPRETER@
+INTERP_PATH = @INTERP_PATH@
+LD = @LD@
+LDDL_FLAGS = @LDDL_FLAGS@
+LDFLAGS = @LDFLAGS@
+LD_RUN_PATH = @LD_RUN_PATH@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIB_SPECS = @LIB_SPECS@
+LTLIBOBJS = @LTLIBOBJS@
+M4 = @M4@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+REVISION = @REVISION@
+SET_MAKE = @SET_MAKE@
+SHDLIB_EXT = @SHDLIB_EXT@
+SHELL = @SHELL@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_LIB_SPECS = @SHLIB_LIB_SPECS@
+SPICE_EXEC = @SPICE_EXEC@
+STARTUP_FILE = @STARTUP_FILE@
+STDLIBS = @STDLIBS@
+STRIP = @STRIP@
+SUBDIRS =
+SUBLIB =
+TCL_LIB_DIR = @TCL_LIB_DIR@
+VERSION = @VERSION@
+WISH_EXE = @WISH_EXE@
+WRAPPER_SCRIPT = @WRAPPER_SCRIPT@
+XCIRCUIT_TARGET = @XCIRCUIT_TARGET@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+EXTRA_DIST = sub.c
+INCLUDES = -I..
+
+# Requirements for Xw library
+noinst_LIBRARIES = libxcXw.a
+libxcXw_a_SOURCES = BBoard.c Button.c Cascade.c Display.c Form.c \
+ Manager.c MapEvents.c MenuBtn.c MenuMgr.c MenuPane.c \
+ PButton.c PopupMgr.c Primitive.c ResConvert.c SText.c \
+ SourceStr.c TextEdit.c Toggle.c Traversal.c WorkSpace.c
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Xw/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Xw/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libxcXw.a: $(libxcXw_a_OBJECTS) $(libxcXw_a_DEPENDENCIES)
+ -rm -f libxcXw.a
+ $(libxcXw_a_AR) libxcXw.a $(libxcXw_a_OBJECTS) $(libxcXw_a_LIBADD)
+ $(RANLIB) libxcXw.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Xw/Manager.c b/Xw/Manager.c
new file mode 100644
index 0000000..00bd0c1
--- /dev/null
+++ b/Xw/Manager.c
@@ -0,0 +1,894 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Manager.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: This file contains source for the Manager Meta Widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <X11/StringDefs.h>
+
+static Boolean XwFocusIsHere();
+static void MgrDestroy();
+static void MgrClassPartInit();
+static void ClassInitialize();
+static void Initialize();
+static Boolean SetValues();
+
+
+
+/*************************************<->*************************************
+ *
+ * Default translations for all subclasses of Manager
+ * -----------
+ * Note, if a manager subclass has additional translations it
+ * will have to duplicate this set as well.
+ *************************************<->***********************************/
+
+static char defaultTranslations[] =
+ "<EnterWindow>: enter() \n\
+ <LeaveWindow>: leave() \n\
+ <Visible>: visible() \n\
+ <FocusIn>: focusIn()";
+
+
+
+/*************************************<->*************************************
+ *
+ * Default actions for all subclasses of Manager
+ * -----------
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ {"enter", (XtActionProc) _XwManagerEnter},
+ {"leave", (XtActionProc) _XwManagerLeave},
+ {"focusIn", (XtActionProc) _XwManagerFocusIn},
+ {"visible", (XtActionProc) _XwManagerVisibility},
+};
+
+/*
+ * Resource definitions for Subclasses of Manager
+ */
+
+static XtResource resources[] =
+{
+ {
+ XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
+ XtOffset (XwManagerWidget, manager.foreground),
+ XtRString, "XtDefaultForeground"
+ },
+
+ {
+ XtNbackgroundTile, XtCBackgroundTile, XtRTileType, sizeof (int),
+ XtOffset (XwManagerWidget, manager.background_tile),
+ XtRString, "background"
+ },
+
+ {
+ XtNhighlightThickness, XtCHighlightThickness, XtRInt, sizeof (int),
+ XtOffset (XwManagerWidget, manager.highlight_thickness),
+ XtRString, "0"
+ },
+
+ {
+ XtNtraversalOn, XtCTraversalOn, XtRBoolean, sizeof (Boolean),
+ XtOffset (XwManagerWidget, manager.traversal_on),
+ XtRString, "False"
+ },
+
+ {
+ XtNlayout, XtCLayout, XtRLayout, sizeof(int),
+ XtOffset(XwManagerWidget, manager.layout),
+ XtRString, "minimize"
+ },
+
+ {
+ XtNnextTop, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset (XwManagerWidget, manager.next_top),
+ XtRPointer, (caddr_t) NULL
+ },
+
+};
+
+
+/******************************************************************
+ * The Manager class record definition
+ ******************************************************************/
+
+XwManagerClassRec XwmanagerClassRec =
+{
+ {
+ (WidgetClass) &constraintClassRec, /* superclass */
+ "XwManager", /* class_name */
+ sizeof(XwManagerRec), /* widget_size */
+ ClassInitialize, /* class_initialize */
+ MgrClassPartInit, /* class part initialize */
+ FALSE, /* class_inited */
+ Initialize, /* initialize */
+ NULL, /* initialize hook */
+ NULL, /* realize */
+ actionsList, /* actions */
+ XtNumber(actionsList), /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ TRUE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress enterleave */
+ FALSE, /* visible_interest */
+ MgrDestroy, /* destroy */
+ NULL, /* resize */
+ NULL, /* expose */
+ SetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback private */
+ NULL, /* tm_table */
+ NULL, /* query geometry */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ { /* Composite class */
+ NULL, /* Geometry Manager */
+ NULL, /* Change Managed */
+ _XwManagerInsertChild, /* Insert Child */
+ XtInheritDeleteChild, /* Delete Child */
+ NULL,
+ },
+
+ { /* constraint class fields */
+ NULL,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ {
+ (XwTraversalProc) mgr_traversal, /* Mgr class traversal handler */
+ NULL, /* default translations */
+ }
+};
+
+WidgetClass XwmanagerWidgetClass = (WidgetClass) &XwmanagerClassRec;
+
+
+
+/************************************************************************
+ *
+ * ClassInitialize
+ * Initialize the manager class structure. This is called only the
+ * first time a manager widget is created.
+ *
+ *
+ * After class init, the "translations" variable will contain the compiled
+ * translations to be used to augment a widget's translation
+ * table if they wish to have keyboard traversal on.
+ *
+ ************************************************************************/
+
+static void ClassInitialize()
+{
+ XwRegisterConverters(); /* Register Library Conversion Rtnes */
+
+ XwmanagerClassRec.manager_class.translations =
+ XtParseTranslationTable(defaultTranslations);
+}
+
+
+/************************************************************************
+ *
+ * MgrClassPartInit
+ *
+ * Used by subclasses of manager to inherit class record procedures.
+ *
+ ************************************************************************/
+
+static void MgrClassPartInit(w)
+WidgetClass w;
+
+{
+ XwManagerWidgetClass mw= (XwManagerWidgetClass) w;
+
+ if (mw->manager_class.traversal_handler == XtInheritTraversalProc)
+ mw->manager_class.traversal_handler = (XwTraversalProc) mgr_traversal;
+}
+
+
+
+
+
+
+/************************************************************************
+ *
+ * Initialize
+ * The main widget instance initialization routine.
+ *
+ ************************************************************************/
+
+static void Initialize (request, new)
+ Widget request, new;
+{
+ XwManagerWidget mw = (XwManagerWidget) new;
+ Arg args[1];
+
+
+ if ((mw->manager.layout < XwIGNORE) || (mw->manager.layout > XwSWINDOW))
+ {
+ mw->manager.layout = XwMINIMIZE;
+ XtWarning("Manager: Invalid layout setting.");
+ }
+
+
+ mw -> manager.managed_children = (WidgetList) XtMalloc
+ (XwBLOCK * sizeof(Widget));
+ mw -> manager.num_slots = XwBLOCK;
+ mw -> manager.num_managed_children = 0;
+ mw -> manager.active_child = NULL;
+
+ mw -> composite.children = (WidgetList) XtMalloc
+ (XwBLOCK * sizeof(Widget));
+ mw -> composite.num_slots = XwBLOCK;
+ mw -> composite.num_children = 0;
+/* mw -> composite.num_mapped_children = 0; for R3 */
+
+ mw -> composite.insert_position = (XtOrderProc) _XwInsertOrder;
+
+
+ /* Verify the highlight and tiling resources */
+
+ if (mw -> manager.background_tile != XwBACKGROUND)
+ {
+ XtWarning("Manager: Incorrect background tile.");
+ mw -> manager.background_tile = XwBACKGROUND;
+ }
+
+
+ /* If this widget is requesting traversal then augment its
+ * translation table with some additional events.
+ */
+ if (mw->manager.traversal_on == True)
+ {
+ XtAugmentTranslations((Widget) mw,
+ XwmanagerClassRec.manager_class.translations);
+ mw->core.widget_class->core_class.visible_interest = True;
+ }
+
+}
+
+
+
+
+
+/*********************************************************************
+ *
+ * _XwManagerInsertChild
+ *
+ ********************************************************************/
+
+ /* ARGSUSED */
+void _XwManagerInsertChild(w)
+ Widget w;
+{
+ Cardinal position;
+ Cardinal i;
+ CompositeWidget cw;
+
+ cw = (CompositeWidget) w->core.parent;
+ if (cw -> composite.insert_position != NULL)
+ position = (*cw->composite.insert_position)((Widget)cw);
+ else
+ position = cw->composite.num_children;
+
+
+ /*************************************************
+ * Allocate another block of space if needed
+ *************************************************/
+ if ((cw -> composite.num_children + 1) >
+ cw -> composite.num_slots)
+ {
+ cw -> composite.num_slots += XwBLOCK;
+ cw -> composite.children = (WidgetList)
+ XtRealloc ((caddr_t) cw -> composite.children,
+ (cw -> composite.num_slots * sizeof(Widget)));
+ }
+
+
+ /********************************************************
+ * Ripple children up one space from "position"
+ *********************************************************/
+
+ for (i = cw->composite.num_children; i > position; i--) {
+ cw->composite.children[i] = cw->composite.children[i-1];
+ }
+ cw->composite.children[position] = w;
+ cw->composite.num_children++;
+}
+
+
+/***************************************************************************
+ *
+ * Cardinal
+ * _XwInsertOrder (cw)
+ *
+ ************************************************************************/
+
+Cardinal _XwInsertOrder (cw)
+
+ CompositeWidget cw; /* Composite widget being inserted into */
+{
+ Cardinal position = cw->composite.num_children;
+
+ return (position);
+}
+
+/**********************************************************************
+ *
+ * _XwReManageChildren
+ *
+ * This procedure will be called by the ChangeManged procedure of
+ * each manager. It will reassemble the currently managed children
+ * into the "manager.managed_children" list.
+ *
+ ********************************************************************/
+void _XwReManageChildren(mw)
+ XwManagerWidget mw;
+{
+ int i;
+
+ /* Put "managed children" info together again */
+
+ mw -> manager.num_managed_children = 0;
+ for (i=0; i < mw->composite.num_children; i++)
+ {
+ if (mw -> composite.children[i]->core.managed)
+ {
+ if ((mw -> manager.num_managed_children + 1) >
+ mw -> manager.num_slots)
+ {
+ mw -> manager.num_slots += XwBLOCK;
+ mw -> manager.managed_children = (WidgetList)
+ XtRealloc ((caddr_t) mw -> manager.managed_children,
+ (mw -> manager.num_slots * sizeof(Widget)));
+ }
+ mw -> manager.managed_children
+ [mw -> manager.num_managed_children++] =
+ mw -> composite.children[i];
+ }
+ }
+}
+
+
+/************************************************************************
+ *
+ * SetValues
+ * Perform and updating necessary for a set values call.
+ *
+ ************************************************************************/
+
+static Boolean SetValues (current, request, new, last)
+Widget current, request, new;
+Boolean last;
+
+{
+ Boolean returnFlag = False;
+ Boolean tempTrav, tempVisible, tempSensitive;
+ Boolean tempAnSensitive, tempMapped;
+ XwManagerWidget curmw = (XwManagerWidget) current;
+ XwManagerWidget reqmw = (XwManagerWidget) request;
+ XwManagerWidget newmw = (XwManagerWidget) new;
+ Widget tempoldActive, old_active;
+ XwManagerWidget parent;
+ Boolean traversalIsHere = False;
+ Boolean parentIsMgr = False;
+
+
+ /* Verify correct new values. */
+
+ if (newmw -> manager.traversal_on != True &&
+ newmw -> manager.traversal_on != False)
+ newmw -> manager.traversal_on = curmw -> manager.traversal_on;
+
+
+ /* Process the change in values */
+
+ if ((curmw->core.mapped_when_managed != newmw->core.mapped_when_managed) ||
+ (curmw->core.sensitive != newmw->core.sensitive) ||
+ (curmw->core.ancestor_sensitive != newmw->core.ancestor_sensitive) ||
+ (curmw->core.visible != newmw-> core.visible) ||
+ (curmw->manager.traversal_on != newmw->manager.traversal_on))
+ {
+ returnFlag = TRUE;
+ if (XwFocusIsHere(curmw))
+ {
+ tempTrav= curmw->manager.traversal_on;
+ tempVisible = curmw->core.visible;
+ tempSensitive = curmw->core.sensitive;
+ tempAnSensitive = curmw->core.ancestor_sensitive;
+ tempMapped = curmw->core.mapped_when_managed;
+
+ curmw->manager.traversal_on = newmw->manager.traversal_on;
+ curmw->core.ancestor_sensitive = newmw->core.ancestor_sensitive;
+ curmw->core.sensitive = newmw->core.sensitive;
+ curmw->core.visible = newmw->core.visible;
+ curmw->core.mapped_when_managed = newmw->core.mapped_when_managed;
+
+ XwProcessTraversal (curmw, XwTRAVERSE_HOME, FALSE);
+
+ curmw->manager.traversal_on = tempTrav;
+ curmw->core.visible = tempVisible;
+ curmw->core.sensitive = tempSensitive;
+ curmw->core.ancestor_sensitive = tempAnSensitive;
+ curmw->core.mapped_when_managed = tempMapped;
+ }
+ else
+ {
+ traversalIsHere = False;
+ parentIsMgr = False;
+
+ /* There are special cases if we are the highest Xw mgr widget */
+ if (XtIsSubclass((Widget)(parent = (XwManagerWidget)XtParent(newmw)),
+ XwmanagerWidgetClass))
+ {
+ parentIsMgr = True;
+ if (parent->manager.active_child == (Widget)curmw)
+ traversalIsHere = True;
+ }
+ else if (newmw->manager.active_child)
+ traversalIsHere = True;
+
+ if (traversalIsHere)
+ {
+ /* Clear the active child path, from us down */
+ old_active = newmw->manager.active_child;
+ newmw->manager.active_child = NULL;
+ if (parentIsMgr)
+ parent->manager.active_child = NULL;
+ while (old_active != NULL)
+ {
+ if (!XtIsSubclass(old_active, XwmanagerWidgetClass))
+ old_active = NULL;
+ else
+ {
+ tempoldActive = ((XwManagerWidget)old_active)->manager.
+ active_child;
+ ((XwManagerWidget)old_active)->manager.active_child = NULL;
+ old_active = tempoldActive;
+ }
+ }
+
+ /* Find the top most manager */
+ if (parentIsMgr)
+ {
+ while ((parent->core.parent != NULL) &&
+ (XtIsSubclass(parent->core.parent, XwmanagerWidgetClass)))
+ parent = (XwManagerWidget)parent->core.parent;
+ }
+ else
+ parent = curmw;
+
+ /* Clear the toolkit kbd focus */
+ XtSetKeyboardFocus((Widget)parent, NULL);
+ }
+ }
+ }
+
+
+ if (newmw->manager.layout != curmw->manager.layout)
+ {
+ if ((newmw->manager.layout < XwIGNORE) ||
+ (newmw->manager.layout > XwSWINDOW))
+ {
+ newmw->manager.layout = curmw->manager.layout;
+ XtWarning("Manager: Invalid layout setting.");
+ }
+ else returnFlag = True;
+ }
+
+
+ if (newmw -> manager.highlight_thickness < 0)
+ {
+ XtWarning ("Manager: Invalid highlight thickness.");
+ newmw -> manager.highlight_thickness =
+ curmw -> manager.highlight_thickness;
+ }
+
+
+ if (newmw -> manager.background_tile != XwBACKGROUND)
+ {
+ XtWarning("Manager: Incorrect background tile.");
+ newmw -> manager.background_tile =
+ curmw -> manager.background_tile;
+ }
+
+ /* Set the widget's background tile */
+
+ if (newmw -> manager.background_tile !=
+ curmw -> manager.background_tile ||
+ newmw -> manager.foreground !=
+ curmw -> manager.foreground ||
+ newmw -> core.background_pixel !=
+ curmw -> core.background_pixel)
+ {
+ Mask valueMask;
+ XSetWindowAttributes attributes;
+
+ if (newmw -> manager.background_tile == XwFOREGROUND)
+ {
+ valueMask = CWBackPixel;
+ attributes.background_pixel = newmw -> manager.foreground;
+ }
+ else
+ {
+ valueMask = CWBackPixel;
+ attributes.background_pixel = newmw -> core.background_pixel;
+ }
+
+ if (XtIsRealized ((Widget)newmw))
+ XChangeWindowAttributes (XtDisplay(newmw), newmw -> core.window,
+ valueMask, &attributes);
+
+ returnFlag = TRUE;
+ }
+
+
+ /* Check the geometry in relationship to the highlight thickness */
+
+ if ((request -> core.width == 0) && (current -> core.width == 0))
+ newmw -> core.width += newmw -> manager.highlight_thickness * 2;
+
+ if ((request -> core.height == 0) && (current -> core.height == 0))
+ newmw -> core.height += newmw -> manager.highlight_thickness * 2;
+
+
+ /* If this widget is requesting traversal then augment its
+ * translation table with some additional events.
+ */
+ if ((newmw->manager.traversal_on != curmw->manager.traversal_on) &&
+ (newmw->manager.traversal_on == True))
+ {
+ /* XXX this was a hard bug! where were the XXX's?
+ *
+ * In R2 we could not pass newmw to this toolkit call! But I
+ * have found the bug!!!! In R2 it was a temporary structure (stack)
+ * but now curmw is the temporary one and newmw is real!
+ * I can see why they were worried before. Now there is no worry.
+ * Go ahead and pass newmw!
+ */
+ XtAugmentTranslations((Widget) newmw,
+ XwmanagerClassRec.manager_class.translations);
+ newmw->core.widget_class->core_class.visible_interest = True;
+
+ }
+
+
+ /* Return flag to indicate if redraw is needed. */
+
+ return (returnFlag);
+}
+
+
+
+/************************************************************************
+ *
+ * Enter, FocusIn and Leave Window procs
+ *
+ * These two procedures handle traversal activation and deactivation
+ * for manager widgets. They are invoked directly throught the
+ * the action table of a widget.
+ *
+ ************************************************************************/
+
+void _XwManagerEnter (mw, event)
+XwManagerWidget mw;
+XEvent * event;
+
+{
+ XPoint ul,lr;
+
+ ul.x = ul.y = lr.x = lr.y = 0;
+
+ /* Only the top level manager should invoke a traversal handler*/
+ if (!XtIsSubclass (mw -> core.parent, XwmanagerWidgetClass))
+ {
+ /*
+ * All external entry points into the traversal code must take
+ * care of initializing the traversal list.
+ */
+ _XwInitCheckList();
+
+ (*(((XwManagerWidgetClass) mw -> core.widget_class) ->
+ manager_class.traversal_handler))
+ ((Widget)mw, ul, lr, XwTRAVERSE_CURRENT);
+ }
+
+ return;
+}
+
+
+
+void _XwManagerFocusIn (mw, event)
+XwManagerWidget mw;
+XEvent * event;
+
+{
+ _XwManagerEnter (mw, event);
+ return;
+}
+
+
+void _XwManagerLeave (mw, event)
+XwManagerWidget mw;
+XEvent * event;
+
+{
+ XwManagerWidget tw;
+
+ /* if my parent is NOT a subclass of XwManager then I will assume
+ that I have left the traversal hierarchy. For the time being
+ I will set the focus back to pointer root--I should not have to
+ do this if the window manager people can come to an agreement
+ on conventions for focus change.
+ */
+ if (!XtIsSubclass (mw -> core.parent, XwmanagerWidgetClass))
+ XSetInputFocus (XtDisplay (mw->core.parent),
+ PointerRoot, RevertToNone, CurrentTime);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Find a Traversable Primitive
+ * This functions is used by manager widget's traversal handlers
+ * to determine if there is a primitive in their hierarchy which
+ * can be traversed to.
+ *
+ ************************************************************************/
+
+Boolean _XwFindTraversablePrim (cw)
+CompositeWidget cw;
+
+{
+ register int i;
+ WidgetList wList;
+ Widget w;
+
+ wList = cw -> composite.children;
+
+ for (i = 0; i < cw -> composite.num_children; i++)
+ {
+ w = *wList++;
+
+ if (XtIsSubclass(w, XwmanagerWidgetClass) &&
+ ((((XwManagerWidget)w)->manager.traversal_on == False) ||
+ (w->core.visible == FALSE)))
+ {
+ continue;
+ }
+
+ if (XtIsSubclass (w, compositeWidgetClass) && w -> core.managed == True)
+ {
+ if (_XwFindTraversablePrim ((CompositeWidget) w))
+ {
+ return (True);
+ }
+ }
+
+ else if (XtIsSubclass (w, XwprimitiveWidgetClass))
+ {
+ if (w -> core.sensitive == True &&
+ w -> core.ancestor_sensitive == True &&
+ w -> core.visible == True &&
+ w -> core.managed == True &&
+ w -> core.mapped_when_managed == True &&
+ w -> core.being_destroyed == False &&
+ ((XwPrimitiveWidget) w)->primitive.traversal_type ==
+ XwHIGHLIGHT_TRAVERSAL)
+
+ {
+ return (True);
+ }
+ }
+
+ else /* Check for non - primitive class primitives?? */
+ {
+ }
+ }
+
+ return (False);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Boolean
+ * XwTestTraversability(widget, widgetType)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean XwTestTraversability(widget, widgetType)
+ Widget widget;
+ int * widgetType;
+{
+ Boolean returnFlag=FALSE;
+
+ if (XtIsSubclass (widget, XwprimitiveWidgetClass))
+ {
+ *widgetType = XwPRIMITIVE;
+ if (((XwPrimitiveWidget) widget)->primitive.traversal_type ==
+ XwHIGHLIGHT_TRAVERSAL)
+ returnFlag = TRUE;
+ }
+ else
+ if (XtIsSubclass (widget, XwmanagerWidgetClass))
+ {
+ *widgetType = XwMANAGER;
+ if (((XwManagerWidget)widget) -> manager.traversal_on)
+ returnFlag = TRUE;
+ }
+ else
+ *widgetType = 0;
+
+
+ if (widget-> core.sensitive != True ||
+ widget-> core.ancestor_sensitive != True ||
+ widget-> core.visible != True ||
+ widget-> core.managed != True ||
+ widget-> core.mapped_when_managed != True ||
+ widget-> core.being_destroyed == True)
+
+ returnFlag = FALSE;
+
+
+ return(returnFlag);
+}
+
+
+static Boolean XwFocusIsHere(mw)
+
+ XwManagerWidget mw;
+{
+ while (1)
+ {
+ if (mw->manager.active_child == NULL) return(FALSE);
+ if (XtIsSubclass(mw->manager.active_child, XwmanagerWidgetClass))
+ mw= (XwManagerWidget)mw->manager.active_child;
+ else
+ if (XtIsSubclass(mw->manager.active_child, XwprimitiveWidgetClass))
+ {
+ if (((XwPrimitiveWidget)mw->manager.active_child)
+ ->primitive.I_have_traversal) return(TRUE);
+ else return(FALSE);
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * MgrDestroy (w)
+ *
+ * Description:
+ * -----------
+ * Free up space allocated to track managed children.
+ *
+ * Inputs:
+ * ------
+ * w = manager subclass to be destroyed.
+ *
+ *
+ *************************************<->***********************************/
+
+static void MgrDestroy(w)
+ XwManagerWidget w;
+{
+ XwManagerWidget parent;
+
+ /*
+ * If we are in the traversal focus path, then we need to clean
+ * things up.
+ */
+ if (XwFocusIsHere(w))
+ XwProcessTraversal(w, XwTRAVERSE_HOME, FALSE);
+ else if ((XtIsSubclass((Widget)(parent = (XwManagerWidget)XtParent(w)),
+ XwmanagerWidgetClass)) &&
+ (parent->manager.active_child == (Widget)w))
+ {
+ parent->manager.active_child = NULL;
+ }
+ XtRemoveCallbacks ((Widget)w, XtNnextTop, w -> manager.next_top);
+ XtFree((char *) w->manager.managed_children);
+}
+
+
+/************************************************************************
+ *
+ * Visibility
+ * Track whether a widget is visible.
+ *
+ ***********************************************************************/
+void _XwManagerVisibility (mw, event)
+ XwManagerWidget mw;
+ XEvent * event;
+{
+ XVisibilityEvent * vEvent = (XVisibilityEvent *)event;
+
+ if (vEvent->state == VisibilityFullyObscured)
+ {
+ mw->core.visible = False;
+ if (XwFocusIsHere(mw))
+ XwProcessTraversal (mw, XwTRAVERSE_HOME, FALSE);
+ }
+ else
+ mw->core.visible = True;
+
+
+}
+
+
+/************************************************************************
+ *
+ * Unmap
+ * Track whether a widget is visible.
+ *
+ ***********************************************************************/
+void _XwManagerUnmap (mw, event)
+ XwManagerWidget mw;
+ XEvent * event;
+{
+ mw->core.visible = False;
+ if (XwFocusIsHere(mw))
+ XwProcessTraversal (mw, XwTRAVERSE_HOME, FALSE);
+
+}
diff --git a/Xw/MapEvents.c b/Xw/MapEvents.c
new file mode 100644
index 0000000..e0347a8
--- /dev/null
+++ b/Xw/MapEvents.c
@@ -0,0 +1,948 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MapEvents.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Menu Manager Support Routines
+ **
+ ** This file contains a series of support routines, used by
+ ** the menu manager meta-class and any of its subclasses,
+ ** to convert an event string into an internal format. The
+ ** internal format may then be used to compare against real
+ ** X events. These routines are capable of handling a subset
+ ** of the string formats supported by the translation manager.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <X11/Xatom.h>
+
+
+static Boolean ParseImmed();
+static Boolean ParseKeySym();
+
+
+
+typedef struct {
+ char * event;
+ XrmQuark signature;
+ unsigned int eventType;
+ Boolean (*parseProc)();
+ unsigned int closure;
+} EventKey;
+
+static EventKey modifierStrings[] = {
+
+ /* Modifier, Quark, Mask */
+
+ {"None", NULLQUARK, 0, NULL, None},
+ {"Shift", NULLQUARK, 0, NULL, ShiftMask},
+ {"Lock", NULLQUARK, 0, NULL, LockMask},
+ {"Ctrl", NULLQUARK, 0, NULL, ControlMask},
+ {"Mod1", NULLQUARK, 0, NULL, Mod1Mask},
+ {"Mod2", NULLQUARK, 0, NULL, Mod2Mask},
+ {"Mod3", NULLQUARK, 0, NULL, Mod3Mask},
+ {"Mod4", NULLQUARK, 0, NULL, Mod4Mask},
+ {"Mod5", NULLQUARK, 0, NULL, Mod5Mask},
+ {"Meta", NULLQUARK, 0, NULL, Mod1Mask},
+ {NULL, NULLQUARK, 0, NULL, None},
+};
+
+
+static EventKey buttonEvents[] = {
+
+/* Event Name, Quark, Event Type, DetailProc Closure */
+
+{"Btn1Down", NULLQUARK, ButtonPress, ParseImmed, Button1},
+{"Btn2Down", NULLQUARK, ButtonPress, ParseImmed, Button2},
+{"Btn3Down", NULLQUARK, ButtonPress, ParseImmed, Button3},
+{"Btn4Down", NULLQUARK, ButtonPress, ParseImmed, Button4},
+{"Btn5Down", NULLQUARK, ButtonPress, ParseImmed, Button5},
+{"Btn1Up", NULLQUARK, ButtonRelease, ParseImmed, Button1},
+{"Btn2Up", NULLQUARK, ButtonRelease, ParseImmed, Button2},
+{"Btn3Up", NULLQUARK, ButtonRelease, ParseImmed, Button3},
+{"Btn4Up", NULLQUARK, ButtonRelease, ParseImmed, Button4},
+{"Btn5Up", NULLQUARK, ButtonRelease, ParseImmed, Button5},
+{ NULL, NULLQUARK, 0, NULL, None}};
+
+
+static EventKey keyEvents[] = {
+
+/* Event Name, Quark, Event Type, DetailProc Closure */
+
+{"KeyPress", NULLQUARK, KeyPress, ParseKeySym, None},
+{"Key", NULLQUARK, KeyPress, ParseKeySym, None},
+{"KeyDown", NULLQUARK, KeyPress, ParseKeySym, None},
+{"KeyUp", NULLQUARK, KeyRelease, ParseKeySym, None},
+{"KeyRelease", NULLQUARK, KeyRelease, ParseKeySym, None},
+{ NULL, NULLQUARK, 0, NULL, None}};
+
+
+static unsigned int buttonModifierMasks[] = {
+ 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
+};
+
+static initialized = FALSE;
+
+
+
+/*************************************<->*************************************
+ *
+ * Numeric convertion routines
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static unsigned int StrToHex(str)
+ String str;
+{
+ register char c;
+ register int val = 0;
+
+ while (c = *str) {
+ if ('0' <= c && c <= '9') val = val*16+c-'0';
+ else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10;
+ else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10;
+ else return -1;
+ str++;
+ }
+
+ return val;
+}
+
+static unsigned int StrToOct(str)
+ String str;
+{
+ register char c;
+ register int val = 0;
+
+ while (c = *str) {
+ if ('0' <= c && c <= '7') val = val*8+c-'0'; else return -1;
+ str++;
+ }
+
+ return val;
+}
+
+static unsigned int StrToNum(str)
+ String str;
+{
+ register char c;
+ register int val = 0;
+
+ if (*str == '0') {
+ str++;
+ if (*str == 'x' || *str == 'X') return StrToHex(++str);
+ else return StrToOct(str);
+ }
+
+ while (c = *str) {
+ if ('0' <= c && c <= '9') val = val*10+c-'0';
+ else return -1;
+ str++;
+ }
+
+ return val;
+}
+
+
+/*************************************<->*************************************
+ *
+ * FillInQuarks (parameters)
+ *
+ * Description:
+ * -----------
+ * Converts each string entry in the modifier/event tables to a
+ * quark, thus facilitating faster comparisons.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void FillInQuarks (table)
+
+ EventKey * table;
+
+{
+ register int i;
+
+ for (i=0; table[i].event; i++)
+ table[i].signature = XrmStringToQuark(table[i].event);
+}
+
+
+/*************************************<->*************************************
+ *
+ * LookupModifier (parameters)
+ *
+ * Description:
+ * -----------
+ * Compare the passed in string to the list of valid modifiers.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean LookupModifier (name, valueP)
+
+ String name;
+ unsigned int *valueP;
+
+{
+ register int i;
+ register XrmQuark signature = XrmStringToQuark(name);
+
+ for (i=0; modifierStrings[i].event != NULL; i++)
+ if (modifierStrings[i].signature == signature) {
+ *valueP = modifierStrings[i].closure;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ScanAlphanumeric (parameters)
+ *
+ * Description:
+ * -----------
+ * Scan string until a non-alphanumeric character is encountered.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static String ScanAlphanumeric (str)
+
+ register String str;
+
+{
+ while (
+ ('A' <= *str && *str <= 'Z') || ('a' <= *str && *str <= 'z')
+ || ('0' <= *str && *str <= '9')) str++;
+ return str;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ScanWhitespace (parameters)
+ *
+ * Description:
+ * -----------
+ * Scan the string, skipping over all white space characters.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static String ScanWhitespace(str)
+ register String str;
+{
+ while (*str == ' ' || *str == '\t') str++;
+ return str;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ParseImmed (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean ParseImmed (str, closure, detail)
+
+ String str;
+ unsigned int closure;
+ unsigned int * detail;
+
+{
+ *detail = closure;
+ return (TRUE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * ParseKeySym (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean ParseKeySym (str, closure, detail)
+
+ String str;
+ unsigned int closure;
+ unsigned int * detail;
+
+{
+ char keySymName[100], *start;
+
+ str = ScanWhitespace(str);
+
+ if (*str == '\\') {
+ str++;
+ keySymName[0] = *str;
+ if (*str != '\0' && *str != '\n') str++;
+ keySymName[1] = '\0';
+ *detail = XStringToKeysym(keySymName);
+ } else if (*str == ',' || *str == ':') {
+ /* No detail; return a failure */
+ *detail = NoSymbol;
+ return (FALSE);
+ } else {
+ start = str;
+ while (
+ *str != ','
+ && *str != ':'
+ && *str != ' '
+ && *str != '\t'
+ && *str != '\n'
+ && *str != '\0') str++;
+ (void) strncpy(keySymName, start, str-start);
+ keySymName[str-start] = '\0';
+ *detail = XStringToKeysym(keySymName);
+ }
+
+ if (*detail == NoSymbol)
+ {
+ if (( '0' <= keySymName[0]) && (keySymName[0] <= '9'))
+ {
+ *detail = StrToNum(keySymName);
+ return (TRUE);
+ }
+ return (FALSE);
+ }
+ else
+ return (TRUE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * ParseModifiers (parameters)
+ *
+ * Description:
+ * -----------
+ * Parse the string, extracting all modifier specifications.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static String ParseModifiers(str, modifiers, status)
+
+ register String str;
+ unsigned int * modifiers;
+ Boolean * status;
+
+{
+ register String start;
+ char modStr[100];
+ Boolean notFlag, exclusive;
+ unsigned int maskBit;
+
+ /* Initially assume all is going to go well */
+ *status = TRUE;
+ *modifiers = 0;
+
+ /* Attempt to parse the first button modifier */
+ str = ScanWhitespace(str);
+ start = str;
+ str = ScanAlphanumeric(str);
+ if (start != str) {
+ (void) strncpy(modStr, start, str-start);
+ modStr[str-start] = '\0';
+ if (LookupModifier(modStr, &maskBit))
+ {
+ if (maskBit== None) {
+ *modifiers = 0;
+ str = ScanWhitespace(str);
+ return str;
+ }
+ }
+ str = start;
+ }
+
+
+ /* Keep parsing modifiers, until the event specifier is encountered */
+ while ((*str != '<') && (*str != '\0')) {
+ if (*str == '~') {
+ notFlag = TRUE;
+ str++;
+ } else
+ notFlag = FALSE;
+
+ start = str;
+ str = ScanAlphanumeric(str);
+ if (start == str) {
+ /* ERROR: Modifier or '<' missing */
+ *status = FALSE;
+ return str;
+ }
+ (void) strncpy(modStr, start, str-start);
+ modStr[str-start] = '\0';
+
+ if (!LookupModifier(modStr, &maskBit))
+ {
+ /* Unknown modifier name */
+ *status = FALSE;
+ return str;
+ }
+
+ if (notFlag)
+ *modifiers &= ~maskBit;
+ else
+ *modifiers |= maskBit;
+ str = ScanWhitespace(str);
+ }
+
+ return str;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ParseEventType (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static String ParseEventType(str, table, eventType, index, status)
+
+ register String str;
+ EventKey * table;
+ unsigned int * eventType;
+ Cardinal * index;
+ Boolean * status;
+
+{
+ String start = str;
+ char eventTypeStr[100];
+ register Cardinal i;
+ register XrmQuark signature;
+
+ /* Parse out the event string */
+ str = ScanAlphanumeric(str);
+ (void) strncpy(eventTypeStr, start, str-start);
+ eventTypeStr[str-start] = '\0';
+
+ /* Attempt to match the parsed event against our supported event set */
+ signature = XrmStringToQuark(eventTypeStr);
+ for (i = 0; table[i].signature != NULLQUARK; i++)
+ if (table[i].signature == signature)
+ {
+ *index = i;
+ *eventType = table[*index].eventType;
+
+ *status = TRUE;
+ return str;
+ }
+
+ /* Unknown event specified */
+ *status = FALSE;
+ return (str);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMapEvent (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean
+_XwMapEvent (str, table, eventType, detail, modifiers)
+
+ register String str;
+ EventKey * table;
+ unsigned int * eventType;
+ unsigned int * detail;
+ unsigned int * modifiers;
+
+{
+ Cardinal index;
+ Boolean status;
+
+ /* Initialize, if first time called */
+ if (!initialized)
+ {
+ initialized = TRUE;
+ FillInQuarks (buttonEvents);
+ FillInQuarks (modifierStrings);
+ FillInQuarks (keyEvents);
+ }
+
+ /* Parse the modifiers */
+ str = ParseModifiers(str, modifiers, &status);
+ if ( status == FALSE || *str != '<')
+ return (FALSE);
+ else
+ str++;
+
+ /* Parse the event type and detail */
+ str = ParseEventType(str, table, eventType, &index, &status);
+ if (status == FALSE || *str != '>')
+ return (FALSE);
+ else
+ str++;
+
+ /* Save the detail */
+ return ((*(table[index].parseProc))(str, table[index].closure, detail));
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMapBtnEvent (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwMapBtnEvent (str, eventType, button, modifiers)
+
+ register String str;
+ unsigned int * eventType;
+ unsigned int * button;
+ unsigned int * modifiers;
+
+{
+ if (_XwMapEvent (str, buttonEvents, eventType, button, modifiers) == FALSE)
+ return (FALSE);
+
+ /*
+ * The following is a fix for an X11 deficiency in regards to
+ * modifiers in grabs.
+ */
+ if (*eventType == ButtonRelease)
+ {
+ /* the button that is going up will always be in the modifiers... */
+ *modifiers |= buttonModifierMasks[*button];
+ }
+
+ return (TRUE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMapKeyEvent (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwMapKeyEvent (str, eventType, key, modifiers)
+
+ register String str;
+ unsigned int * eventType;
+ unsigned int * key;
+ unsigned int * modifiers;
+
+{
+ return (_XwMapEvent (str, keyEvents, eventType, key, modifiers));
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMatchBtnEvent (parameters)
+ *
+ * Description:
+ * -----------
+ * Compare the passed in event to the event described by the parameter
+ * list.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwMatchBtnEvent (event, eventType, button, modifiers)
+
+ XButtonEvent * event;
+ unsigned int eventType;
+ unsigned int button;
+ unsigned int modifiers;
+
+{
+ if ((event->type == eventType) &&
+ (event->button == button) &&
+ (event->state == modifiers))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMatchKeyEvent (parameters)
+ *
+ * Description:
+ * -----------
+ * Compare the passed in event to the event described by the parameter
+ * list.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwMatchKeyEvent (event, eventType, key, modifiers)
+
+ XKeyEvent * event;
+ unsigned int eventType;
+ unsigned int key;
+ unsigned int modifiers;
+
+{
+ if ((event->type == eventType) &&
+ (event->keycode == key) &&
+ (event->state == modifiers))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwValidModifier (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwValidModifier (str)
+
+ register String str;
+
+{
+ unsigned int modifiers;
+ Boolean status;
+
+ /*
+ * Scan the string for a valid set of event modifiers; valid includes
+ * a NULL string, an empty string, or all white space. A NULL is
+ * inserted into the string at the end of the modifiers.
+ */
+
+ if ((str == NULL) || (*str == '\0'))
+ return (TRUE);
+
+ str = ParseModifiers (str, &modifiers, &status);
+
+ if (status == TRUE)
+ *str = '\0';
+
+ return (status);
+}
+
+/*************************************<->*************************************
+ *
+ * _XwMapToHex (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+String _XwMapToHex (menuMgrId)
+
+ unsigned long menuMgrId;
+
+{
+ static char buffer[(sizeof(Widget) << 1) + 1];
+ int i;
+ char digit;
+
+ /* Convert the menu manager widget id into a hex string */
+ for (i = (sizeof(Widget) << 1) - 1; i >= 0; i--)
+ {
+ digit = (char) menuMgrId & 0x0F;
+ buffer[i] = (digit < 10) ? (digit + '0') : (digit - 10 + 'A');
+ menuMgrId = menuMgrId >> 4;
+ }
+
+ buffer[sizeof(Widget) << 1] = '\0';
+ return (buffer);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMapFromHex (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+unsigned long _XwMapFromHex (str)
+
+ String str;
+
+{
+ unsigned long id = 0;
+ int digit;
+
+ /* Convert the hex string into a menu manager widget id */
+ while (str && *str)
+ {
+ digit = (int) ((*str >= '0') && (*str <= '9')) ? (*str - '0') :
+ (*str + 10 - 'A');
+ id = (id * 16) + digit;
+ str++;
+ }
+
+ return (id);
+}
diff --git a/Xw/MenuBtn.c b/Xw/MenuBtn.c
new file mode 100644
index 0000000..3861eaf
--- /dev/null
+++ b/Xw/MenuBtn.c
@@ -0,0 +1,2570 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MenuBtn.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains code for primitive widget class: MenuButton
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/*
+ *#define DEBUG TRUE
+ */
+#undef NLS16
+
+/*
+ * Include files & Static Routine Definitions
+ */
+#include <string.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/keysymdef.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/MenuBtnP.h>
+#include <Xw/MenuBtn.h>
+
+#ifdef NLS16
+#include <X11/XHPlib.h>
+#endif
+
+#ifndef XtRWidget
+#define XtRWidget XtRPointer
+#endif
+
+static void Redisplay();
+static Boolean SetValues();
+static void ClassPartInitialize();
+static void Inverted();
+static void NonInverted();
+static void Select();
+static void Enter();
+static void Leave();
+static void Moved();
+static void Initialize();
+static void Destroy();
+static void Realize();
+static void Resize();
+static void IdealWidth();
+static void Unhighlight();
+static void Highlight();
+static void SetCascadeEnabled();
+static void ClearCascadeEnabled();
+static void EnterParentsWindow();
+static void SetTraversalType();
+static void TraverseLeft();
+static void TraverseRight();
+static void TraverseNext();
+static void TraversePrev();
+static void TraverseHome();
+static void TraverseUp();
+static void TraverseDown();
+static void TraverseNextTop();
+static void Unmap();
+static void Visibility();
+Boolean _XwUniqueEvent();
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: default translation table for class: MenuButton
+ * -----------
+ *
+ * Matches events with string descriptors for internal routines.
+ *
+ *************************************<->***********************************/
+
+
+static char defaultTranslations[] =
+ "<Btn1Down>: select()\n\
+ <Visible>: visibility()\n\
+ <Unmap>: unmap()\n\
+ <EnterWindow>: enter()\n\
+ <LeaveWindow>: leave()\n\
+ <Motion>: moved()\n\
+ <Key>Select: select()\n\
+ <Key>Left: traverseLeft()\n\
+ <Key>Up: traverseUp()\n\
+ <Key>Right: traverseRight()\n\
+ <Key>Down: traverseDown()\n\
+ <Key>Prior: traversePrev()\n\
+ <Key>Next: traverseNext()\n\
+ <Key>KP_Enter: traverseNextTop()\n\
+ <Key>Home: traverseHome()";
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: action list for class: MenuButton
+ * -----------
+ *
+ * Matches string descriptors with internal routines.
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ {"select", (XtActionProc) Select},
+ {"visibility", (XtActionProc) Visibility},
+ {"unmap", (XtActionProc) Unmap},
+ {"enter", (XtActionProc) Enter},
+ {"leave", (XtActionProc) Leave},
+ {"moved", (XtActionProc) Moved},
+ {"traverseLeft", (XtActionProc) TraverseLeft },
+ {"traverseRight", (XtActionProc) TraverseRight },
+ {"traverseNext", (XtActionProc) TraverseNext },
+ {"traversePrev", (XtActionProc) TraversePrev },
+ {"traverseHome", (XtActionProc) TraverseHome },
+ {"traverseUp", (XtActionProc) TraverseUp },
+ {"traverseDown", (XtActionProc) TraverseDown },
+ {"traverseNextTop", (XtActionProc) TraverseNextTop },
+};
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: resource list for class: MenuButton
+ * -----------
+ *
+ * Provides default resource settings for instances of this class.
+ * To get full set of default settings, examine resouce list of super
+ * classes of this class.
+ *
+ *************************************<->***********************************/
+
+static XtResource resources[] =
+{
+ {
+ XtNborderWidth, XtCBorderWidth,XtRDimension, sizeof(Dimension),
+ XtOffset(XwMenuButtonWidget, core.border_width),
+ XtRString, "0"
+ },
+
+ {
+ XtNlabelType, XtCLabelType, XtRLabelType, sizeof(int),
+ XtOffset(XwMenuButtonWidget, menubutton.labelType),
+ XtRString, "string"
+ },
+
+ {
+ XtNlabelImage, XtCLabelImage, XtRImage, sizeof(XImage *),
+ XtOffset(XwMenuButtonWidget, menubutton.labelImage),
+ XtRImage, NULL
+ },
+
+ {
+ XtNrectColor, XtCRectColor, XtRPixel, sizeof(Pixel),
+ XtOffset(XwMenuButtonWidget, menubutton.rectColor),
+ XtRString, "white"
+ },
+
+ {
+ XtNrectStipple, XtCRectStipple, XtRPixmap, sizeof(Pixmap),
+ XtOffset(XwMenuButtonWidget, menubutton.rectStipple),
+ XtRPixmap, NULL
+ },
+
+ {
+ XtNcascadeImage, XtCCascadeImage, XtRImage, sizeof(XImage *),
+ XtOffset(XwMenuButtonWidget, menubutton.cascadeImage),
+ XtRImage, NULL
+ },
+
+ {
+ XtNmarkImage, XtCMarkImage, XtRImage, sizeof(XImage *),
+ XtOffset(XwMenuButtonWidget, menubutton.markImage),
+ XtRImage, NULL
+ },
+
+ {
+ XtNsetMark, XtCSetMark, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwMenuButtonWidget, menubutton.setMark),
+ XtRString, "FALSE"
+ },
+
+ {
+ XtNnoPad, XtCNoPad, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwMenuButtonWidget, menubutton.noPad),
+ XtRString, "FALSE"
+ },
+
+ {
+ XtNcascadeOn, XtCCascadeOn, XtRWidget, sizeof(Widget),
+ XtOffset(XwMenuButtonWidget, menubutton.cascadeOn),
+ XtRWidget, NULL
+ },
+
+ {
+ XtNkbdAccelerator, XtCKbdAccelerator, XtRString, sizeof(caddr_t),
+ XtOffset(XwMenuButtonWidget, menubutton.accelerator),
+ XtRString, NULL
+ },
+
+ {
+ XtNhint, XtCHint, XtRString, sizeof(caddr_t),
+ XtOffset(XwMenuButtonWidget, menubutton.hint),
+ XtRString, NULL
+ },
+
+ {
+ XtNhintProc, XtCHintProc, XtRFunction, sizeof(XwStrProc),
+ XtOffset(XwMenuButtonWidget, menubutton.hintProc),
+ XtRFunction, NULL
+ },
+
+ {
+ XtNmgrOverrideMnemonic, XtCMgrOverrideMnemonic, XtRBoolean,
+ sizeof(Boolean),
+ XtOffset(XwMenuButtonWidget, menubutton.mgrOverrideMnemonic),
+ XtRString, "FALSE"
+ },
+
+ {
+ XtNmnemonic, XtCMnemonic, XtRString, sizeof(caddr_t),
+ XtOffset(XwMenuButtonWidget, menubutton.mnemonic),
+ XtRString, NULL
+ },
+
+ {
+ XtNhighlightStyle, XtCHighlightStyle, XtRHighlightStyle, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.highlight_style),
+ XtRString, "widget_defined"
+ },
+
+ {
+ XtNcascadeSelect, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset (XwMenuButtonWidget, menubutton.cascadeSelect),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNcascadeUnselect, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset (XwMenuButtonWidget, menubutton.cascadeUnselect),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNmenuMgrId, XtCMenuMgrId, XtRWidget, sizeof(Widget),
+ XtOffset (XwMenuButtonWidget, menubutton.menuMgr),
+ XtRWidget, NULL
+ },
+};
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: global class record for instances of class: MenuButton
+ * -----------
+ *
+ * Defines default field settings for this class record.
+ *
+ *************************************<->***********************************/
+
+XwMenuButtonClassRec XwmenubuttonClassRec =
+{
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwbuttonClassRec,
+ /* class_name */ "XwMenuButton",
+ /* widget_size */ sizeof(XwMenuButtonRec),
+ /* class_initialize */ NULL,
+ /* class_part_init */ ClassPartInitialize,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actionsList,
+ /* num_actions */ XtNumber(actionsList),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE, /* FIX ME LATER */
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* cb List */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ NULL, /* FIX ME LATER */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ {
+ /* primitive class fields */
+ /* border_highlight */ Inverted,
+ /* border_unhighlight */ NonInverted,
+ /* select_proc */ Select,
+ /* release_proc */ NULL,
+ /* toggle_proc */ NULL,
+ /* translations */ NULL,
+ },
+ {
+ /* button class fields */ 0,
+ },
+ {
+ /* menubutton class fields */
+ /* ideal width proc */ IdealWidth,
+ /* unhighlight proc */ Unhighlight,
+ /* highlight proc */ Highlight,
+ /* cascade selected */ SetCascadeEnabled,
+ /* cascade unselected*/ ClearCascadeEnabled,
+ /* enter parents win */ EnterParentsWindow,
+ /* cascadeSelectProc */ NULL,
+ /* cascadeUnselectProc */ NULL,
+ /* setTraversalType */ SetTraversalType
+ }
+};
+WidgetClass XwmenubuttonWidgetClass = (WidgetClass)&XwmenubuttonClassRec;
+WidgetClass XwmenuButtonWidgetClass = (WidgetClass)&XwmenubuttonClassRec;
+
+
+/*************************************<->*************************************
+ *
+ * SetCascadeEnabled (mbutton)
+ *
+ * Description:
+ * -----------
+ * This routine is called by the Menu Manager to force the menubutton into
+ * thinking that the cascade select callbacks have been recently called.
+ *
+ * Inputs:
+ * ------
+ * mbutton = this menubutton widget
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+static void SetCascadeEnabled (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ mbutton->menubutton.cascadeEnabled = TRUE;
+}
+
+/*************************************<->*************************************
+ *
+ * ClearCascadeEnabled (mbutton)
+ *
+ * Description:
+ * -----------
+ * This routine is called by the Menu Manager to force the menubutton into
+ * thinking that the cascade unselect callbacks have been recently called.
+ *
+ * Inputs:
+ * ------
+ * mbutton = this menubutton widget
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+static void ClearCascadeEnabled (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ mbutton->menubutton.cascadeEnabled = FALSE;
+}
+
+/*************************************<->*************************************
+ *
+ * ClassPartInitialize (parameters)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassPartInitialize (wc)
+
+ register XwMenuButtonWidgetClass wc;
+
+{
+ register XwMenuButtonWidgetClass super =
+ (XwMenuButtonWidgetClass) wc->core_class.superclass;
+
+ if (wc->menubutton_class.idealWidthProc == XtInheritIdealWidthProc)
+ wc->menubutton_class.idealWidthProc =
+ super->menubutton_class.idealWidthProc;
+
+ if (wc->menubutton_class.unhighlightProc == XtInheritUnhighlightProc)
+ wc->menubutton_class.unhighlightProc =
+ super->menubutton_class.unhighlightProc;
+
+ if (wc->menubutton_class.highlightProc == XtInheritHighlightProc)
+ wc->menubutton_class.highlightProc =
+ super->menubutton_class.highlightProc;
+
+ if (wc->menubutton_class.setCascadeProc == XtInheritSetCascadeProc)
+ wc->menubutton_class.setCascadeProc =
+ super->menubutton_class.setCascadeProc;
+
+ if (wc->menubutton_class.clearCascadeProc == XtInheritClearCascadeProc)
+ wc->menubutton_class.clearCascadeProc =
+ super->menubutton_class.clearCascadeProc;
+
+ if (wc->menubutton_class.enterParentProc == XtInheritEnterParentProc)
+ wc->menubutton_class.enterParentProc =
+ super->menubutton_class.enterParentProc;
+
+ if (wc->menubutton_class.cascadeSelectProc == XtInheritCascadeSelectProc)
+ wc->menubutton_class.cascadeSelectProc =
+ super->menubutton_class.cascadeSelectProc;
+
+ if (wc->menubutton_class.cascadeUnselectProc == XtInheritCascadeUnselectProc)
+ wc->menubutton_class.cascadeUnselectProc =
+ super->menubutton_class.cascadeUnselectProc;
+
+ if (wc->menubutton_class.setTraversalType == XtInheritSetTraversalTypeProc)
+ wc->menubutton_class.setTraversalType =
+ super->menubutton_class.setTraversalType;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ComputeHeight (mbutton)
+ *
+ * Description:
+ * -----------
+ * Returns the ideal height of the menubutton by considering whether the
+ * label is text or image.
+ *
+ * Inputs:
+ * ------
+ * mbutton = widget to compute height of
+ *
+ * Outputs:
+ * -------
+ * returns the ideal height of mbutton
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Dimension ComputeHeight(mbutton)
+XwMenuButtonWidget mbutton;
+{
+ Dimension max = 0;
+
+ if (mbutton->menubutton.labelType == XwSTRING)
+ max = mbutton->button.label_height;
+
+ if ((mbutton->menubutton.labelType == XwIMAGE) &&
+ (mbutton->menubutton.labelImage->height > max))
+ max = mbutton->menubutton.labelImage->height;
+
+ if (mbutton->menubutton.markImage->height > max)
+ max = mbutton->menubutton.markImage->height;
+
+ if (mbutton->menubutton.cascadeImage->height > max)
+ max = mbutton->menubutton.cascadeImage->height;
+
+ return (max + 2 * mbutton->button.internal_height +
+ 2 * mbutton->primitive.highlight_thickness);
+
+}
+
+/*************************************<->*************************************
+ *
+ * ComputeVertical
+ *
+ * Description:
+ * -----------
+ * Computes the values for mark_y, label_y and cascade_y.
+ *
+ * Inputs:
+ * ------
+ * mbutton = menubutton to compute and set values for
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ComputeVertical (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ Dimension string_y;
+
+ string_y = (mbutton->core.height - mbutton->button.label_height)/2 +
+ mbutton->button.font->max_bounds.ascent;
+
+ if (mbutton->menubutton.labelType == XwSTRING)
+ mbutton->button.label_y = string_y;
+
+ else if (mbutton->menubutton.labelImage)
+ mbutton->button.label_y = (mbutton->core.height -
+ mbutton->menubutton.labelImage->height) / 2;
+
+ mbutton->menubutton.mark_y = (mbutton->core.height -
+ mbutton->menubutton.markImage->height)/2;
+
+ mbutton->menubutton.cascade_y = (mbutton->core.height -
+ mbutton->menubutton.cascadeImage->height)/2;
+
+}
+
+/*************************************<->*************************************
+ *
+ * SetUnderline (mbutton)
+ *
+ * Description:
+ * -----------
+ * Set the underline parameters underline_width and underline_y.
+ *
+ * Inputs:
+ * ------
+ * mbutton = menubutton
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XTextWidth ()
+ * XGetFontProperty ()
+ *
+ *************************************<->***********************************/
+
+static void SetUnderline (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ int i, temp;
+
+ if ((!mbutton->menubutton.mgrOverrideMnemonic) &&
+ (mbutton->menubutton.mnemonic))
+ {
+ mbutton->menubutton.mnemonicMatch = FALSE;
+ temp = XwStrlen (mbutton->button.label);
+
+ for (i = 0; i < temp;)
+ {
+#ifdef NLS16
+ if (XHPIs16bitCharacter (mbutton->button.font->fid,
+ mbutton->button.label[i],
+ mbutton->button.label[i+1]) == NULL)
+ {
+#endif
+ if (*mbutton->menubutton.mnemonic ==
+ (char) mbutton->button.label[i])
+ {
+ unsigned long bval;
+
+ mbutton->menubutton.mnemonicMatch = TRUE;
+ mbutton->menubutton.underline_width =
+ XTextWidth(mbutton->button.font, mbutton->button.label+i, 1);
+
+ mbutton->menubutton.underline_x =
+ XTextWidth(mbutton->button.font, mbutton->button.label, i) +
+ mbutton->primitive.highlight_thickness +
+ 4 * mbutton->button.internal_width + XwMARKWIDTH;
+
+ if (XGetFontProperty(mbutton->button.font, XA_UNDERLINE_POSITION,
+ &bval) == 0)
+ mbutton->menubutton.underline_y =
+ mbutton->button.font->descent +1;
+ else
+ mbutton->menubutton.underline_y = (Dimension) bval;
+
+ mbutton->menubutton.underline_y += mbutton->button.label_y;
+ break;
+ }
+ else
+ i += 1;
+#ifdef NLS16
+ }
+ else
+ i += 2;
+#endif
+ }
+ }
+ else
+ mbutton->menubutton.mnemonicMatch = FALSE;
+}
+
+/*************************************<->*************************************
+ *
+ * GetGC (mbutton)
+ *
+ * Description:
+ * -----------
+ * Creates image_GC
+ *
+ * Inputs:
+ * ------
+ * mbutton = menubutton
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtGetGC()
+ *
+ *************************************<->***********************************/
+
+static void GetGC (mbutton)
+XwMenuButtonWidget mbutton;
+{
+
+ XGCValues values;
+ unsigned long dostipple = 0;
+
+ values.function = GXcopy;
+ values.plane_mask = AllPlanes;
+ values.subwindow_mode = ClipByChildren;
+ values.clip_x_origin = 0;
+ values.clip_y_origin = 0;
+ values.clip_mask = None;
+ values.fill_style = FillSolid;
+ values.graphics_exposures = True;
+
+ values.foreground = mbutton->primitive.foreground;
+ values.background = mbutton->core.background_pixel;
+
+ mbutton->menubutton.defPixmap_GC =
+ XtGetGC ((Widget) mbutton,
+ GCFunction | GCPlaneMask | GCSubwindowMode |
+ GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
+ GCClipMask | GCForeground | GCBackground,
+ &values);
+
+ values.foreground = mbutton->core.background_pixel;
+ values.background = mbutton->primitive.foreground;
+
+ mbutton->menubutton.invertPixmap_GC =
+ XtGetGC ((Widget) mbutton,
+ GCFunction | GCPlaneMask | GCSubwindowMode |
+ GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
+ GCClipMask | GCForeground | GCBackground,
+ &values);
+
+ values.background = mbutton->core.background_pixel;
+ values.stipple = mbutton->menubutton.rectStipple;
+ if (values.stipple != (Pixmap)NULL) {
+ dostipple = GCStipple;
+ values.fill_style = FillOpaqueStippled;
+ values.foreground = mbutton->primitive.foreground;
+ }
+ else
+ values.foreground = mbutton->menubutton.rectColor;
+
+ mbutton->menubutton.rect_GC =
+ XtGetGC ((Widget) mbutton,
+ GCFunction | GCPlaneMask | GCSubwindowMode |
+ GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
+ GCClipMask | GCForeground | GCBackground | dostipple |
+ GCFillStyle, &values);
+}
+
+/*************************************<->*************************************
+ *
+ * GetDefImages
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ * mbutton = menubutton
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void GetDefImages (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ static unsigned char defMarkData[] =
+ {
+ 0x00, 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0x3c,
+ 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x07,
+ 0x8c, 0x03, 0x8e, 0x01, 0xde, 0x01, 0xdc, 0x00,
+ 0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00,
+ };
+
+ static unsigned char defCascadeData[] =
+ {
+ 0x80, 0x00, 0x80, 0x01, 0x80, 0x03, 0x80, 0x07,
+ 0x80, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f,
+ 0xfe, 0x3f, 0xfe, 0x1f, 0x80, 0x0f, 0x80, 0x07,
+ 0x80, 0x03, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00
+ };
+
+ mbutton->menubutton.defMarkImage =
+ XCreateImage (XtDisplay(mbutton), CopyFromParent, 1, XYBitmap, 0,
+ defMarkData, 16, 16, 8, 2);
+
+ mbutton->menubutton.defMarkImage->byte_order = MSBFirst;
+ mbutton->menubutton.defMarkImage->bitmap_bit_order = LSBFirst;
+ mbutton->menubutton.defMarkImage->bitmap_unit = 8;
+
+
+ mbutton->menubutton.defCascadeImage =
+ XCreateImage (XtDisplay(mbutton), CopyFromParent, 1, XYBitmap, 0,
+ defCascadeData, 16, 16, 8, 2);
+
+ mbutton->menubutton.defCascadeImage->byte_order = MSBFirst;
+ mbutton->menubutton.defCascadeImage->bitmap_bit_order = LSBFirst;
+ mbutton->menubutton.defCascadeImage->bitmap_unit = 8;
+}
+
+/*************************************<->*************************************
+ *
+ * CreatePixmap
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ * mbutton = menubutton
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void CreatePixmap (mbutton, image, pix, invertedPix)
+XwMenuButtonWidget mbutton;
+XImage * image;
+Pixmap * pix;
+Pixmap * invertedPix;
+{
+ if (*pix != (Pixmap)NULL)
+ XFreePixmap (XtDisplay(mbutton), *pix);
+
+ if (*invertedPix != (Pixmap)NULL)
+ XFreePixmap (XtDisplay(mbutton), *invertedPix);
+
+ if (image)
+ {
+ *pix = XCreatePixmap (XtDisplay(mbutton),
+ RootWindowOfScreen(XtScreen(mbutton)),
+ image->width, image->height,
+ DefaultDepthOfScreen(XtScreen(mbutton)));
+
+ XPutImage (XtDisplay(mbutton), *pix, mbutton->menubutton.defPixmap_GC,
+ image, 0, 0, 0, 0, image->width, image->height);
+
+ if (image->format == XYBitmap)
+ {
+ *invertedPix = XCreatePixmap (XtDisplay(mbutton),
+ RootWindowOfScreen(XtScreen(mbutton)),
+ image->width, image->height,
+ DefaultDepthOfScreen(XtScreen(mbutton)));
+
+ XPutImage (XtDisplay(mbutton), *invertedPix,
+ mbutton->menubutton.invertPixmap_GC,
+ image, 0, 0, 0, 0, image->width, image->height);
+ }
+
+ }
+ else
+ {
+ *pix = (Pixmap)NULL;
+ *invertedPix = (Pixmap)NULL;
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * IdealWidth
+ *
+ * Description:
+ * -----------
+ * NOTE!!! This should be eventually replaced by a QueryProc.
+ *
+ * Inputs:
+ * ------
+ * w = menubutton widget
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void IdealWidth (w, width)
+Widget w;
+Dimension * width;
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ *width = 2 * mbutton->primitive.highlight_thickness +
+ 2 * (XwMENUBTNPAD + mbutton->button.internal_width) +
+ XwMARKWIDTH + XwCASCADEWIDTH;
+
+ if (mbutton->menubutton.labelType == XwSTRING)
+ *width += mbutton->button.label_width;
+ else if (mbutton->menubutton.labelType == XwIMAGE)
+ *width += mbutton->menubutton.labelImage->width;
+}
+
+/*************************************<->*************************************
+ *
+ * Initialize (request, new)
+ *
+ * Description:
+ * -----------
+ * This is the menubutton instance initialize procedure.
+ *
+ *
+ * Inputs:
+ * ------
+ * request = original instance record;
+ *
+ * new = instance record with modifications induced by
+ * other initialize routines, changes are made to this
+ * record;
+ *
+ * args = argument list specified in XtCreateWidget;
+ *
+ * num_args = argument count;
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Initialize (request, new)
+ Widget request, new;
+{
+ Dimension dim;
+ KeySym tempKeysym;
+
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) new;
+
+ /* Augment our translations to include the traversal actions */
+ XtAugmentTranslations ((Widget)mbutton,
+ XwprimitiveClassRec.primitive_class.translations);
+
+ /*
+ * Always disable traversal in a menubutton. Since the traversal
+ * state is inherited from the menu manager, we will let it control
+ * our traversal state.
+ */
+ mbutton->primitive.traversal_type = XwHIGHLIGHT_OFF;
+
+ mbutton->menubutton.cascadeEnabled = FALSE;
+ mbutton->menubutton.inverted = FALSE;
+ mbutton->menubutton.labelPixmap =
+ mbutton->menubutton.markPixmap =
+ mbutton->menubutton.cascadePixmap =
+ mbutton->menubutton.invertLabelPixmap =
+ mbutton->menubutton.invertMarkPixmap =
+ mbutton->menubutton.invertCascadePixmap = (Pixmap)NULL;
+
+ GetDefImages(mbutton);
+ GetGC(mbutton);
+
+ /*
+ * If the menuMgr field has not been set up, check if in a menu system
+ * (menu manager as ancestor).
+ */
+ if (mbutton->menubutton.menuMgr == NULL)
+ {
+ if ((XtIsSubclass (XtParent (mbutton), XwmenupaneWidgetClass)) &&
+ (XtIsSubclass (XtParent (XtParent (mbutton)), shellWidgetClass)) &&
+ (XtIsSubclass (XtParent (XtParent (XtParent (mbutton))),
+ XwmenumgrWidgetClass)))
+ {
+ mbutton->menubutton.menuMgr =
+ (Widget) XtParent (XtParent (XtParent(mbutton)));
+ }
+ }
+
+ /*
+ * We need to malloc space for the strings and copy them to our
+ * space. The toolkit simply copies the pointer to the string.
+ */
+ if ((mbutton->menubutton.accelerator) &&
+ (_XwMapKeyEvent (mbutton->menubutton.accelerator,
+ &mbutton->menubutton.accelEventType,
+ &tempKeysym,
+ &mbutton->menubutton.accelModifiers)))
+ {
+ mbutton->menubutton.accelDetail = XKeysymToKeycode (XtDisplay(mbutton),
+ tempKeysym);
+ mbutton->menubutton.accelerator =
+ strcpy(XtMalloc((unsigned)(XwStrlen(mbutton->menubutton.accelerator)+1)),
+ mbutton->menubutton.accelerator);
+ }
+ else
+ {
+ if (mbutton->menubutton.accelerator)
+ XtWarning ("MenuButton: Invalid accelerator; disabling feature");
+ mbutton->menubutton.accelerator = NULL;
+ mbutton->menubutton.accelEventType = 0;
+ mbutton->menubutton.accelDetail = 0;
+ mbutton->menubutton.accelModifiers = 0;
+ }
+
+ if (mbutton->menubutton.hint)
+ mbutton->menubutton.hint =
+ strcpy(XtMalloc((unsigned)(XwStrlen(mbutton->menubutton.hint)+1)),
+ mbutton->menubutton.hint);
+
+ /*
+ * malloc space for mnemonic. Only take 1st character & null
+ */
+ if ((mbutton->menubutton.mnemonic) &&
+ (*(mbutton->menubutton.mnemonic) != '\0'))
+ {
+ char mne = mbutton->menubutton.mnemonic[0];
+
+ mbutton->menubutton.mnemonic = (String) XtMalloc(2);
+ mbutton->menubutton.mnemonic[0] = mne;
+ mbutton->menubutton.mnemonic[1] = '\0';
+ }
+ else
+ if (mbutton->menubutton.mnemonic)
+ XtWarning ("MenuButton: Invalid mnemonic; disabling feature");
+
+ if (mbutton->menubutton.labelImage)
+ CreatePixmap(mbutton, mbutton->menubutton.labelImage,
+ &mbutton->menubutton.labelPixmap,
+ &mbutton->menubutton.invertLabelPixmap);
+
+ if (!mbutton->menubutton.markImage)
+ mbutton->menubutton.markImage = mbutton->menubutton.defMarkImage;
+
+ CreatePixmap(mbutton, mbutton->menubutton.markImage,
+ &mbutton->menubutton.markPixmap,
+ &mbutton->menubutton.invertMarkPixmap);
+
+ if (!mbutton->menubutton.cascadeImage)
+ mbutton->menubutton.cascadeImage = mbutton->menubutton.defCascadeImage;
+
+ CreatePixmap(mbutton, mbutton->menubutton.cascadeImage,
+ &mbutton->menubutton.cascadePixmap,
+ &mbutton->menubutton.invertCascadePixmap);
+
+ if (request->core.height <= 0)
+ mbutton->core.height = ComputeHeight(mbutton);
+
+ ComputeVertical(mbutton);
+ SetUnderline(mbutton);
+
+ if (request->core.width <= 0)
+ IdealWidth(mbutton, &mbutton->core.width);
+}
+
+/*************************************<->*************************************
+ *
+ * Destroy
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Destroy (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ if (mbutton->menubutton.accelerator)
+ XtFree (mbutton->menubutton.accelerator);
+
+ XtDestroyGC (mbutton->menubutton.defPixmap_GC);
+ XtDestroyGC (mbutton->menubutton.inverted_GC);
+ XtDestroyGC (mbutton->menubutton.invertPixmap_GC);
+ XtDestroyGC (mbutton->menubutton.rect_GC);
+
+ mbutton->menubutton.defMarkImage->data = NULL;
+ XDestroyImage (mbutton->menubutton.defMarkImage);
+ mbutton->menubutton.defCascadeImage->data = NULL;
+ XDestroyImage (mbutton->menubutton.defCascadeImage);
+
+ XtRemoveAllCallbacks ((Widget)mbutton, XtNcascadeSelect);
+ XtRemoveAllCallbacks ((Widget)mbutton, XtNcascadeUnselect);
+
+ XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.markPixmap);
+ XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.cascadePixmap);
+ if (mbutton->menubutton.labelPixmap)
+ XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.labelPixmap);
+}
+
+/*************************************<->*************************************
+ *
+ * Realize
+ *
+ * Description:
+ * -----------
+ * Creates the window for this menubutton instance. Sets bit gravity
+ * so that on resize the menubutton is repainted.
+ *
+ *
+ * Inputs:
+ * ------
+ * w = widget to be realized.
+ *
+ * valueMask = contains event mask for this window/widget.
+ *
+ * attributes = window attributes for this window/widget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCreateWindow()
+ *************************************<->***********************************/
+
+static void Realize(w, p_valueMask, attributes)
+Widget w;
+XtValueMask * p_valueMask;
+XSetWindowAttributes * attributes;
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ XtValueMask valueMask = *p_valueMask;
+ valueMask |= CWBitGravity;
+ attributes->bit_gravity = ForgetGravity;
+
+
+ XtCreateWindow ((Widget)mbutton, InputOutput, (Visual *) CopyFromParent,
+ valueMask, attributes);
+
+ _XwRegisterName (mbutton);
+} /* Realize */
+
+/*************************************<->*************************************
+ *
+ * Select (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * Mark menubutton as selected, (i.e., draw it as active)
+ * Generate the correct callbacks.
+ *
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCallCallbacks()
+ *************************************<->***********************************/
+
+static void Select(w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ /* Don't do anything if its not sensitive. */
+
+ if (XtIsSensitive((Widget)mbutton))
+ {
+ /*
+ * if there is a menu manager, call the process select routine to
+ * determine if the event is valid for the menu system.
+ */
+ if (mbutton->menubutton.menuMgr)
+ {
+ if ((*(((XwMenuMgrWidgetClass) XtClass(mbutton->menubutton.menuMgr))->
+ menu_mgr_class.processSelect))
+ (mbutton->menubutton.menuMgr, mbutton, event) == FALSE)
+ {
+ return;
+ }
+ }
+
+ XtCallCallbacks ((Widget)mbutton, XtNselect, NULL);
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * DrawLabelMarkCascade (mbutton)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void DrawLabelMarkCascade (mbutton)
+XwMenuButtonWidget mbutton;
+{
+ Dimension labelStarts;
+ GC theGC;
+ Pixmap thePixmap;
+
+ if (mbutton->menubutton.inverted)
+ theGC = mbutton->button.inverse_GC;
+ else
+ theGC = mbutton->button.normal_GC;
+
+
+ if (mbutton->menubutton.noPad == True)
+ labelStarts = mbutton->primitive.highlight_thickness +
+ mbutton->button.internal_width;
+ else
+ labelStarts = mbutton->primitive.highlight_thickness +
+ mbutton->button.internal_width + XwMENUBTNPAD + XwMARKWIDTH;
+ /*
+ * Draw the label with its underline if needed.
+ */
+ if (mbutton->menubutton.labelType == XwSTRING)
+ {
+ XDrawString(
+ XtDisplay(mbutton), XtWindow(mbutton), theGC,
+ labelStarts, mbutton->button.label_y,
+ mbutton->button.label, (int) mbutton->button.label_len);
+
+ if ((!mbutton->menubutton.mgrOverrideMnemonic) &&
+ (mbutton->menubutton.mnemonicMatch))
+ XDrawLine(
+ XtDisplay(mbutton), XtWindow(mbutton), theGC,
+ mbutton->menubutton.underline_x,
+ mbutton->menubutton.underline_y,
+ mbutton->menubutton.underline_x +
+ mbutton->menubutton.underline_width,
+ mbutton->menubutton.underline_y);
+ }
+ else if (mbutton->menubutton.labelType == XwRECT)
+ {
+ /* Draw a colored or stippled rectangle with a border around it */
+
+ if (mbutton->menubutton.noPad == True) {
+ XFillRectangle(
+ XtDisplay(mbutton), XtWindow(mbutton),
+ mbutton->menubutton.rect_GC,
+ 2, 2, mbutton->menubutton.labelImage->width - 1,
+ mbutton->menubutton.labelImage->height - 1);
+ XDrawRectangle(
+ XtDisplay(mbutton), XtWindow(mbutton), theGC,
+ 2, 2, mbutton->menubutton.labelImage->width - 1,
+ mbutton->menubutton.labelImage->height - 1);
+ }
+ else {
+ XFillRectangle(
+ XtDisplay(mbutton), XtWindow(mbutton),
+ mbutton->menubutton.rect_GC,
+ XwMARKWIDTH + 3, 3, mbutton->core.width - XwMARKWIDTH - 6,
+ mbutton->core.height - 6);
+ XDrawRectangle(
+ XtDisplay(mbutton), XtWindow(mbutton), theGC,
+ XwMARKWIDTH + 3, 3, mbutton->core.width - XwMARKWIDTH - 6,
+ mbutton->core.height - 6);
+ }
+ }
+ else
+ {
+ if ((mbutton->menubutton.inverted) &&
+ (mbutton->menubutton.invertLabelPixmap))
+ thePixmap = mbutton->menubutton.invertLabelPixmap;
+ else
+ thePixmap = mbutton->menubutton.labelPixmap;
+
+ XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
+ mbutton->menubutton.defPixmap_GC, 0, 0,
+ mbutton->menubutton.labelImage->width,
+ mbutton->menubutton.labelImage->height,
+ labelStarts, mbutton->button.label_y);
+ }
+
+ /*
+ * If the mark is set, display the mark.
+ */
+ if (mbutton->menubutton.setMark)
+ {
+ if ((mbutton->menubutton.inverted) &&
+ (mbutton->menubutton.invertMarkPixmap))
+ thePixmap = mbutton->menubutton.invertMarkPixmap;
+ else
+ thePixmap = mbutton->menubutton.markPixmap;
+
+ XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
+ mbutton->menubutton.defPixmap_GC, 0, 0,
+ mbutton->menubutton.markImage->width,
+ mbutton->menubutton.markImage->height,
+ mbutton->button.internal_width +
+ mbutton->primitive.highlight_thickness,
+ mbutton->menubutton.mark_y);
+ }
+
+ /*
+ * If the cascade is set, display it.
+ */
+ if (mbutton->menubutton.cascadeOn)
+ {
+ if ((mbutton->menubutton.inverted) &&
+ (mbutton->menubutton.invertCascadePixmap))
+ thePixmap = mbutton->menubutton.invertCascadePixmap;
+ else
+ thePixmap = mbutton->menubutton.cascadePixmap;
+
+ XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
+ mbutton->menubutton.defPixmap_GC, 0, 0,
+ mbutton->menubutton.cascadeImage->width,
+ mbutton->menubutton.cascadeImage->height,
+ mbutton->core.width - XwCASCADEWIDTH -
+ mbutton->primitive.highlight_thickness -
+ mbutton->button.internal_width,
+ mbutton->menubutton.cascade_y);
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * Inverted (mbutton)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XFillRectangle
+ * DrawLabelMarkCascade
+ *
+ *************************************<->***********************************/
+
+static void Inverted (mw)
+XwMenuButtonWidget mw;
+
+{
+ mw -> menubutton.inverted = TRUE;
+
+ XFillRectangle (XtDisplay (mw), XtWindow (mw),
+ mw->button.normal_GC,
+ mw -> primitive.highlight_thickness + 1,
+ mw -> primitive.highlight_thickness + 1,
+ mw -> core.width - 2 *
+ (mw -> primitive.highlight_thickness + 1),
+ mw -> core.height - 2 *
+ (mw -> primitive.highlight_thickness + 1));
+ DrawLabelMarkCascade (mw);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * NonInverted (mbutton)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XClearWindow
+ * DrawLabelMarkCascade
+ *
+ *************************************<->***********************************/
+
+static void NonInverted (mbutton)
+XwMenuButtonWidget mbutton;
+
+{
+ mbutton->menubutton.inverted = FALSE;
+
+ XClearWindow (XtDisplay(mbutton), XtWindow(mbutton));
+ DrawLabelMarkCascade (mbutton);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * Highlight(mbutton)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Moved
+ * Inverted
+ *
+ *************************************<->***********************************/
+
+static void Highlight (mbutton)
+XwMenuButtonWidget mbutton;
+{
+/*
+ if (mbutton->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
+ _XwHighlightBorder(mbutton);
+ else
+*/
+ Inverted (mbutton);
+}
+
+/*************************************<->*************************************
+ *
+ * Unhighlight (mbutton)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Moved
+ * Inverted
+ *
+ *************************************<->***********************************/
+
+static void Unhighlight (mbutton)
+XwMenuButtonWidget mbutton;
+{
+/*
+ if (mbutton->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
+ _XwUnhighlightBorder(mbutton);
+ else
+*/
+ NonInverted (mbutton);
+ mbutton->menubutton.cascadeEnabled = FALSE;
+}
+
+/*************************************<->*************************************
+ *
+ * Enter (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Moved
+ * Inverted
+ *
+ *************************************<->***********************************/
+
+static void Enter(w,event)
+Widget w;
+XEvent *event;
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
+
+#ifdef DEBUG
+ printf ("Enter %s\n", w->core.name);
+#endif
+ if ((mbutton->menubutton.menuMgr == NULL) ||
+ ((*(((XwMenuMgrWidgetClass)
+ XtClass (mbutton->menubutton.menuMgr))->menu_mgr_class.validEvent))
+ (mbutton->menubutton.menuMgr, mbutton, event)))
+ {
+ /*
+ * Check on cascade indicator
+ */
+ Moved (w, event);
+
+/*
+ * if (mbutton->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
+ */
+ Inverted(mbutton);
+ }
+
+ /* to-do: if no hintProc is specified, should generate a hint tag */
+
+ if ((mbutton->menubutton.hint != NULL) &&
+ (mbutton->menubutton.hintProc != NULL)) {
+ mbutton->menubutton.hintProc(mbutton->menubutton.hint);
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * EnterParentsWindow (menupane, mbutton,event)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void EnterParentsWindow (menupane, mbutton, event)
+Widget menupane;
+XwMenuButtonWidget mbutton;
+XEvent * event;
+{
+ Boolean remainHighlighted;
+ XwunselectParams params;
+
+ XEnterWindowEvent * entEvent = (XEnterWindowEvent *) event;
+
+#ifdef DEBUG
+ printf ("EnterParents %s %s ", menupane->core.name, mbutton->core.name);
+#endif
+
+ /*
+ * if outside of the menubutton, bring down submenu. I am assuming that
+ * the x parameters are okay. This means that entering my parents borders
+ * on the correct y parameters will not cause the unselects to be called.
+ */
+ if ((entEvent->y < mbutton->core.y) ||
+ (entEvent->y > mbutton->core.y + mbutton->core.height +
+ 2 * mbutton->core.border_width))
+ {
+ params.rootX = entEvent->x_root;
+ params.rootY = entEvent->y_root;
+ params.remainHighlighted = FALSE;
+
+#ifdef DEBUG
+ printf ("rootX %d rootY %d\n", params.rootX, params.rootY);
+ printf ("disabled\n");
+#endif
+
+ XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, &params);
+ mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
+ if (mbutton->menubutton.cascadeEnabled == FALSE)
+ Unhighlight (mbutton);
+ }
+/* else
+ * Moved (mbutton, event);
+ */
+
+#ifdef DEBUG
+ printf ("\n");
+#endif
+
+ XtRemoveEventHandler (menupane, EnterWindowMask, FALSE,
+ (XtEventHandler)EnterParentsWindow, mbutton);
+}
+
+/*************************************<->*************************************
+ *
+ * Leave (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCallCallbacks
+ * NonInverted
+ *
+ *************************************<->***********************************/
+
+static void Leave(w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwunselectParams params;
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
+ XLeaveWindowEvent * lEvent = (XLeaveWindowEvent *) event;
+
+ params.rootX = lEvent->x_root;
+ params.rootY = lEvent->y_root;
+
+
+ if ((mbutton->menubutton.menuMgr == NULL) ||
+ ((*(((XwMenuMgrWidgetClass)
+ XtClass (mbutton->menubutton.menuMgr))->menu_mgr_class.validEvent))
+ (mbutton->menubutton.menuMgr, mbutton, event)))
+ {
+ if (mbutton->menubutton.cascadeEnabled)
+ {
+ params.remainHighlighted = FALSE;
+ XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, &params);
+ mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
+
+ if (mbutton->menubutton.cascadeEnabled)
+ {
+ XtAddEventHandler (XtParent(mbutton), EnterWindowMask, FALSE,
+ (XtEventHandler)EnterParentsWindow, mbutton);
+ return;
+ }
+ }
+
+ if (mbutton->menubutton.inverted)
+ NonInverted(mbutton);
+ }
+
+ if ((mbutton->menubutton.hint != NULL) &&
+ (mbutton->menubutton.hintProc != NULL)) {
+ mbutton->menubutton.hintProc("");
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * Moved
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XQueryPointer
+ * XtCallCallbacks
+ *
+ *************************************<->***********************************/
+
+static void Moved (w,event)
+Widget w;
+XEvent * event;
+
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
+
+ int xPosition, yPosition;
+ int xroot, yroot;
+ Window root, child;
+ unsigned int mask;
+ XwunselectParams params;
+
+ XButtonPressedEvent * buttonEvent = (XButtonPressedEvent *) event;
+
+#ifdef DEBUG
+ printf ("Moved %s\n", w->core.name);
+#endif
+
+ /*
+ * only do this if I have a cascade showing
+ */
+ if ((mbutton->menubutton.cascadeOn) &&
+ (mbutton->primitive.traversal_type == XwHIGHLIGHT_OFF))
+ {
+ /*
+ * if there is a menu manager and the cascade has not been popped up,
+ * then ask the menu manager if it should be popped up
+ */
+ if ((mbutton->menubutton.menuMgr == NULL) ||
+ (mbutton->menubutton.cascadeEnabled == TRUE) ||
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(mbutton->menubutton.menuMgr))->menu_mgr_class.doICascade))
+ (mbutton->menubutton.menuMgr, mbutton))
+ {
+ /*
+ * check if the event appears to have occurred in the cascade area
+ */
+ if ((mbutton->menubutton.cascadeEnabled) ||
+ ((buttonEvent->y > 0) &&
+ (buttonEvent->y < mbutton->core.height +
+ 2 * mbutton->core.border_width) &&
+ (buttonEvent->x < mbutton->core.width +
+ 2 * mbutton->core.border_width) &&
+ (buttonEvent->x > mbutton->core.width +
+ 2 * mbutton->core.border_width -
+ XwCASCADEWIDTH -
+ mbutton->primitive.highlight_thickness -
+ mbutton->button.internal_width)))
+ {
+ /*
+ * Verify that its really in the cascade area
+ */
+ XQueryPointer (XtDisplay(mbutton), mbutton->core.window,
+ &root, &child, &xroot, &yroot, &xPosition,
+ &yPosition, &mask);
+
+ if ((yPosition > 0) &&
+ (yPosition < mbutton->core.height +
+ 2 * mbutton->core.border_width) &&
+ (xPosition < mbutton->core.width +
+ 2 * mbutton->core.border_width) &&
+ (xPosition > mbutton->core.width +
+ 2 * mbutton->core.border_width - XwCASCADEWIDTH -
+ mbutton->primitive.highlight_thickness -
+ mbutton->button.internal_width))
+ {
+ if (!mbutton->menubutton.cascadeEnabled)
+ {
+ XtCallCallbacks ((Widget)mbutton, XtNcascadeSelect, NULL);
+#ifdef DEBUG
+ printf ("enabled\n");
+#endif
+ mbutton->menubutton.cascadeEnabled = TRUE;
+ }
+ }
+ else if (mbutton->menubutton.cascadeEnabled)
+ {
+ params.rootX = xroot;
+ params.rootY = yroot;
+ params.remainHighlighted = FALSE;
+#ifdef DEBUG
+ printf ("Moved rootX %d rootY %d\n", params.rootX, params.rootY);
+#endif
+ XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, &params);
+ mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
+ }
+ }
+ }
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * Redisplay (w, event)
+ *
+ * Description:
+ * -----------
+ * Cause the widget, identified by w, to be redisplayed.
+ *
+ * Inputs:
+ * ------
+ * w = widget to be redisplayed;
+ * event = event structure identifying need for redisplay on this
+ * widget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Inverted
+ * NonInverted
+ * _XwHighlightBorder
+ * _XwUnhighlightBorder
+ *
+ *************************************<->***********************************/
+
+static void Redisplay(w, event)
+ Widget w;
+ XEvent *event;
+{
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ /*
+ * if the highlight state has changed since the last redisplay,
+ * update the window and set the font GC.
+ */
+ if (mbutton->menubutton.inverted)
+ Inverted(mbutton);
+
+ else
+ NonInverted(mbutton);
+
+ if (mbutton->primitive.highlighted)
+ _XwHighlightBorder(mbutton);
+
+ else
+ if (mbutton->primitive.display_highlighted)
+ _XwUnhighlightBorder(mbutton);
+}
+
+/*************************************<->*************************************
+ *
+ * SetValues(urrent, request, new)
+ *
+ * Description:
+ * -----------
+ * This is the set values procedure for the menubutton class. It is
+ * called last (the set values rtnes for its superclasses are called
+ * first).
+ *
+ *
+ * Inputs:
+ * ------
+ * current = original widget;
+ * request = copy of current (?);
+ * new = copy of request which reflects changes made to it by
+ * set values procedures of its superclasses;
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues (current, request, new)
+Widget current, request, new;
+{
+ XtWidgetGeometry reqGeo;
+ XtWidgetGeometry replyGeo;
+ XwMenuButtonWidget curmbutton = (XwMenuButtonWidget) current;
+ XwMenuButtonWidget newmbutton = (XwMenuButtonWidget) new;
+ Boolean flag = FALSE; /* our return value */
+ Dimension dim;
+ KeySym tempKeysym;
+
+ /* We never allow our traversal state to change using SetValues() */
+ newmbutton->primitive.traversal_type = curmbutton->primitive.traversal_type;
+
+ /*
+ * If the accelerator string changed, malloc space for the string
+ * and copy it to our space. The old string must be freed.
+ */
+
+ if (curmbutton->menubutton.accelerator !=
+ newmbutton->menubutton.accelerator)
+ {
+ if (newmbutton->menubutton.accelerator)
+ {
+ if (_XwMapKeyEvent (newmbutton->menubutton.accelerator,
+ &newmbutton->menubutton.accelEventType,
+ &tempKeysym,
+ &newmbutton->menubutton.accelModifiers)
+ == FALSE)
+ {
+ /* Invalid string; revert to previous one */
+ XtWarning
+ ("MenuButton: Invalid accelerator; using previous setting");
+ newmbutton->menubutton.accelerator =
+ curmbutton->menubutton.accelerator;
+ newmbutton->menubutton.accelEventType =
+ curmbutton->menubutton.accelEventType;
+ newmbutton->menubutton.accelDetail =
+ curmbutton->menubutton.accelDetail;
+ newmbutton->menubutton.accelModifiers =
+ curmbutton->menubutton.accelModifiers;
+ }
+ else
+ {
+ /* valid string */
+ newmbutton->menubutton.accelDetail = XKeysymToKeycode (
+ XtDisplay(newmbutton), tempKeysym);
+ newmbutton->menubutton.accelerator =
+ strcpy(XtMalloc((unsigned)
+ (XwStrlen(newmbutton->menubutton.accelerator)+1)),
+ newmbutton->menubutton.accelerator);
+
+ if (newmbutton->menubutton.menuMgr)
+ (*(((XwMenuMgrWidgetClass)
+ XtClass (newmbutton->menubutton.menuMgr))->
+ menu_mgr_class.setSelectAccelerator))
+ (newmbutton->menubutton.menuMgr, (Widget)newmbutton,
+ newmbutton->menubutton.accelerator,
+ newmbutton->menubutton.accelEventType,
+ newmbutton->menubutton.accelDetail,
+ newmbutton->menubutton.accelModifiers);
+
+ if (curmbutton->menubutton.accelerator)
+ XtFree ((char *) curmbutton->menubutton.accelerator);
+ }
+ }
+ else if (curmbutton->menubutton.accelerator)
+ {
+ if (curmbutton->menubutton.menuMgr)
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(curmbutton->menubutton.menuMgr))->
+ menu_mgr_class.clearSelectAccelerator))
+ (curmbutton->menubutton.menuMgr, (Widget)curmbutton);
+
+ XtFree ((char *) curmbutton->menubutton.accelerator);
+ }
+ }
+
+ /*
+ * Determine if the mnemonic changed, verify and malloc space.
+ * Notify menuMgr of the change.
+ */
+
+ if (curmbutton->menubutton.mnemonic != newmbutton->menubutton.mnemonic)
+ {
+ if (newmbutton->menubutton.mnemonic)
+ {
+ if (*(newmbutton->menubutton.mnemonic) == '\0')
+ {
+ XtWarning
+ ("MenuButton: Invalid mnemonic; using previous setting");
+ newmbutton->menubutton.mnemonic = curmbutton->menubutton.mnemonic;
+ }
+ else
+ {
+ char mne = newmbutton->menubutton.mnemonic[0];
+
+ newmbutton->menubutton.mnemonic = (String)XtMalloc(2);
+ newmbutton->menubutton.mnemonic[0] = mne;
+ newmbutton->menubutton.mnemonic[1] = '\0';
+
+ if (newmbutton->menubutton.menuMgr)
+ (*(((XwMenuMgrWidgetClass)
+ XtClass (newmbutton->menubutton.menuMgr))->
+ menu_mgr_class.setSelectMnemonic))
+ (newmbutton->menubutton.menuMgr, (Widget)newmbutton,
+ newmbutton->menubutton.mnemonic);
+
+ XtFree (curmbutton->menubutton.mnemonic);
+ }
+ }
+ else
+ {
+ if (newmbutton->menubutton.menuMgr)
+ (*(((XwMenuMgrWidgetClass)
+ XtClass (curmbutton->menubutton.menuMgr))->
+ menu_mgr_class.clearSelectMnemonic))
+ (curmbutton->menubutton.menuMgr, (Widget)curmbutton);
+
+ XtFree(curmbutton->menubutton.mnemonic);
+ }
+ }
+
+ /*
+ * recalculate the underline parameters if mnemonic or font changes
+ */
+ if ((newmbutton->menubutton.mnemonic != curmbutton->menubutton.mnemonic) ||
+ (newmbutton->button.font != curmbutton->button.font))
+ {
+ SetUnderline (newmbutton);
+ flag = TRUE;
+ }
+
+
+ /*
+ * If the foreground or background changed, or the color or stipple
+ * declaration was changed, recreate the GC's
+ */
+ if ((newmbutton->primitive.foreground !=
+ curmbutton->primitive.foreground) ||
+ (newmbutton->core.background_pixel !=
+ curmbutton->core.background_pixel) ||
+ (newmbutton->menubutton.rectColor !=
+ curmbutton->menubutton.rectColor) ||
+ (newmbutton->menubutton.rectStipple !=
+ curmbutton->menubutton.rectStipple))
+ {
+ GetGC (newmbutton);
+ XtDestroyGC (curmbutton->menubutton.defPixmap_GC);
+ XtDestroyGC (curmbutton->menubutton.invertPixmap_GC);
+ }
+
+ /*
+ * If the GCs are new, or the images are new, create new pixmaps
+ */
+ if ((newmbutton->menubutton.markImage !=
+ curmbutton->menubutton.markImage) ||
+ (newmbutton->primitive.foreground !=
+ curmbutton->primitive.foreground) ||
+ (newmbutton->core.background_pixel !=
+ curmbutton->core.background_pixel))
+ {
+ if (!newmbutton->menubutton.markImage)
+ newmbutton->menubutton.markImage =
+ newmbutton->menubutton.defMarkImage;
+
+ CreatePixmap(newmbutton, newmbutton->menubutton.markImage,
+ &newmbutton->menubutton.markPixmap,
+ &newmbutton->menubutton.invertMarkPixmap);
+ flag = TRUE;
+ }
+
+ if ((newmbutton->menubutton.cascadeImage !=
+ curmbutton->menubutton.cascadeImage) ||
+ (newmbutton->primitive.foreground !=
+ curmbutton->primitive.foreground) ||
+ (newmbutton->core.background_pixel !=
+ curmbutton->core.background_pixel))
+ {
+ if (!newmbutton->menubutton.cascadeImage)
+ newmbutton->menubutton.cascadeImage =
+ newmbutton->menubutton.defCascadeImage;
+
+ CreatePixmap(newmbutton, newmbutton->menubutton.cascadeImage,
+ &newmbutton->menubutton.cascadePixmap,
+ &newmbutton->menubutton.invertCascadePixmap);
+ flag = TRUE;
+ }
+
+ if ((newmbutton->menubutton.labelImage !=
+ curmbutton->menubutton.labelImage) ||
+ (newmbutton->primitive.foreground !=
+ curmbutton->primitive.foreground) ||
+ (newmbutton->core.background_pixel !=
+ curmbutton->core.background_pixel))
+ {
+ CreatePixmap(newmbutton, newmbutton->menubutton.labelImage,
+ &newmbutton->menubutton.labelPixmap,
+ &newmbutton->menubutton.invertLabelPixmap);
+
+ if (newmbutton->menubutton.labelType == XwIMAGE)
+ flag = TRUE;
+ }
+
+ if ((newmbutton->core.sensitive != curmbutton->core.sensitive) ||
+ (newmbutton->core.ancestor_sensitive !=
+ curmbutton->core.ancestor_sensitive))
+ {
+ if (curmbutton->menubutton.menuMgr)
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(curmbutton->menubutton.menuMgr))->
+ menu_mgr_class.btnSensitivityChanged))
+ (curmbutton->menubutton.menuMgr, (Widget)newmbutton);
+ }
+ }
+
+ /*
+ * fields that change that cause a redraw
+ */
+ if ((newmbutton->menubutton.labelType !=
+ curmbutton->menubutton.labelType) ||
+ (newmbutton->menubutton.setMark !=
+ curmbutton->menubutton.setMark) ||
+ (newmbutton->menubutton.cascadeOn !=
+ curmbutton->menubutton.cascadeOn) ||
+ (newmbutton->menubutton.mgrOverrideMnemonic !=
+ curmbutton->menubutton.mgrOverrideMnemonic) ||
+ (newmbutton->menubutton.rectColor !=
+ curmbutton->menubutton.rectColor) ||
+ (newmbutton->menubutton.rectStipple !=
+ curmbutton->menubutton.rectStipple))
+
+
+ flag = TRUE;
+
+
+ /**********************************************************************
+ * Calculate the window size: The assumption here is that if
+ * the width and height are the same in the new and current instance
+ * record that those fields were not changed with set values. Therefore
+ * its okay to recompute the necessary width and height. However, if
+ * the new and current do have different width/heights then leave them
+ * alone because that's what the user wants.
+ *********************************************************************/
+
+ /* "noPad" option prevents button from resizing itself 2/24/00 --Tim */
+
+ if (curmbutton->core.width == request->core.width &&
+ curmbutton->menubutton.noPad == False)
+ {
+ IdealWidth (newmbutton, &newmbutton->core.width);
+ flag = TRUE;
+ }
+ else if (request->core.width <= 0)
+ {
+ XtWarning ("MenuButton: Invalid width; using previous setting");
+ newmbutton->core.width = curmbutton->core.width;
+ }
+
+ if (curmbutton->core.height == request->core.height &&
+ curmbutton->menubutton.noPad == False)
+ {
+ newmbutton->core.height = ComputeHeight(newmbutton);
+ flag = TRUE;
+ }
+ else if (request->core.height <= 0)
+ {
+ XtWarning ("MenuButton: Invalid height; using previous setting");
+ newmbutton->core.height = curmbutton->core.height;
+ }
+
+ return (flag);
+}
+
+/*************************************<->*************************************
+ *
+ * Resize(w)
+ *
+ * Description:
+ * -----------
+ * A resize event has been generated. Recompute location of button
+ * elements.
+ *
+ * Inputs:
+ * ------
+ * w = widget to be resized.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Resize(w)
+ Widget w;
+{
+
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ ComputeVertical(mbutton);
+ SetUnderline(mbutton);
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetTraversalType(w)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetTraversalType (w, highlight_mode)
+
+ Widget w;
+ int highlight_mode;
+
+{
+
+ XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
+
+ mbutton->primitive.traversal_type = highlight_mode;
+
+ if (highlight_mode == XwHIGHLIGHT_TRAVERSAL)
+ {
+ XtAugmentTranslations (w, XwprimitiveClassRec.primitive_class.
+ translations);
+ w->core.widget_class->core_class.visible_interest = True;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseRight(w, event)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseRight (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the next menupane, if we
+ * have a cascade.
+ */
+
+ if ((w->menubutton.cascadeOn) && (w->menubutton.menuMgr) &&
+ (w->primitive.I_have_traversal) && (_XwUniqueEvent (event)))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseRight))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseLeft(w, event)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseLeft (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the previous menupane.
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseLeft))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseNext(w, event)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseNext (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the previous menupane.
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseNext))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraversePrev(w, event)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraversePrev (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the previous menupane.
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traversePrev))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseHome(w)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseHome (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the first menupane.
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseHome))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseUp(w)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseUp (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse up one menu button
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseUp))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseDown(w)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseDown (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse down one menu button
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseDown))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseNextTop(w)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseNextTop (w, event)
+
+ XwMenuButtonWidget w;
+ XEvent * event;
+
+{
+ /*
+ * Ask the menu manager to traverse to the next top level menupane
+ */
+
+ if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
+ (w->primitive.I_have_traversal))
+ {
+ (*(((XwMenuMgrWidgetClass)
+ XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseNextTop))
+ (w->menubutton.menuMgr, event);
+ }
+}
+
+
+/************************************************************************
+ *
+ * _XwExtractTime
+ * Extract the time field from the event structure.
+ *
+ ************************************************************************/
+
+static Time _XwExtractTime (event)
+
+ XEvent * event;
+
+{
+ if ((event->type == ButtonPress) || (event->type == ButtonRelease))
+ return (event->xbutton.time);
+
+ if ((event->type == KeyPress) || (event->type == KeyRelease))
+ return (event->xkey.time);
+
+ return ((Time) 0);
+}
+
+
+Boolean _XwUniqueEvent (event)
+
+ XEvent * event;
+
+{
+ static unsigned long serial = 0;
+ static Time time = 0;
+ static int type = 0;
+ Time newTime;
+
+ /*
+ * Ignore duplicate events, caused by an event being dispatched
+ * to both the focus widget and the spring-loaded widget, where
+ * these map to the same widget (menus).
+ */
+ if ((time != (newTime = _XwExtractTime (event))) ||
+ (type != event->type) ||
+ (serial != event->xany.serial))
+ {
+ /* Save the fingerprints for the new event */
+ type = event->type;
+ serial = event->xany.serial;
+ time = newTime;
+
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Visibility(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Visibility (widget, event)
+
+ Widget widget;
+ XEvent * event;
+
+{
+ /*
+ * Noop; purpose is to prevent Primitive's translation from
+ * taking effect.
+ */
+}
+
+
+/*************************************<->*************************************
+ *
+ * Unmap(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Unmap (widget, event)
+
+ Widget widget;
+ XEvent * event;
+
+{
+ /*
+ * Noop; purpose is to prevent Primitive's translation from
+ * taking effect.
+ */
+}
diff --git a/Xw/MenuBtn.h b/Xw/MenuBtn.h
new file mode 100644
index 0000000..cbe86d5
--- /dev/null
+++ b/Xw/MenuBtn.h
@@ -0,0 +1,55 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MenuBtn.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for MenuButton class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/***********************************************************************
+ *
+ * MenuButton Widget
+ *
+ ***********************************************************************/
+
+
+extern WidgetClass XwmenubuttonWidgetClass;
+
+/* synonym added for consistent naming conventions */
+extern WidgetClass XwmenuButtonWidgetClass;
+
+typedef struct _XwMenuButtonClassRec *XwMenuButtonWidgetClass;
+typedef struct _XwMenuButtonRec *XwMenuButtonWidget;
+
+
+
+/********************
+ *
+ * CascadeUnselect callback data typedef
+ *
+ ********************/
+
+typedef struct
+{
+ Dimension rootX;
+ Dimension rootY;
+ Boolean remainHighlighted;
+} XwunselectParams;
diff --git a/Xw/MenuBtnP.h b/Xw/MenuBtnP.h
new file mode 100644
index 0000000..c3485d2
--- /dev/null
+++ b/Xw/MenuBtnP.h
@@ -0,0 +1,148 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MenuBtnP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for MenuButton class
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#define XwMARKWIDTH 16
+#define XwCASCADEWIDTH 16
+#define XwMENUBTNPAD 6
+
+/********************************************
+ *
+ * the MenuButton widget class record
+ *
+ ********************************************/
+
+typedef struct _XwMenuButtonClassPart
+{
+ XwWidthProc idealWidthProc;
+ XtWidgetProc unhighlightProc;
+ XtWidgetProc highlightProc;
+ XtWidgetProc setCascadeProc;
+ XtWidgetProc clearCascadeProc;
+ XtWidgetProc enterParentProc;
+ XtWidgetProc cascadeSelectProc;
+ XtWidgetProc cascadeUnselectProc;
+ XwWintProc setTraversalType;
+} XwMenuButtonClassPart;
+
+#define XtInheritSetCascadeProc ((XtWidgetProc) _XtInherit)
+#define XtInheritClearCascadeProc ((XtWidgetProc) _XtInherit)
+#define XtInheritCascadeSelectProc ((XtWidgetProc) _XtInherit)
+#define XtInheritCascadeUnselectProc ((XtWidgetProc) _XtInherit)
+#define XtInheritSetTraversalTypeProc ((XwWintProc) _XtInherit)
+
+/****************************************************
+ *
+ * Full class record declaration for MenuButton class
+ *
+ ****************************************************/
+typedef struct _XwMenuButtonClassRec {
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwButtonClassPart button_class;
+ XwMenuButtonClassPart menubutton_class;
+} XwMenuButtonClassRec;
+
+
+extern XwMenuButtonClassRec XwmenubuttonClassRec;
+
+/********************************************
+ *
+ * New fields for the instance record
+ *
+ ********************************************/
+
+typedef struct _XwMenuButtonPart
+{
+ /* can be set through resources */
+
+ int labelType;
+ XImage * labelImage;
+ XImage * cascadeImage;
+ XImage * markImage;
+ Pixel rectColor;
+ Pixmap rectStipple;
+ Boolean setMark;
+ Boolean noPad;
+ Widget cascadeOn;
+ char * accelerator;
+ char * hint;
+ XwStrProc hintProc;
+ Boolean mgrOverrideMnemonic;
+ String mnemonic;
+ XtCallbackList cascadeSelect;
+ XtCallbackList cascadeUnselect;
+
+ /* can not be set through resources */
+
+ Widget menuMgr;
+ Dimension mark_y;
+ Dimension cascade_y;
+ Dimension underline_x;
+ Dimension underline_y;
+ Dimension underline_width;
+
+ Boolean mnemonicMatch;
+ Boolean cascadeEnabled;
+ Boolean inverted;
+
+ unsigned int accelEventType;
+ KeyCode accelDetail;
+ unsigned int accelModifiers;
+
+ Pixmap labelPixmap;
+ Pixmap markPixmap;
+ Pixmap cascadePixmap;
+ Pixmap invertLabelPixmap;
+ Pixmap invertMarkPixmap;
+ Pixmap invertCascadePixmap;
+ XImage * defMarkImage;
+ XImage * defCascadeImage;
+
+ GC inverted_GC;
+ GC defPixmap_GC;
+ GC invertPixmap_GC;
+ GC rect_GC;
+
+} XwMenuButtonPart;
+
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwMenuButtonRec {
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwButtonPart button;
+ XwMenuButtonPart menubutton;
+} XwMenuButtonRec;
+
+
+
+
diff --git a/Xw/MenuMgr.c b/Xw/MenuMgr.c
new file mode 100644
index 0000000..c928686
--- /dev/null
+++ b/Xw/MenuMgr.c
@@ -0,0 +1,652 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MenuMgr.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Menu Manager Meta Class Widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <X11/Xatom.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+
+static void Initialize();
+static void Destroy();
+static Boolean SetValues();
+static void ClassInitialize();
+
+
+/****************************************************************
+ *
+ * MenuPane Resources
+ *
+ ****************************************************************/
+
+static XtResource resources[] = {
+ {XtNassociateChildren, XtCAssociateChildren, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwMenuMgrWidget, menu_mgr.associateChildren), XtRString,
+ "TRUE"},
+
+ {XtNmenuPost, XtCMenuPost, XtRString, sizeof(String),
+ XtOffset(XwMenuMgrWidget, menu_mgr.postString), XtRString,
+ "<Btn1Down>"},
+
+ {XtNmenuSelect, XtCMenuSelect, XtRString, sizeof(String),
+ XtOffset(XwMenuMgrWidget, menu_mgr.selectString), XtRString,
+ "<Btn1Up>"},
+
+ {XtNmenuUnpost, XtCMenuUnpost, XtRString, sizeof(String),
+ XtOffset(XwMenuMgrWidget, menu_mgr.unpostString), XtRString,
+ NULL},
+
+ {XtNkbdSelect, XtCKbdSelect, XtRString, sizeof(String),
+ XtOffset(XwMenuMgrWidget, menu_mgr.kbdSelectString), XtRString,
+ "<Key>Select"}
+};
+
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+XwMenuMgrClassRec XwmenumgrClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwmanagerClassRec,
+ /* class_name */ "XwMenuMgr",
+ /* widget_size */ sizeof(XwMenuMgrRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ NULL,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ NULL,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* PRIVATE cb list */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },{
+/* composite_class fields */
+ /* geometry_manager */ NULL,
+ /* change_managed */ NULL,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ NULL,
+ },{
+/* constraint class fields */
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ NULL,
+ },{
+/* manager_class fields */
+ /* traversal handler */ NULL,
+ /* translations */ NULL,
+ },{
+/* menu manager class - none */
+ /* attachPane */ NULL,
+ /* detachPane */ NULL,
+ /* addPane */ NULL,
+ /* setSelectAccelerar */ NULL,
+ /* clearSelectAcceler */ NULL,
+ /* setPostMnemonic */ NULL,
+ /* clearPostMnemonic */ NULL,
+ /* addButton */ NULL,
+ /* processSelect */ NULL,
+ /* validEvent */ NULL,
+ /* doICascade */ NULL,
+ /* setSelectMnemonic */ NULL,
+ /* clearSelectMnemon */ NULL,
+ /* setTitleAttributes */ NULL,
+ /* paneManagedChildren*/ NULL,
+ /* traverseLeft */ NULL,
+ /* traverseRight */ NULL,
+ /* traverseNext */ NULL,
+ /* traversePrev */ NULL,
+ /* traverseHome */ NULL,
+ /* traverseUp */ NULL,
+ /* traverseDown */ NULL,
+ /* traverseNextTop */ NULL,
+ /* btnSensitivityChan */ NULL,
+ /* paneSensitivityCha */ NULL,
+ }
+};
+
+WidgetClass XwmenumgrWidgetClass = (WidgetClass)&XwmenumgrClassRec;
+
+
+/*************************************<->*************************************
+ *
+ * ClassInitialize(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassInitialize ()
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ *
+ * Description:
+ * -----------
+ * Initialize the menu_mgr fields within the widget's instance structure.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Initialize (request, new)
+
+ XwMenuMgrWidget request, new;
+
+{
+ KeySym tempKeysym;
+
+ /* FOR NOW, MENUS DO NOT UNDERSTAND TRAVERSAL */
+ /* new->manager.traversal_on = FALSE; */
+
+ /*
+ * Save a copy of the posting event string, and also convert it
+ * into a form which can be compared against an X button event.
+ */
+ if ((new->menu_mgr.postString) &&
+ (strlen(new->menu_mgr.postString) > 0))
+ {
+ if (_XwMapBtnEvent (new->menu_mgr.postString,
+ &new->menu_mgr.postEventType,
+ &new->menu_mgr.postButton,
+ &new->menu_mgr.postModifiers) == FALSE)
+ {
+ /* String was not valid; use the default one */
+ XtWarning("MenuMgr: Invalid post event; using <Btn1Down>");
+ new->menu_mgr.postString = (String) strcpy (XtMalloc (XwStrlen
+ ("<Btn1Down>") + 1), "<Btn1Down>");
+
+ _XwMapBtnEvent ("<Btn1Down>",
+ &new->menu_mgr.postEventType,
+ &new->menu_mgr.postButton,
+ &new->menu_mgr.postModifiers);
+ }
+ else
+ {
+ /* String was valid */
+ new->menu_mgr.postString = (String) strcpy (XtMalloc (XwStrlen
+ (new->menu_mgr.postString) + 1), new->menu_mgr.postString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.postString = NULL;
+ new->menu_mgr.postModifiers = 0;
+ new->menu_mgr.postButton = 0;
+ }
+
+ /*
+ * Save a copy of the selecting event string, and also convert it
+ * into a form which can be compared against an X button event.
+ */
+ if ((new->menu_mgr.selectString) &&
+ (strlen(new->menu_mgr.selectString) > 0))
+ {
+ if (_XwMapBtnEvent (new->menu_mgr.selectString,
+ &new->menu_mgr.selectEventType,
+ &new->menu_mgr.selectButton,
+ &new->menu_mgr.selectModifiers) == FALSE)
+ {
+ /* String was not valid; use the default one */
+ XtWarning("MenuMgr: Invalid select event; using <Btn1Up>");
+ new->menu_mgr.selectString = (String) strcpy (XtMalloc (XwStrlen
+ ("<Btn1Up>") + 1), "<Btn1Up>");
+
+ _XwMapBtnEvent ("<Btn1Up>",
+ &new->menu_mgr.selectEventType,
+ &new->menu_mgr.selectButton,
+ &new->menu_mgr.selectModifiers);
+ }
+ else
+ {
+ /* String was valid */
+ new->menu_mgr.selectString = (String) strcpy (XtMalloc (XwStrlen
+ (new->menu_mgr.selectString) + 1), new->menu_mgr.selectString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.selectString = NULL;
+ new->menu_mgr.selectModifiers = 0;
+ new->menu_mgr.selectButton = 0;
+ }
+
+ /*
+ * Save a copy of the unposting event string, and also convert it
+ * into a form which can be compared against an X button event.
+ */
+ if ((new->menu_mgr.unpostString) &&
+ (strlen(new->menu_mgr.unpostString) > 0))
+ {
+ if (_XwMapKeyEvent (new->menu_mgr.unpostString,
+ &new->menu_mgr.unpostEventType,
+ &tempKeysym,
+ &new->menu_mgr.unpostModifiers) == FALSE)
+ {
+ /* String was not valid; use the default one */
+ XtWarning("MenuMgr: Invalid unpost event; disabling option");
+ new->menu_mgr.unpostString = NULL;
+ }
+ else
+ {
+ /* String was valid */
+ new->menu_mgr.unpostKey = XKeysymToKeycode(XtDisplay(new),tempKeysym);
+ new->menu_mgr.unpostString = (String) strcpy (XtMalloc (XwStrlen
+ (new->menu_mgr.unpostString) + 1), new->menu_mgr.unpostString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.unpostString = NULL;
+ new->menu_mgr.unpostModifiers = 0;
+ new->menu_mgr.unpostKey = 0;
+ }
+
+ /*
+ * Save a copy of the kbd select event string, and also convert it
+ * into a form which can be compared against an X key event.
+ */
+ if ((new->menu_mgr.kbdSelectString) &&
+ (strlen(new->menu_mgr.kbdSelectString) > 0))
+ {
+ if (_XwMapKeyEvent (new->menu_mgr.kbdSelectString,
+ &new->menu_mgr.kbdSelectEventType,
+ &tempKeysym,
+ &new->menu_mgr.kbdSelectModifiers) == FALSE)
+ {
+ /* String was not valid; use the default one */
+ XtWarning("MenuMgr: Invalid keyboard select event; using default");
+ new->menu_mgr.kbdSelectString = (String) strcpy (XtMalloc (XwStrlen
+ ("<Key>Select") + 1), "<Key>Select");
+
+ _XwMapKeyEvent ("<Key>Select",
+ &new->menu_mgr.kbdSelectEventType,
+ &new->menu_mgr.kbdSelectKey,
+ &new->menu_mgr.kbdSelectModifiers);
+ }
+ else
+ {
+ /* String was valid */
+ new->menu_mgr.kbdSelectKey =
+ XKeysymToKeycode(XtDisplay(new),tempKeysym);
+ new->menu_mgr.kbdSelectString = (String) strcpy (XtMalloc (XwStrlen
+ (new->menu_mgr.kbdSelectString) + 1),
+ new->menu_mgr.kbdSelectString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.kbdSelectString = NULL;
+ new->menu_mgr.kbdSelectModifiers = 0;
+ new->menu_mgr.kbdSelectKey = 0;
+ }
+
+
+ /* Allocate space for each of the tables used by a menu manager */
+ new->menu_mgr.menuBtnAccelTable =
+ (XwKeyAccel *) XtMalloc(100 * sizeof(XwKeyAccel));
+ new->menu_mgr.numAccels = 0;
+ new->menu_mgr.sizeAccelTable = 100;
+
+ new->menu_mgr.pendingAttachList =
+ (XwAttachList *) XtMalloc(25 * sizeof(XwAttachList));
+ new->menu_mgr.numAttachReqs = 0;
+ new->menu_mgr.sizeAttachList = 25;
+
+
+ /* Set menu flags */
+ new->menu_mgr.menuActive = FALSE;
+} /* Initialize */
+
+
+/*************************************<->*************************************
+ *
+ * SetValues()
+ *
+ * Description:
+ * -----------
+ *
+ * This procedure simply checks to see if the post or select specification
+ * has changed, and allocates space for the new string and frees up the
+ * old string. It will also map the new specification into a button/
+ * modifier pair.
+ *
+ * NOTE: When a new post or select string is specified, this routine will
+ * allocate space for the new string, but will NOT free up the old
+ * string; thus, our subclasses can check to see if these strings
+ * differ, and can remove any translations. It is then upto the
+ * subclass to free the old string and to modify any translations or
+ * button grabs which are associated with the post or select actions.
+ *
+ * It is also the responsibility of the subclass to check the state
+ * of the 'associate children' flag, and to modify any corresponding
+ * translations or grabs.
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues (current, request, new)
+
+ XwMenuMgrWidget current, request, new;
+
+{
+ KeySym tempKeysym;
+
+ /* FOR NOW, MENUS DO NOT UNDERSTAND TRAVERSAL */
+ /* new->manager.traversal_on = FALSE; */
+
+ /* Handle the case of a changed posting string */
+
+ if (current->menu_mgr.postString != new->menu_mgr.postString)
+ {
+ /* Allocate a new buffer to hold the string */
+ if ((new->menu_mgr.postString) &&
+ (strlen(new->menu_mgr.postString) > 0))
+ {
+ if (_XwMapBtnEvent (new->menu_mgr.postString,
+ &new->menu_mgr.postEventType,
+ &new->menu_mgr.postButton,
+ &new->menu_mgr.postModifiers) == FALSE)
+ {
+ /* Invalid post string; use the previous one */
+ XtWarning("MenuMgr: Invalid post event; using previous setting");
+ new->menu_mgr.postString = current->menu_mgr.postString;
+ new->menu_mgr.postEventType = current->menu_mgr.postEventType;
+ new->menu_mgr.postButton = current->menu_mgr.postButton;
+ new->menu_mgr.postModifiers = current->menu_mgr.postModifiers;
+ }
+ else
+ {
+ /* Valid post string */
+ new->menu_mgr.postString = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_mgr.postString) + 1),
+ new->menu_mgr.postString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.postString = NULL;
+ new->menu_mgr.postEventType = 0;
+ new->menu_mgr.postButton = 0;
+ new->menu_mgr.postModifiers = 0;
+ }
+
+ /*
+ * Don't free up the buffer holding the old post string.
+ * This is to be done by our subclass.
+ */
+ }
+
+ /* Handle the case of a changed select string */
+
+ if (current->menu_mgr.selectString != new->menu_mgr.selectString)
+ {
+ /* Allocate a new buffer to hold the string */
+ if ((new->menu_mgr.selectString) &&
+ (strlen(new->menu_mgr.selectString) > 0))
+ {
+ if (_XwMapBtnEvent (new->menu_mgr.selectString,
+ &new->menu_mgr.selectEventType,
+ &new->menu_mgr.selectButton,
+ &new->menu_mgr.selectModifiers) == FALSE)
+ {
+ /* Invalid select string; use the previous one */
+ XtWarning("MenuMgr: Invalid select event; using previous setting");
+ new->menu_mgr.selectString = current->menu_mgr.selectString;
+ new->menu_mgr.selectEventType = current->menu_mgr.selectEventType;
+ new->menu_mgr.selectButton = current->menu_mgr.selectButton;
+ new->menu_mgr.selectModifiers = current->menu_mgr.selectModifiers;
+ }
+ else
+ {
+ /* Valid select string */
+ new->menu_mgr.selectString = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_mgr.selectString) + 1),
+ new->menu_mgr.selectString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.selectString = NULL;
+ new->menu_mgr.selectEventType = 0;
+ new->menu_mgr.selectButton = 0;
+ new->menu_mgr.selectModifiers = 0;
+ }
+
+ /*
+ * Don't free up the buffer holding the old select string.
+ * This is to be done by our subclass.
+ */
+ }
+
+ /* Handle the case of a changed unposting string */
+
+ if (current->menu_mgr.unpostString != new->menu_mgr.unpostString)
+ {
+ /* Allocate a new buffer to hold the string */
+ if ((new->menu_mgr.unpostString) &&
+ (strlen(new->menu_mgr.unpostString) > 0))
+ {
+ if (_XwMapKeyEvent (new->menu_mgr.unpostString,
+ &new->menu_mgr.unpostEventType,
+ &tempKeysym,
+ &new->menu_mgr.unpostModifiers) == FALSE)
+ {
+ /* Invalid unpost string; use the previous one */
+ XtWarning("MenuMgr: Invalid unpost event; using previous setting");
+ new->menu_mgr.unpostString = current->menu_mgr.unpostString;
+ new->menu_mgr.unpostEventType = current->menu_mgr.unpostEventType;
+ new->menu_mgr.unpostKey = current->menu_mgr.unpostKey;
+ new->menu_mgr.unpostModifiers = current->menu_mgr.unpostModifiers;
+ }
+ else
+ {
+ /* Valid unpost string */
+ new->menu_mgr.unpostKey = XKeysymToKeycode(XtDisplay(new),
+ tempKeysym);
+ new->menu_mgr.unpostString = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_mgr.unpostString) + 1),
+ new->menu_mgr.unpostString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.unpostString = NULL;
+ new->menu_mgr.unpostEventType = 0;
+ new->menu_mgr.unpostKey = 0;
+ new->menu_mgr.unpostModifiers = 0;
+ }
+
+ /*
+ * Don't free up the buffer holding the old unpost string.
+ * This is to be done by our subclass.
+ */
+ }
+
+ /* Handle the case of a changed kbd select string */
+
+ if (current->menu_mgr.kbdSelectString != new->menu_mgr.kbdSelectString)
+ {
+ /* Allocate a new buffer to hold the string */
+ if ((new->menu_mgr.kbdSelectString) &&
+ (strlen(new->menu_mgr.kbdSelectString) > 0))
+ {
+ if (_XwMapKeyEvent (new->menu_mgr.kbdSelectString,
+ &new->menu_mgr.kbdSelectEventType,
+ &tempKeysym,
+ &new->menu_mgr.kbdSelectModifiers) == FALSE)
+ {
+ /* Invalid kbd select string; use the previous one */
+ XtWarning
+ ("MenuMgr: Invalid keyboard select event; using previous setting");
+ new->menu_mgr.kbdSelectString = current->menu_mgr.kbdSelectString;
+ new->menu_mgr.kbdSelectEventType =
+ current->menu_mgr.kbdSelectEventType;
+ new->menu_mgr.kbdSelectKey = current->menu_mgr.kbdSelectKey;
+ new->menu_mgr.kbdSelectModifiers =
+ current->menu_mgr.kbdSelectModifiers;
+ }
+ else
+ {
+ /* Valid kbd select string */
+ new->menu_mgr.kbdSelectKey = XKeysymToKeycode(XtDisplay(new),
+ tempKeysym);
+ new->menu_mgr.kbdSelectString = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_mgr.kbdSelectString) + 1),
+ new->menu_mgr.kbdSelectString);
+ }
+ }
+ else
+ {
+ new->menu_mgr.kbdSelectString = NULL;
+ new->menu_mgr.kbdSelectEventType = 0;
+ new->menu_mgr.kbdSelectKey = 0;
+ new->menu_mgr.kbdSelectModifiers = 0;
+ }
+
+ /*
+ * Don't free up the buffer holding the old kbd select string.
+ * This is to be done by our subclass.
+ */
+ }
+
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Destroy
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Destroy (mw)
+
+ XwMenuMgrWidget mw;
+
+{
+ /* Free up our resources */
+
+ if (mw->menu_mgr.postString)
+ XtFree (mw->menu_mgr.postString);
+
+ if (mw->menu_mgr.selectString)
+ XtFree (mw->menu_mgr.selectString);
+
+ if (mw->menu_mgr.unpostString)
+ XtFree (mw->menu_mgr.unpostString);
+
+ if (mw->menu_mgr.kbdSelectString)
+ XtFree (mw->menu_mgr.kbdSelectString);
+
+ XtFree ((char *)(mw->menu_mgr.menuBtnAccelTable));
+ XtFree ((char *)(mw->menu_mgr.pendingAttachList));
+}
+
diff --git a/Xw/MenuPane.c b/Xw/MenuPane.c
new file mode 100644
index 0000000..bf3c0d4
--- /dev/null
+++ b/Xw/MenuPane.c
@@ -0,0 +1,855 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: MenuPane.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Menu Pane Meta Class Widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <X11/Xatom.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+
+static void Initialize();
+static void Destroy();
+static Boolean SetValues();
+static void GetFontGC();
+static void InsertChild();
+static void ConstraintInitialize();
+static void ClassPartInitialize();
+static void SetTraversalFlag();
+
+
+/****************************************************************
+ *
+ * MenuPane Resources
+ *
+ ****************************************************************/
+
+static XtResource resources[] = {
+ {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(XwMenuPaneWidget, menu_pane.title_font), XtRString, "fixed"},
+
+ {XtNtitleString, XtCTitleString, XtRString, sizeof(caddr_t),
+ XtOffset(XwMenuPaneWidget, menu_pane.title_string), XtRString, NULL},
+
+ {XtNtitleImage, XtCTitleImage, XtRImage, sizeof(XImage *),
+ XtOffset(XwMenuPaneWidget, menu_pane.titleImage), XtRImage, NULL},
+
+ {XtNtitleShowing, XtCTitleShowing, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwMenuPaneWidget, menu_pane.title_showing), XtRString, "TRUE"},
+
+ {XtNattachTo, XtCAttachTo, XtRString, sizeof(String),
+ XtOffset(XwMenuPaneWidget, menu_pane.attach_to), XtRString, NULL},
+
+ {XtNmgrTitleOverride, XtCTitleOverride, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwMenuPaneWidget, menu_pane.title_override), XtRString,
+ "FALSE"},
+
+ {XtNtitleType, XtCTitleType, XtRTitleType, sizeof(int),
+ XtOffset(XwMenuPaneWidget, menu_pane.title_type), XtRString, "string"},
+
+ {XtNmnemonic, XtCMnemonic, XtRString, sizeof(String),
+ XtOffset(XwMenuPaneWidget, menu_pane.mnemonic),XtRString,NULL},
+
+ {XtNselect, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset(XwMenuPaneWidget, menu_pane.select), XtRPointer, NULL}
+};
+
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+XwMenuPaneClassRec XwmenupaneClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwmanagerClassRec,
+ /* class_name */ "XwMenuPane",
+ /* widget_size */ sizeof(XwMenuPaneRec),
+ /* class_initialize */ NULL,
+ /* class_part_init */ ClassPartInitialize,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ NULL,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ NULL,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* PRIVATE cb list */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },{
+/* composite_class fields */
+ /* geometry_manager */ NULL,
+ /* change_managed */ NULL,
+ /* insert_child */ InsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ NULL,
+ },{
+/* constraint class fields */
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* Constraint_size */ sizeof (Boolean),
+ /* initialize */ ConstraintInitialize,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ NULL,
+ },{
+/* manager_class fields */
+ /* traversal handler */ NULL,
+ /* translations */ NULL,
+ },{
+/* menu pane class - none */
+ /* setTraversalFlag */ (XwWBoolProc) SetTraversalFlag
+ }
+};
+
+WidgetClass XwmenupaneWidgetClass = (WidgetClass)&XwmenupaneClassRec;
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassPartInitialize (wc)
+
+ register XwMenuPaneWidgetClass wc;
+
+{
+ if (wc->constraint_class.initialize == XtInheritMenuPaneConstraintInit)
+ wc->constraint_class.initialize = (XtInitProc) ClassPartInitialize;
+
+ if (wc->menu_pane_class.setTraversalFlag == XtInheritSetTraversalFlagProc)
+ wc->menu_pane_class.setTraversalFlag = (XwWBoolProc) SetTraversalFlag;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ConstraintInitialize (request, new)
+
+ Widget request;
+ Widget new;
+
+{
+ Boolean * managed_and_mapped;
+
+ managed_and_mapped = (Boolean *) new->core.constraints;
+
+ /* Widgets are never managed when they are first created */
+ *managed_and_mapped = FALSE;
+}
+
+
+/*************************************<->*************************************
+ *
+ * ProcedureName (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void InsertChild (w)
+ Widget w;
+{
+ CompositeWidgetClass composite;
+ Widget parent, grandparent, greatgrandparent;
+
+ /* Invoke our superclass's insert_child procedure */
+ composite = (CompositeWidgetClass)
+ XwmenupaneWidgetClass->core_class.superclass;
+
+ (*(composite->composite_class.insert_child)) (w);
+
+ /* Call menu mgr's AddButton() procedure */
+ if ((parent = (Widget) XtParent(w)) &&
+ (grandparent = (Widget) XtParent(parent)) &&
+ (greatgrandparent = (Widget) XtParent(grandparent)) &&
+ (XtIsSubclass (greatgrandparent, XwmenumgrWidgetClass)))
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(greatgrandparent))->menu_mgr_class.
+ addButton) (greatgrandparent, w);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ *
+ * Description:
+ * -----------
+ * Initialize the menu_pane fields within the widget's instance structure.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Initialize (request, new)
+ XwMenuPaneWidget request, new;
+{
+ Widget parent, grandparent;
+ KeySym tempKeysym;
+
+ /*
+ * Always force traversal off for a menupane. We inherit our
+ * traversal setting from our menu manager, and it will take
+ * care of setting us to the correct state.
+ */
+ new->manager.traversal_on = FALSE;
+
+ new->menu_pane.attachId = NULL;
+
+ /* Call menu mgr's AddPane() procedure */
+ if ((parent = (Widget) XtParent(new)) &&
+ (grandparent = (Widget) XtParent(parent)) &&
+ (XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.addPane)
+ (grandparent, (Widget)new);
+ }
+ else
+ grandparent = NULL;
+
+
+ /* Get the GC used to display the title string/image */
+ GetFontGC (new);
+
+ /* Save a copy of the title string, if present */
+ if (new->menu_pane.title_string)
+ {
+ new->menu_pane.title_string = (String)
+ strcpy(XtMalloc(XwStrlen(new->menu_pane.title_string) + 1),
+ new->menu_pane.title_string);
+ }
+ else
+ {
+ /* Set a default title string: the widget name */
+ new->menu_pane.title_string = (String)
+ strcpy(XtMalloc(XwStrlen(new->core.name) + 1),
+ new->core.name);
+ }
+
+ /* Save a copy of the accelerator string, if present */
+ if ((new->menu_pane.mnemonic) && (*(new->menu_pane.mnemonic) != '\0'))
+ {
+ /* Valid mnemonic specified */
+ char mne = new->menu_pane.mnemonic[0];
+
+ new->menu_pane.mnemonic = (String)XtMalloc(2);
+ new->menu_pane.mnemonic[0] = mne;
+ new->menu_pane.mnemonic[1] = '\0';
+
+ /* Register it with the menu manager */
+ if (grandparent)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ setPostMnemonic) (grandparent, (Widget)new, new->menu_pane.mnemonic);
+ }
+ }
+ else
+ {
+ if (new->menu_pane.mnemonic)
+ XtWarning ("MenuPane: Invalid mnemonic; disabling feature");
+ new->menu_pane.mnemonic = NULL;
+ }
+
+ /* Save a copy of the attach string, if present */
+ if (new->menu_pane.attach_to)
+ {
+ new->menu_pane.attach_to = (String)
+ strcpy(XtMalloc(XwStrlen(new->menu_pane.attach_to) + 1),
+ new->menu_pane.attach_to);
+
+ /* Call menu mgr's AttachPane() procedure */
+ if (grandparent)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ attachPane) (grandparent, (Widget)new, new->menu_pane.attach_to);
+ }
+ }
+
+} /* Initialize */
+
+
+/*************************************<->*************************************
+ *
+ * SetValues
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues (current, request, new)
+ XwMenuPaneWidget current, request, new;
+{
+ Boolean redrawFlag = FALSE;
+ Boolean titleAttributeChange = FALSE;
+ Widget parent, grandparent;
+ KeySym tempKeysym;
+
+ /* We never allow our traversal flag to change using SetValues() */
+ new->manager.traversal_on = current->manager.traversal_on;
+
+ /* Determine if we are being controlled by a menu manager */
+ if (((parent = (Widget) XtParent(new)) == NULL) ||
+ ((grandparent = (Widget) XtParent(parent)) == NULL) ||
+ (!XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
+ {
+ grandparent = NULL;
+ }
+
+ if ((new->menu_pane.title_type != XwSTRING) &&
+ (new->menu_pane.title_type != XwIMAGE))
+ {
+ XtWarning("MenuPane: Invalid title type; using previous setting");
+ new->menu_pane.title_type = current->menu_pane.title_type;
+ }
+
+ if ((current->menu_pane.title_showing != new->menu_pane.title_showing) ||
+ (current->menu_pane.title_override != new->menu_pane.title_override))
+ {
+ redrawFlag = TRUE;
+ }
+
+ /* Handle the case of a changed title string or image */
+
+ if (current->menu_pane.title_string != new->menu_pane.title_string)
+ {
+ /* Allocate a new buffer to hold the string */
+ if (new->menu_pane.title_string)
+ {
+ new->menu_pane.title_string = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_pane.title_string) + 1),
+ new->menu_pane.title_string);
+ }
+ else
+ {
+ /* Assign a default title: the widget name */
+ new->menu_pane.title_string = (String)
+ strcpy (XtMalloc (XwStrlen (new->core.name) + 1),
+ new->core.name);
+ }
+
+ /*
+ * Free up the buffer holding the old title string.
+ * XtFree() is smart enough to catch a NULL pointer.
+ */
+ XtFree (current->menu_pane.title_string);
+
+ if (new->menu_pane.title_type == XwSTRING)
+ {
+ titleAttributeChange = TRUE;
+
+ if (new->menu_pane.title_showing)
+ redrawFlag = TRUE;
+ }
+ }
+
+ if (current->menu_pane.titleImage != new->menu_pane.titleImage)
+ {
+ /*
+ * Depending upon whether the depth of the title image can change,
+ * we may need to generate a new GC, which will be used by our call
+ * to XPutImage(). However, I don't believe this is the case.
+ */
+
+ if (new->menu_pane.title_type == XwIMAGE)
+ {
+ titleAttributeChange = TRUE;
+
+ if (new->menu_pane.title_showing)
+ redrawFlag = TRUE;
+ }
+ }
+
+ if (current->menu_pane.title_type != new->menu_pane.title_type)
+ {
+ redrawFlag = TRUE;
+ titleAttributeChange = TRUE;
+ }
+
+
+ /* Determine if the menu manager needs to attach us elsewhere */
+
+ if (current->menu_pane.attach_to != new->menu_pane.attach_to)
+ {
+ /* Allocate a new buffer to hold the string */
+ if (new->menu_pane.attach_to)
+ {
+ new->menu_pane.attach_to = (String)
+ strcpy (XtMalloc (XwStrlen (new->menu_pane.attach_to) + 1),
+ new->menu_pane.attach_to);
+ }
+
+ /* Call menu mgr's DetachPane() procedure */
+ if (grandparent)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ detachPane) (grandparent, (Widget)new, current->menu_pane.attach_to);
+ }
+
+ /*
+ * Free up the buffer holding the old attach string.
+ * XtFree() is smart enough to catch a NULL pointer.
+ */
+ XtFree (current->menu_pane.attach_to);
+
+ /* Call menu mgr's AttachPane() procedure */
+ if (grandparent)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ attachPane) (grandparent, (Widget)new, new->menu_pane.attach_to);
+ }
+ }
+
+ /* Determine if the post mnemonic needs to be changed */
+
+ if (current->menu_pane.mnemonic != new->menu_pane.mnemonic)
+ {
+ if (new->menu_pane.mnemonic)
+ {
+ if (*(new->menu_pane.mnemonic) == '\0')
+ {
+ /* Invalid string; revert to previous one */
+ XtWarning
+ ("MenuPane: Invalid post mnemonic; using previous setting");
+ new->menu_pane.mnemonic = current->menu_pane.mnemonic;
+ }
+ else
+ {
+ /* Valid string; remove old mnemonic, and add new one */
+ char mne = new->menu_pane.mnemonic[0];
+
+ new->menu_pane.mnemonic = (String) XtMalloc(2);
+ new->menu_pane.mnemonic[0] = mne;
+ new->menu_pane.mnemonic[1] = '\0';
+
+ if (grandparent && current->menu_pane.mnemonic)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ clearPostMnemonic) (grandparent, (Widget)current);
+ }
+
+ if (grandparent)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ setPostMnemonic) (grandparent, (Widget)new,
+ new->menu_pane.mnemonic);
+ }
+ XtFree (current->menu_pane.mnemonic);
+ }
+ }
+ else
+ {
+ /* Remove old accelerator */
+ if (grandparent && current->menu_pane.mnemonic)
+ {
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ clearPostMnemonic) (grandparent, (Widget)current);
+ }
+
+ new->menu_pane.mnemonic = NULL;
+
+ XtFree(current->menu_pane.mnemonic);
+ }
+ }
+
+
+ /* Force a redraw and get a new GC if the font attributes change */
+
+ if ((current->manager.foreground != new->manager.foreground) ||
+ (current->menu_pane.title_font->fid != new->menu_pane.title_font->fid))
+ {
+ XtDestroyGC (current->menu_pane.titleGC);
+ GetFontGC (new);
+ redrawFlag = TRUE;
+ titleAttributeChange = TRUE;
+ }
+
+ if ((current->core.background_pixel != new->core.background_pixel) ||
+ (current->manager.background_tile != new->manager.background_tile))
+ {
+ titleAttributeChange = TRUE;
+ }
+
+ if (((new->core.sensitive != current->core.sensitive) ||
+ (new->core.ancestor_sensitive != current->core.ancestor_sensitive)) &&
+ grandparent)
+ {
+ /* Call menu mgr's paneSensitivityChanged() procedure */
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ paneSensitivityChanged) (grandparent, (Widget)new);
+ }
+
+ if (titleAttributeChange && grandparent)
+ {
+ /* Call menu mgr's SetTitleAttributes() procedure */
+ (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
+ setTitleAttributes) (grandparent, (Widget)new);
+ }
+
+
+ return (redrawFlag);
+}
+
+
+/*************************************<->*************************************
+ *
+ * GetFontGC
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void GetFontGC (mw)
+
+ XwMenuPaneWidget mw;
+
+{
+ XGCValues values;
+
+ values.foreground = mw->manager.foreground;
+ values.background = mw->core.background_pixel;
+ values.font = mw->menu_pane.title_font->fid;
+ values.line_width = 1;
+ values.line_style = LineSolid;
+ values.function = GXcopy;
+ values.plane_mask = AllPlanes;
+ values.subwindow_mode = ClipByChildren;
+ values.clip_x_origin = 0;
+ values.clip_y_origin = 0;
+ values.clip_mask = None;
+
+ mw->menu_pane.titleGC = XtGetGC ((Widget)mw, GCForeground | GCFont |
+ GCFunction | GCLineWidth | GCLineStyle |
+ GCBackground | GCPlaneMask | GCSubwindowMode |
+ GCClipXOrigin | GCClipYOrigin | GCClipMask,
+ &values);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Destroy
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Destroy (mw)
+
+ XwMenuPaneWidget mw;
+
+{
+ /* Free up our resources */
+
+ if (mw->menu_pane.title_string)
+ XtFree (mw->menu_pane.title_string);
+
+ if (mw->menu_pane.attach_to)
+ XtFree (mw->menu_pane.attach_to);
+
+ if (mw->menu_pane.mnemonic)
+ XtFree (mw->menu_pane.mnemonic);
+
+ XtDestroyGC (mw->menu_pane.titleGC);
+
+ XtRemoveCallbacks ((Widget)mw, XtNselect, mw->menu_pane.select);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwSetMappedManagedChildrenList (parameters)
+ *
+ * Description:
+ * -----------
+ * MenuPane widgets are only interested in using their children
+ * which are both managed and mapped_when_managed, during layout
+ * calculations. This global routine traverses the list of
+ * children for the specified manager widget, and constructs a
+ * parallel list of only those children meeting the above criteria.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+void _XwSetMappedManagedChildrenList (mw)
+
+ XwManagerWidget mw;
+
+{
+ int i;
+
+ mw->manager.num_managed_children = 0;
+
+ for (i = 0; i < mw->composite.num_children; i++)
+ {
+ if ((mw->composite.children[i]->core.managed) &&
+ (mw->composite.children[i]->core.mapped_when_managed))
+ {
+ /* Add to list */
+ if ((mw->manager.num_managed_children + 1) >
+ mw->manager.num_slots)
+ {
+ /* Grow the list */
+ mw->manager.num_slots += XwBLOCK;
+ mw->manager.managed_children = (WidgetList)
+ XtRealloc ((caddr_t)mw->manager.managed_children,
+ (mw->manager.num_slots * sizeof(Widget)));
+ }
+
+ mw->manager.managed_children [mw->manager.num_managed_children++] =
+ mw->composite.children[i];
+ }
+ }
+
+ /*
+ * In case this has been called during a SetValues on the pane,
+ * we want to make sure that both the new and old widgets get
+ * properly updated.
+ */
+ ((XwManagerWidget)mw->core.self)->manager.num_managed_children =
+ mw->manager.num_managed_children;
+ ((XwManagerWidget)mw->core.self)->manager.managed_children =
+ mw->manager.managed_children;
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetTraversalFlag(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetTraversalFlag (w, enableFlag)
+
+ XwMenuPaneWidget w;
+ Boolean enableFlag;
+
+{
+ w->manager.traversal_on = enableFlag;
+
+ if (enableFlag == True)
+ {
+ XtAugmentTranslations ((Widget)w, XwmanagerClassRec.manager_class.
+ translations);
+ w->core.widget_class->core_class.visible_interest = True;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwAllAttachesAreSensitive(parameters)
+ *
+ * Description:
+ * -----------
+ * This functions verifies that the path from a menubutton back upto
+ * the top level menupane has no insensitive widgets (panes or buttons)
+ * in it.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+Boolean _XwAllAttachesAreSensitive (menuBtn)
+
+ Widget menuBtn;
+
+{
+ XwMenuPaneWidget parent;
+
+ while (menuBtn != NULL)
+ {
+ parent = (XwMenuPaneWidget)XtParent(menuBtn);
+
+ if (!XtIsSensitive((Widget)parent) || !XtIsSensitive(menuBtn))
+ return (False);
+
+ menuBtn = (Widget) parent->menu_pane.attachId;
+ }
+
+ return (True);
+}
diff --git a/Xw/PButton.c b/Xw/PButton.c
new file mode 100644
index 0000000..187a3f2
--- /dev/null
+++ b/Xw/PButton.c
@@ -0,0 +1,640 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PButton.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains code for primitive widget class: PushButton
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/*
+ * Include files & Static Routine Definitions
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/PButtonP.h>
+#include <Xw/PButton.h>
+#include <X11/keysymdef.h>
+
+
+#define PB_BW 2
+
+
+static void Redisplay();
+static void RedrawButtonFace();
+static Boolean SetValues();
+static void ClassInitialize();
+static void Initialize();
+static void Toggle();
+static void ToggleRelease();
+static void Select();
+static void Unselect();
+static void Resize();
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: default translation table for class: PushButton
+ * -----------
+ *
+ * Matches events with string descriptors for internal routines.
+ *
+ *************************************<->***********************************/
+
+static char defaultTranslations[] =
+ "<Btn1Down>: select() \n\
+ <Btn1Up>: unselect() \n\
+ <EnterWindow>: enter() \n\
+ <LeaveWindow>: leave() \n\
+ <KeyDown>Select: select() \n\
+ <KeyUp>Select: unselect()";
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: action list for class: PushButton
+ * -----------
+ *
+ * Matches string descriptors with internal routines.
+ * Note that Primitive will register additional event handlers
+ * for traversal.
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ {"toggle", (XtActionProc) Toggle},
+ {"select", (XtActionProc) Select},
+ {"unselect", (XtActionProc) Unselect},
+ {"enter", (XtActionProc) _XwPrimitiveEnter},
+ {"leave", (XtActionProc) _XwPrimitiveLeave},
+};
+
+
+/* The resource list for Push Button */
+
+static XtResource resources[] =
+{
+ {
+ XtNtoggle, XtCToggle, XtRBoolean, sizeof (Boolean),
+ XtOffset (XwPushButtonWidget, pushbutton.toggle), XtRString, "False"
+ }
+};
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: global class record for instances of class: PushButton
+ * -----------
+ *
+ * Defines default field settings for this class record.
+ *
+ *************************************<->***********************************/
+
+XwPushButtonClassRec XwpushButtonClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwbuttonClassRec,
+ /* class_name */ "XwPushButton",
+ /* widget_size */ sizeof(XwPushButtonRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ _XwRealize,
+ /* actions */ actionsList,
+ /* num_actions */ XtNumber(actionsList),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ NULL,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ }
+};
+WidgetClass XwpushButtonWidgetClass = (WidgetClass)&XwpushButtonClassRec;
+
+
+/*************************************<->*************************************
+ *
+ * Toggle (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * When this pushbutton is selected, toggle the activation state
+ * (i.e., draw it as active if it was not active and draw it as
+ * inactive if it was active). Generate the correct callbacks
+ * in response.
+ *
+ * NOTE: this code assumes that instances do not receive selection
+ * events when insensitive.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCallCallbacks() [libXtk]
+ * Redisplay [PushButton.c]
+ *************************************<->***********************************/
+
+static void Toggle (w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget)w;
+
+
+ if (pb -> button.set)
+ pb -> button.set = False;
+ else
+ pb -> button.set = True;
+
+ RedrawButtonFace (w, event, FALSE);
+ XFlush(XtDisplay(w));
+ XtCallCallbacks (w, ((pb->button.set) ? XtNselect : XtNrelease), NULL);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Select (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * Mark pushbutton as selected, (i.e., draw it as active)
+ * Generate the correct callbacks. If "toggle" flag is
+ * TRUE then call the Toggle routine.
+ *
+ * NOTE: this code assumes that instances do not receive selection
+ * events when insensitive.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCallCallbacks() [libXtk]
+ *************************************<->***********************************/
+
+static void Select (w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget) w;
+
+ if (pb->pushbutton.toggle == TRUE)
+ Toggle(w,event);
+ else
+ {
+ pb->button.set = TRUE;
+
+ RedrawButtonFace (w, event, FALSE);
+ XFlush (XtDisplay(w));
+ XtCallCallbacks (w, XtNselect, NULL);
+ }
+}
+
+
+
+
+/*************************************<->*************************************
+ *
+ * Unselect (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * When this pushbutton is unselected draw it as inactive.
+ * Generate the correct callbacks.
+ *
+ * NOTE: this code respects the utility flag "toggle" if this
+ * flag is set to true then this routine is a no op.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCallCallbacks() [libXtk]
+ *************************************<->***********************************/
+
+static void Unselect(w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget) w;
+
+
+ if (! pb->pushbutton.toggle)
+ {
+ pb->button.set = FALSE;
+
+ RedrawButtonFace (w, event, FALSE);
+ XFlush(XtDisplay(w));
+ XtCallCallbacks (w, XtNrelease, NULL);
+ }
+}
+
+
+static void ToggleRelease(w,event)
+Widget w;
+XEvent *event;
+
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget) w;
+
+ pb->button.set = FALSE;
+
+ RedrawButtonFace (w, event, FALSE);
+ XFlush(XtDisplay(w));
+ XtCallCallbacks (w, XtNrelease, NULL);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ * Description:
+ * -----------
+ * If the core height and width fields are set to 0, treat that as a flag
+ * and compute the optimum size for this button. Then using what ever
+ * the core fields are set to, compute the text placement fields.
+ * Make sure that the label location field is properly set for the
+ * Resize call.
+ *
+ *
+ * Inputs:
+ * ------
+ * request = request widget, old data.
+ *
+ * new = new widget, new data; cumulative effect
+ * of initialize procedures.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+static void Initialize (request, new)
+Widget request, new;
+
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget) new;
+
+ /********************************************************************
+ Needed width:
+ 2 * highlight thickness
+ 2 * button overhead: 2 lines for button outline
+ 2 * internal width (padding between label and button)
+ width of label
+
+ Needed height:
+ 2 * highlight thickness
+ 2 * button overhead: 2 lines for outline
+ 2 * internal height (padding)
+ label height
+
+ ************************************************************************/
+
+ if (request->core.width == 0) pb->core.width = pb->button.label_width +
+ 2 * ( pb->button.internal_width + /* white space */
+ pb->primitive.highlight_thickness + PB_BW);
+
+ if (request->core.height == 0) pb->core.height = pb->button.label_height +
+ 2 * (pb->button.internal_height + pb->primitive.highlight_thickness + PB_BW);
+
+ Resize(new);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * ClassInitialize
+ *
+ * Description:
+ * -----------
+ * Set fields in primitive class part of our class record so that
+ * the traversal code can invoke our button select procedures.
+ *
+ *************************************<->***********************************/
+
+static void ClassInitialize()
+{
+ XwpushButtonClassRec.primitive_class.select_proc = (XwEventProc) Select;
+ XwpushButtonClassRec.primitive_class.release_proc = (XwEventProc) ToggleRelease;
+ XwpushButtonClassRec.primitive_class.toggle_proc = (XwEventProc) Toggle;
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * Redisplay (w, event, region)
+ *
+ * Description:
+ * -----------
+ * Cause the widget, identified by w, to be redisplayed.
+ *
+ *
+ * Inputs:
+ * ------
+ * w = widget to be redisplayed;
+ * event = event structure identifying need for redisplay on this
+ * widget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XDrawString()
+ *************************************<->***********************************/
+
+static void Redisplay (w, event, region)
+Widget w;
+XEvent *event;
+Region region;
+
+{
+ RedrawButtonFace (w, event, TRUE);
+}
+
+
+static void RedrawButtonFace (w, event, all)
+XwPushButtonWidget w;
+XEvent *event;
+Boolean all;
+
+{
+ register XwPushButtonWidget pb = (XwPushButtonWidget) w;
+ int available_height, available_width;
+ Boolean clipHeight, clipWidth;
+
+ /* COMPUTE SPACE AVAILABLE FOR DRAWING LABEL */
+
+ available_width = Max(0,(int)pb->core.width - 2*((int)pb->button.internal_width + pb->primitive.highlight_thickness + PB_BW));
+
+ available_height = Max(0, (int)pb->core.height - 2*((int)pb->button.internal_height + pb->primitive.highlight_thickness + PB_BW));
+
+
+
+ /* SEE IF WE NEED TO CLIP THIS LABEL ON TOP AND/OR BOTTOM */
+
+ if (pb->button.label_width > available_width)
+ clipWidth = True;
+ else
+ clipWidth = False;
+
+
+ if (pb->button.label_height > available_height)
+ clipHeight = True;
+ else
+ clipHeight = False;
+
+
+
+ /* COMPUTE & DRAW PUSHBUTTON */
+
+
+
+ /* COMPUTE x LOCATION FOR STRING & DRAW STRING */
+ XFillRectangle (XtDisplay(w), XtWindow(w),
+ ((pb->button.set
+ )
+ ? pb->button.normal_GC
+ : pb->button.inverse_GC),
+ w -> primitive.highlight_thickness + 1 + PB_BW,
+ w -> primitive.highlight_thickness + 1 + PB_BW,
+ w->core.width- 2 * (w->primitive.highlight_thickness
+ + 1 + PB_BW),
+ w->core.height- 2 * (w->primitive.highlight_thickness
+ + 1 + PB_BW));
+
+ if (pb->button.label_len > 0)
+ {
+ XDrawString(XtDisplay(w), XtWindow(w),
+ ((pb->button.set
+ )
+ ? pb->button.inverse_GC
+ : pb->button.normal_GC),
+ (((int)pb->core.width + 1 - pb->button.label_width) / 2),
+ pb->button.label_y, pb->button.label,
+ pb->button.label_len);
+
+
+ if (clipWidth)
+ {
+ XClearArea (XtDisplay(w), XtWindow(w), 0,0,
+ (pb->primitive.highlight_thickness + PB_BW +
+ pb->button.internal_width), pb->core.height, FALSE);
+
+ XClearArea (XtDisplay(w), XtWindow(w),
+ ((int)pb->core.width - pb->primitive.highlight_thickness -
+ PB_BW - (int)pb->button.internal_width),0,
+ (pb->primitive.highlight_thickness + PB_BW +
+ pb->button.internal_width), pb->core.height, FALSE);
+ }
+
+ if (clipHeight)
+ {
+ XClearArea (XtDisplay(w), XtWindow(w), 0,0, pb->core.width,
+ (pb->primitive.highlight_thickness + PB_BW +
+ pb->button.internal_height), FALSE);
+ XClearArea (XtDisplay(w), XtWindow(w), 0,
+ ((int)pb->core.height - pb->primitive.highlight_thickness -
+ PB_BW - (int)pb->button.internal_height), pb->core.width,
+ (pb->primitive.highlight_thickness + PB_BW +
+ pb->button.internal_height), FALSE);
+ }
+ }
+
+
+ _XwDrawBox (XtDisplay (w), XtWindow (w),
+ w -> button.normal_GC, PB_BW,
+ w -> primitive.highlight_thickness,
+ w -> primitive.highlight_thickness,
+ w->core.width - 2 * w->primitive.highlight_thickness,
+ w->core.height - 2 * w->primitive.highlight_thickness);
+
+
+
+ /*
+ * Draw traversal/enter highlight if actual exposure or
+ * if we had to clip text area
+ */
+
+ if (all || clipWidth || clipHeight)
+ {
+ if (pb->primitive.highlighted)
+ _XwHighlightBorder(w);
+ else if (pb->primitive.display_highlighted)
+ _XwUnhighlightBorder(w);
+ }
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * SetValues(current, request, new)
+ *
+ * Description:
+ * -----------
+ * This is the set values procedure for the pushbutton class. It is
+ * called last (the set values rtnes for its superclasses are called
+ * first).
+ *
+ *
+ * Inputs:
+ * ------
+ * current = original widget;
+ * request = copy of current (?);
+ * new = copy of request which reflects changes made to it by
+ * set values procedures of its superclasses;
+ * last = TRUE if this is the last set values procedure to be called.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues(current, request, new)
+Widget current, request, new;
+
+{
+ XtWidgetGeometry reqGeo;
+ XwPushButtonWidget curpb = (XwPushButtonWidget) current;
+ XwPushButtonWidget newpb = (XwPushButtonWidget) new;
+ Boolean flag = FALSE; /* our return value */
+
+
+ /**********************************************************************
+ * Calculate the window size: The assumption here is that if
+ * the width and height are the same in the new and current instance
+ * record that those fields were not changed with set values. Therefore
+ * its okay to recompute the necessary width and height. However, if
+ * the new and current do have different width/heights then leave them
+ * alone because that's what the user wants.
+ *********************************************************************/
+ if ((curpb->core.width == newpb->core.width) &&
+ (_XwRecomputeSize(current, new)))
+ {
+ newpb->core.width =
+ newpb->button.label_width + 2*(newpb->button.internal_width +
+ newpb->primitive.highlight_thickness + PB_BW);
+ flag = TRUE;
+ }
+
+ if ((curpb->core.height == newpb->core.height) &&
+ (_XwRecomputeSize(current, new)))
+ {
+ newpb->core.height =
+ newpb->button.label_height + 2*(newpb->button.internal_height +
+ newpb->primitive.highlight_thickness + PB_BW);
+ flag = TRUE;
+ }
+
+ return(flag);
+}
+
+
+
+
+/*************************************<->*************************************
+ *
+ * Resize(w)
+ *
+ * Description:
+ * -----------
+ * Recompute location of button text
+ *
+ * Inputs:
+ * ------
+ * w = widget to be resized.
+ *
+ *
+ *************************************<->***********************************/
+
+
+static void Resize(w)
+ Widget w;
+{
+ XwPushButtonWidget pb = (XwPushButtonWidget) w;
+
+ pb->button.label_x = ((int)pb->core.width + 1 - pb->button.label_width) / 2;
+
+ pb->button.label_y =
+ ((int)pb->core.height - pb->button.label_height) / 2
+ + pb->button.font->max_bounds.ascent;
+}
diff --git a/Xw/PButton.h b/Xw/PButton.h
new file mode 100644
index 0000000..9f272d6
--- /dev/null
+++ b/Xw/PButton.h
@@ -0,0 +1,44 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PButton.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for applications using the
+ ** pushbutton widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/***********************************************************************
+ *
+ * PushButton Widget
+ *
+ ***********************************************************************/
+
+
+extern WidgetClass XwpushButtonWidgetClass;
+
+typedef struct _XwPushButtonClassRec *XwPushButtonWidgetClass;
+typedef struct _XwPushButtonRec *XwPushButtonWidget;
+
+
+
+
+
+
diff --git a/Xw/PButtonP.h b/Xw/PButtonP.h
new file mode 100644
index 0000000..d29ecd7
--- /dev/null
+++ b/Xw/PButtonP.h
@@ -0,0 +1,79 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PButtonP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for widgets which are
+ ** subclasses of push button or which need to
+ ** access directly the instance and class fields
+ ** of the pushbutton widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/********************************************
+ *
+ * No new fields need to be defined
+ * for the PushButton widget class record
+ *
+ ********************************************/
+
+typedef struct {int foo;} XwPushButtonClassPart;
+
+
+/****************************************************
+ *
+ * Full class record declaration for PushButton class
+ *
+ ****************************************************/
+typedef struct _XwPushButtonClassRec {
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwButtonClassPart button_class;
+ XwPushButtonClassPart pushbutton_class;
+} XwPushButtonClassRec;
+
+
+extern XwPushButtonClassRec XwpushButtonClassRec;
+
+
+/********************************************
+ *
+ * No new fields needed for instance record
+ *
+ ********************************************/
+
+typedef struct _XwPushButtonPart{
+ Boolean toggle;
+} XwPushButtonPart;
+
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwPushButtonRec {
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwButtonPart button;
+ XwPushButtonPart pushbutton;
+} XwPushButtonRec;
diff --git a/Xw/PopupMgr.c b/Xw/PopupMgr.c
new file mode 100644
index 0000000..4f7f7ad
--- /dev/null
+++ b/Xw/PopupMgr.c
@@ -0,0 +1,4796 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PopupMgr.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Popup Menu Manager Widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+#include <X11/ShellP.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/MenuBtnP.h>
+#include <Xw/MenuBtn.h>
+#include <Xw/PopupMgrP.h>
+#include <Xw/PopupMgr.h>
+
+
+/* Standard Toolkit Routines */
+static void Initialize();
+static void Destroy();
+static Boolean SetValues();
+static void ClassPartInitialize();
+
+/* Global Routines */
+static void AttachPane();
+static void DetachPane();
+static void AddPane();
+static void SetSelectAccelerator();
+static void ClearSelectAccelerator();
+static void AddButton();
+static void Unpost();
+static void Post();
+static Boolean ProcessSelect();
+static Boolean ValidEvent();
+static Boolean DoICascade();
+static void ClassPost();
+static void ClassSelect();
+static Boolean DoYouWantThisAccelerator();
+static Boolean DoYouWantThisPost();
+static void SetPostMnemonic();
+static void ClearPostMnemonic();
+static void SetSelectMnemonic();
+static void ClearSelectMnemonic();
+static void SetTitleAttributes();
+static void TraverseLeft();
+static void TraverseRight();
+static void TraverseNext();
+static void TraversePrev();
+static void TraverseHome();
+static void TraverseUp();
+static void TraverseDown();
+static void TraverseNextTop();
+static void BtnSensitivityChanged();
+static void PaneSensitivityChanged();
+
+/* Action Routines */
+static void MMPost();
+static void MMAccelPost();
+static void MMAccelSelect();
+static void MMUnpost();
+
+/* Callback Routines */
+static void _XwMenuPaneCleanup();
+static void _XwMenuButtonCleanup();
+static void _XwCascadeUnselect();
+static void _XwCascadeSelect();
+
+/* Internal Support Routines */
+static void RegisterTranslation();
+static void ExposeEventHandler();
+static void RegisterPostTranslation();
+static void PositionCascade();
+static Boolean ActionIsUsurpedByChild();
+static void AddToPendingList();
+static void SetButtonAccelerators();
+static void SetTreeAccelerators();
+static void ClearTreeAccelerators();
+static Boolean CompletePath();
+static Widget PendingAttach();
+static void SetUpTranslation();
+static void ForceMenuPaneOnScreen();
+static void PaneManagedChildren();
+static Boolean Visible();
+static void SetMenuTranslations();
+static void ManualPost();
+static void SendFakeLeaveNotify();
+static void SetUpStickyList();
+static void DoDetach();
+
+
+/****************************************************************
+ *
+ * Popup Resources
+ *
+ ****************************************************************/
+
+static XtResource resources[] = {
+ {XtNstickyMenus, XtCStickyMenus, XtRBoolean, sizeof(Boolean),
+ XtOffset(XwPopupMgrWidget, popup_mgr.stickyMode),XtRString,"FALSE"},
+
+ {XtNpostAccelerator, XtCPostAccelerator, XtRString, sizeof(String),
+ XtOffset(XwPopupMgrWidget, popup_mgr.postAccelerator),XtRString,
+ NULL}
+};
+
+/****************************************************************
+ *
+ * Miscellaneous Values
+ *
+ ****************************************************************/
+
+/* Global Action Routines */
+static XtActionsRec XwPopupActions[] = {
+ {"PopupPostMenu", MMPost},
+ {"PopupUnpostMenu", MMUnpost},
+ {"PopupAccelPost", MMAccelPost},
+ {"PopupAccelSelect", MMAccelSelect}
+};
+
+/* Translation Template Strings */
+static String postTemplate = ": PopupPostMenu(";
+static String unpostTemplate = ": PopupUnpostMenu(";
+static String accelPostTemplate = ": PopupAccelPost(";
+static String accelSelectTemplate = ": PopupAccelSelect(";
+static String selectTemplate = ": select()";
+
+static char workArea[300];
+
+
+/*
+ * Used when positioning a cascade such that the cursor will be
+ * in the first item of the cascade.
+ */
+#define FUDGE_FACTOR 8
+
+#define SHELL_PARENT 0
+#define ULTIMATE_PARENT 1
+
+/*
+ * This mask is used during the setting and clearing of button grabs.
+ * If the event being grabbed is a buttonUp event, then these bits
+ * cause the grabs to never activate; so they need to be cleared.
+ */
+#define btnMask (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+XwPopupMgrClassRec XwpopupmgrClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwmenumgrClassRec,
+ /* class_name */ "XwPopupMgr",
+ /* widget_size */ sizeof(XwPopupMgrRec),
+ /* class_initialize */ NULL,
+ /* class_part_init */ ClassPartInitialize,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ NULL,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ NULL,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* PRIVATE cb list */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },{
+/* composite_class fields */
+ /* geometry_manager */ NULL,
+ /* change_managed */ NULL,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ NULL,
+ },{
+/* constraint class fields */
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ NULL,
+ },{
+/* manager_class fields */
+ /* traversal handler */ (XwTraversalProc)XtInheritTraversalProc,
+ /* translations */ NULL,
+ },{
+/* menu manager class */
+ /* attachPane */ AttachPane,
+ /* detachPane */ DetachPane,
+ /* addPane */ AddPane,
+ /* setSelectAccel */ SetSelectAccelerator,
+ /* clearSelectAccel */ ClearSelectAccelerator,
+ /* setPostMnemonic */ SetPostMnemonic,
+ /* clearPostMnemonic */ ClearPostMnemonic,
+ /* addButton */ AddButton,
+ /* processSelect */ (XwBooleanProc)ProcessSelect,
+ /* validEvent */ (XwBooleanProc)ValidEvent,
+ /* doIcascade */ DoICascade,
+ /* setSelectMnemonic */ SetSelectMnemonic,
+ /* clearSelectMnemon */ ClearSelectMnemonic,
+ /* setTitleAttributes */ SetTitleAttributes,
+ /* paneManagedChildren*/ PaneManagedChildren,
+ /* traverseLeft */ TraverseLeft,
+ /* traverseRight */ TraverseRight,
+ /* traverseNext */ TraverseNext,
+ /* traversePrev */ TraversePrev,
+ /* traverseHome */ TraverseHome,
+ /* traverseUp */ TraverseUp,
+ /* traverseDown */ TraverseDown,
+ /* traverseNextTop */ TraverseNextTop,
+ /* btnSensitivityChan */ BtnSensitivityChanged,
+ /* paneSensitivityCha */ PaneSensitivityChanged,
+ },{
+/* popup menu manager class - none */
+ /* manualPost */ (XwPostProc) ManualPost,
+ }
+};
+
+WidgetClass XwpopupmgrWidgetClass = (WidgetClass)&XwpopupmgrClassRec;
+WidgetClass XwpopupMgrWidgetClass = (WidgetClass)&XwpopupmgrClassRec;
+
+/*----------------------------------------------------------------------*/
+/* I don't really know why PopupMgr needs to register its actions */
+/* globally like this when all other widgets don't; regardless, */
+/* running this in ClassInitialize() doesn't work because the app */
+/* context can be destroyed and remade, and then it loses the actions, */
+/* instead returning "Warning: Actions not found: PopupPostMenu". */
+/* Furthermore, the "correct" implementation needs a value for "app", */
+/* which must be declared global, which is clearly a hack. So I'm */
+/* instead creating a world-accessible function which does what */
+/* ClassInitialize() did, but it takes an argument "app" and must be */
+/* called every time the application is (re)made. */
+/*----------------------------------------------------------------------*/
+
+void XwAppInitialize(XtAppContext app)
+{
+ /* Register the global action routines */
+ XtAppAddActions (app, XwPopupActions, XtNumber(XwPopupActions));
+}
+
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ *
+ * Description:
+ * -----------
+ * Initialize the popup_mgr fields within the widget's instance structure.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Initialize (request, new)
+
+ XwPopupMgrWidget request;
+ register XwPopupMgrWidget new;
+
+{
+ Widget grandparent;
+ KeySym tempKeysym;
+
+ /*
+ * Clear the 'map when managed' flag, since this widget should
+ * never be visible.
+ */
+ new->core.mapped_when_managed = FALSE;
+
+ /* Fill in our instance fields */
+ new->popup_mgr.topLevelPane = (Widget) NULL;
+ new->popup_mgr.lastSelected = (Widget) NULL;
+ new->popup_mgr.savedCascadeList = (Widget *) XtMalloc(25 * sizeof(Widget));
+ new->popup_mgr.numSavedCascades = 0;
+ new->popup_mgr.sizeSavedCascadeList = 25;
+ new->popup_mgr.currentCascadeList = (Widget *) XtMalloc(25 * sizeof(Widget));
+ new->popup_mgr.numCascades = 0;
+ new->popup_mgr.sizeCascadeList = 25;
+ new->popup_mgr.attachPane = (XwMenuPaneWidget) NULL;
+ new->popup_mgr.detachPane = (XwMenuPaneWidget) NULL;
+ new->popup_mgr.origMouseX = -1;
+ new->popup_mgr.origMouseY = -1;
+
+ /* Get the widget Id for the widget to which the menu is attached */
+ grandparent = (Widget) XtParent(XtParent(new));
+
+ /*
+ * If a post accelerator is specified, then attempt to convert it to
+ * a usable format (not a string); if the accelerator specification is
+ * invalid, then use the default post accelerator (none).
+ */
+ if ((new->popup_mgr.postAccelerator) &&
+ (strlen(new->popup_mgr.postAccelerator) > 0) &&
+ (_XwMapKeyEvent (new->popup_mgr.postAccelerator,
+ &new->popup_mgr.accelEventType,
+ &tempKeysym,
+ &new->popup_mgr.accelModifiers)))
+ {
+ /* Valid accelerator string; save a copy */
+ new->popup_mgr.accelKey = XKeysymToKeycode(XtDisplay(new),
+ tempKeysym);
+ new->popup_mgr.postAccelerator = (String) strcpy (XtMalloc (
+ XwStrlen(new->popup_mgr. postAccelerator) + 1),
+ new->popup_mgr.postAccelerator);
+
+ /* Set up a translation in the widget */
+ RegisterTranslation (grandparent, new->popup_mgr.postAccelerator,
+ accelPostTemplate, new);
+ }
+ else
+ {
+ if ((new->popup_mgr.postAccelerator) &&
+ (strlen(new->popup_mgr.postAccelerator) > 0))
+ {
+ XtWarning ("PopupMgr: Invalid post accelerator; disabling feature");
+ }
+ new->popup_mgr.postAccelerator = NULL;
+ new->popup_mgr.accelEventType = 0;
+ new->popup_mgr.accelKey = 0;
+ new->popup_mgr.accelModifiers = 0;
+ }
+
+ /* Attach a posting translation to the widget */
+ if (new->menu_mgr.postString)
+ {
+ RegisterTranslation (grandparent, new->menu_mgr.postString,
+ postTemplate, new);
+ }
+
+ /* Attach an unposting translation to the widget, if specified */
+ if (new->menu_mgr.unpostString)
+ {
+ RegisterTranslation (grandparent, new->menu_mgr.unpostString,
+ unpostTemplate, new);
+ }
+
+ /*
+ * If the children of the widget are to inherit this menu, then we
+ * need to set up a button grab for the posting event; if the widget
+ * is not yet realized, then we cannot set the grab, so we will
+ * attach an exposure event handler to the widget, so that when it
+ * does finally get mapped, we can set up any necessary grabs.
+ */
+ if (XtIsRealized(grandparent))
+ {
+ if (new->menu_mgr.associateChildren)
+ {
+ /* Set up a grab for the post event */
+ if (new->menu_mgr.postString)
+ {
+ XGrabButton (XtDisplay(grandparent), new->menu_mgr.postButton,
+ (new->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent),
+ False, ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, (Window)NULL, (Cursor)NULL);
+ }
+
+ /* Set up a grab for the post accelerator */
+ if (new->popup_mgr.postAccelerator)
+ {
+ XGrabKey (XtDisplay(grandparent),
+ new->popup_mgr.accelKey,
+ new->popup_mgr.accelModifiers, XtWindow(grandparent),
+ False, GrabModeAsync, GrabModeAsync);
+ }
+ }
+ }
+ else
+ {
+ XtAddEventHandler (grandparent, ExposureMask|StructureNotifyMask, False,
+ ExposeEventHandler, new);
+ }
+} /* Initialize */
+
+
+/*************************************<->*************************************
+ *
+ * SetValues()
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues (current, request, new)
+
+ register XwPopupMgrWidget current;
+ XwPopupMgrWidget request;
+ register XwPopupMgrWidget new;
+
+{
+ Widget grandparent;
+ Boolean postGrabSet = FALSE;
+ Boolean postGrabCleared = FALSE;
+ Boolean postAccelGrabSet = FALSE;
+ Boolean postAccelGrabCleared = FALSE;
+ KeySym tempKeysym;
+ XtTranslations translation;
+ String workTemplate;
+ register int i, j, k;
+
+ grandparent = (Widget) XtParent(XtParent(current));
+
+ /* Process the post accelerator */
+ if (current->popup_mgr.postAccelerator != new->popup_mgr.postAccelerator)
+ {
+ if ((new->popup_mgr.postAccelerator) &&
+ (strlen(new->popup_mgr.postAccelerator) > 0))
+ {
+ if (_XwMapKeyEvent (new->popup_mgr.postAccelerator,
+ &new->popup_mgr.accelEventType,
+ &tempKeysym,
+ &new->popup_mgr.accelModifiers))
+ {
+ /* Valid accelerator string; save a copy */
+ new->popup_mgr.accelKey = XKeysymToKeycode (XtDisplay(new),
+ tempKeysym);
+ new->popup_mgr.postAccelerator = (String) strcpy (XtMalloc (
+ XwStrlen(new->popup_mgr. postAccelerator) + 1),
+ new->popup_mgr.postAccelerator);
+ }
+ else
+ {
+ /* Invalid; revert to previous setting */
+ XtWarning
+ ("PopupMgr: Invalid post accelerator; using previous setting");
+ new->popup_mgr.postAccelerator = current->popup_mgr.postAccelerator;
+ new->popup_mgr.accelEventType = current->popup_mgr.accelEventType;
+ new->popup_mgr.accelKey = current->popup_mgr.accelKey;
+ new->popup_mgr.accelModifiers = current->popup_mgr.accelModifiers;
+ }
+ }
+ else
+ {
+ /* None specified, so disable the feature */
+ new->popup_mgr.postAccelerator = NULL;
+ new->popup_mgr.accelEventType = 0;
+ new->popup_mgr.accelKey = 0;
+ new->popup_mgr.accelModifiers = 0;
+ }
+
+ /*
+ * This duplicate check prevents us from doing alot of unnecessary
+ * work in the case where an invalid string was specified, and thus
+ * we reverted to the previous value.
+ */
+ if (current->popup_mgr.postAccelerator != new->popup_mgr.postAccelerator)
+ {
+ /* Remove the old accelerator translation and grab */
+ if (current->popup_mgr.postAccelerator)
+ {
+ RegisterTranslation (grandparent,
+ current->popup_mgr.postAccelerator,
+ accelPostTemplate, NULL);
+
+ if (XtIsRealized(grandparent) &&current->menu_mgr.associateChildren)
+ {
+ XUngrabKey (XtDisplay(grandparent), current->popup_mgr.accelKey,
+ current->popup_mgr.accelModifiers, XtWindow(grandparent));
+ postAccelGrabCleared = TRUE;
+ }
+ }
+
+ /* Set the new accelerator translation and grab */
+ if (new->popup_mgr.postAccelerator)
+ {
+ RegisterTranslation (grandparent, new->popup_mgr.postAccelerator,
+ accelPostTemplate, new);
+
+ if (XtIsRealized(grandparent) && new->menu_mgr.associateChildren)
+ {
+ XGrabKey (XtDisplay(grandparent), new->popup_mgr.accelKey,
+ new->popup_mgr.accelModifiers, XtWindow(grandparent),
+ False, GrabModeAsync, GrabModeAsync);
+ postAccelGrabSet = TRUE;
+ }
+ }
+
+ /* Free up the buffer holding the old string */
+ XtFree (current->popup_mgr.postAccelerator);
+ }
+ }
+
+ /* Process the post event */
+ if (current->menu_mgr.postString != new->menu_mgr.postString)
+ {
+ /* Remove the old post translation and grab */
+ if (current->menu_mgr.postString)
+ {
+ RegisterTranslation (grandparent, current->menu_mgr.postString,
+ postTemplate, NULL);
+
+ if (XtIsRealized(grandparent) && current->menu_mgr.associateChildren)
+ {
+ XUngrabButton (XtDisplay(grandparent), current->menu_mgr.postButton,
+ (current->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent));
+ postGrabCleared = TRUE;
+ }
+
+ /* Free up the old string */
+ XtFree (current->menu_mgr.postString);
+ }
+
+ /* Set the new post translation and grab */
+ if (new->menu_mgr.postString)
+ {
+ RegisterTranslation (grandparent, new->menu_mgr.postString,
+ postTemplate, new);
+
+ if (XtIsRealized(grandparent) && new->menu_mgr.associateChildren)
+ {
+ XGrabButton (XtDisplay(grandparent), new->menu_mgr.postButton,
+ (new->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent),
+ False, ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, (Window)NULL, (Cursor)NULL);
+ postGrabSet = TRUE;
+ }
+ }
+ }
+
+ /* Process the select event. */
+ if (current->menu_mgr.selectString != new->menu_mgr.selectString)
+ {
+
+ /*
+ * Each menubutton and menupane must have a new 'select' translation
+ * set up; no grabs are needed. The old ones do not need to be
+ * removed, since ProcessSelect() will reject them.
+ */
+
+ if (new->menu_mgr.selectString)
+ {
+ /*
+ * Create the translation string of format:
+ *
+ * "!<event>: select()"
+ */
+ workTemplate = &workArea[0];
+ strcpy (workTemplate, "!");
+ strcat (workTemplate, new->menu_mgr.selectString);
+ strcat (workTemplate, selectTemplate);
+ translation = XtParseTranslationTable (workTemplate);
+ SetMenuTranslations (new, translation);
+ /* XtDestroyStateTable (XtClass(new), translation); */
+ }
+
+ if (current->menu_mgr.selectString)
+ XtFree (current->menu_mgr.selectString);
+ }
+
+ /* Process the unpost event. */
+ if (current->menu_mgr.unpostString != new->menu_mgr.unpostString)
+ {
+ /*
+ * Each menubutton and menupane must have a new 'unpost' translation
+ * set up; no grabs are needed. The old ones need to first be
+ * removed.
+ */
+
+ if (current->menu_mgr.unpostString)
+ {
+ /*
+ * Create the translation string of format:
+ *
+ * "!<event>: MMUnpost(mgrId)"
+ */
+
+ workTemplate = &workArea[0];
+ strcpy (workTemplate, "!");
+ strcat (workTemplate, current->menu_mgr.unpostString);
+ strcat (workTemplate, unpostTemplate);
+ strcat (workTemplate, _XwMapToHex(NULL));
+ strcat (workTemplate, ")");
+ translation = XtParseTranslationTable (workTemplate);
+ SetMenuTranslations (new, translation);
+ /* XtDestroyStateTable (XtClass(new), translation); */
+ RegisterTranslation (grandparent, current->menu_mgr.unpostString,
+ unpostTemplate, NULL);
+ XtFree (current->menu_mgr.unpostString);
+ }
+
+ if (new->menu_mgr.unpostString)
+ {
+ /*
+ * Create the translation string of format:
+ *
+ * "!<event>: MMUnpost(mgrId)"
+ */
+
+ workTemplate = &workArea[0];
+ strcpy (workTemplate, "!");
+ strcat (workTemplate, new->menu_mgr.unpostString);
+ strcat (workTemplate, unpostTemplate);
+ strcat (workTemplate, _XwMapToHex(new->core.self));
+ strcat (workTemplate, ")");
+ translation = XtParseTranslationTable (workTemplate);
+ SetMenuTranslations (new, translation);
+ /* XtDestroyStateTable (XtClass(new), translation); */
+ RegisterTranslation (grandparent, new->menu_mgr.unpostString,
+ unpostTemplate, new);
+ }
+ }
+
+ /* Process the keyboard select event. */
+ if (current->menu_mgr.kbdSelectString != new->menu_mgr.kbdSelectString)
+ {
+ /*
+ * Each menubutton and menupane must have a new 'kbd select' translation
+ * set up; no grabs are needed. The old ones do not need to be
+ * removed, since ProcessSelect() will reject them.
+ */
+
+ if (new->menu_mgr.kbdSelectString)
+ {
+ /*
+ * Create the translation string of format:
+ *
+ * "!<event>: select()"
+ */
+ workTemplate = &workArea[0];
+ strcpy (workTemplate, "!");
+ strcat (workTemplate, new->menu_mgr.kbdSelectString);
+ strcat (workTemplate, selectTemplate);
+ translation = XtParseTranslationTable (workTemplate);
+
+ /*
+ * Since the menupanes are our popup grand children, we
+ * will process them simply by traversing our popup children list.
+ */
+ SetMenuTranslations (new, translation);
+ /* XtDestroyStateTable (XtClass(new), translation); */
+ }
+
+ if (current->menu_mgr.kbdSelectString)
+ XtFree (current->menu_mgr.kbdSelectString);
+ }
+
+ /* Process the associateChildren flag */
+ if (current->menu_mgr.associateChildren != new->menu_mgr.associateChildren)
+ {
+ int i;
+
+ /*
+ * If the widget is realized, then we need to set/clear button
+ * and key grabs for the post event, the post accelerator, and
+ * all menubutton accelerators; the two post grabs will only be
+ * set or cleared if they were not already done so earlier; this
+ * would have happened if either of their event strings had
+ * changed.
+ */
+ if (XtIsRealized (grandparent))
+ {
+ if (new->menu_mgr.associateChildren)
+ {
+ /* Set post grab */
+ if ((!postGrabSet) && (new->menu_mgr.postString))
+ {
+ XGrabButton (XtDisplay(grandparent), new->menu_mgr.postButton,
+ (new->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent),
+ False, ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, (Window)NULL, (Cursor)NULL);
+ }
+
+ /* Set post accelerator grab */
+ if ((!postAccelGrabSet) && (new->popup_mgr.postAccelerator))
+ {
+ XGrabKey (XtDisplay(grandparent), new->popup_mgr.accelKey,
+ new->popup_mgr.accelModifiers, XtWindow(grandparent),
+ False, GrabModeAsync, GrabModeAsync);
+ }
+
+ /* Set menubutton accelerator grabs */
+ for (i = 0; i < new->menu_mgr.numAccels; i++)
+ {
+ XGrabKey (XtDisplay(grandparent),
+ new->menu_mgr.menuBtnAccelTable[i].accelKey,
+ new->menu_mgr.menuBtnAccelTable[i].accelModifiers,
+ XtWindow(grandparent), False, GrabModeAsync,
+ GrabModeAsync);
+ }
+ }
+ else
+ {
+ /* Clear post grab */
+ if ((!postGrabCleared) && (current->menu_mgr.postString))
+ {
+ XUngrabButton (XtDisplay(grandparent),
+ current->menu_mgr.postButton,
+ (current->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent));
+ }
+
+ /* Clear post accelerator grab */
+ if ((!postAccelGrabCleared) && (current->popup_mgr.postAccelerator))
+ {
+ XUngrabKey (XtDisplay(grandparent),
+ current->popup_mgr.accelKey,
+ current->popup_mgr.accelModifiers,
+ XtWindow(grandparent));
+ }
+
+ /* Clear menubutton accelerator grabs */
+ for (i = 0; i < current->menu_mgr.numAccels; i++)
+ {
+ XUngrabKey (XtDisplay(grandparent),
+ current->menu_mgr.menuBtnAccelTable[i].accelKey,
+ current->menu_mgr.menuBtnAccelTable[i].accelModifiers,
+ XtWindow(grandparent));
+ }
+ }
+ }
+ }
+
+ /*
+ * Since all of the menu components inherit their traversal setting
+ * from their menu manager, anytime the menu manager's traversal
+ * state changes, we need to propogate this down to all of the other
+ * menu components (panes, buttons, separaters).
+ */
+ if (new->manager.traversal_on != current->manager.traversal_on)
+ {
+ int traversalType;
+
+ if (new->manager.traversal_on)
+ traversalType = XwHIGHLIGHT_TRAVERSAL;
+ else
+ traversalType = XwHIGHLIGHT_OFF;
+
+ for (i = 0; i < current->core.num_popups; i++)
+ {
+ CompositeWidget shell;
+
+ shell = (CompositeWidget) current->core.popup_list[i];
+
+ for (j = 0; j < shell->composite.num_children; j++)
+ {
+ XwMenuPaneWidget menupane;
+
+ /* Here we set the traversal flag for the menupanes */
+ menupane = (XwMenuPaneWidget)shell->composite.children[j];
+ if (XtIsSubclass ((Widget)menupane, XwmenupaneWidgetClass))
+ {
+ (*(((XwMenuPaneWidgetClass)
+ XtClass(menupane))-> menu_pane_class.setTraversalFlag))
+ ((Widget)menupane, new->manager.traversal_on);
+ }
+
+ for (k = 0; k < menupane->manager.num_managed_children; k++)
+ {
+ XwMenuButtonWidget mbutton;
+
+ /* Here we set the traversal flag for the menubuttons */
+ mbutton = (XwMenuButtonWidget)menupane->composite.children[k];
+ if (XtIsSubclass ((Widget)mbutton, XwmenubuttonWidgetClass))
+ {
+ (*(((XwMenuButtonWidgetClass)
+ XtClass(mbutton))-> menubutton_class.setTraversalType))
+ ((Widget)mbutton, traversalType);
+ }
+ }
+ }
+ }
+ }
+
+ /* Clear the sticky menu list, if sticky mode is disabled */
+ if (new->popup_mgr.stickyMode == False)
+ new->popup_mgr.numSavedCascades = 0;
+
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Destroy()
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Destroy (mw)
+
+ register XwPopupMgrWidget mw;
+
+{
+ Widget grandparent;
+ register int i;
+
+ /* Get the widget Id for the widget to which the menus are attached */
+ grandparent = (Widget)XtParent(XtParent(mw));
+
+ /* Free up any memory we allocated */
+ XtFree ((char *)(mw->popup_mgr.savedCascadeList));
+ XtFree ((char *)(mw->popup_mgr.currentCascadeList));
+
+ /* Clean up the post and accelerated post translations */
+ if (mw->menu_mgr.postString)
+ {
+ RegisterTranslation (grandparent, mw->menu_mgr.postString,
+ postTemplate, NULL);
+ }
+ if (mw->popup_mgr.postAccelerator)
+ {
+ RegisterTranslation (grandparent, mw->popup_mgr.postAccelerator,
+ accelPostTemplate, NULL);
+ }
+
+ if (mw->menu_mgr.unpostString)
+ {
+ RegisterTranslation (grandparent, mw->menu_mgr.unpostString,
+ unpostTemplate, NULL);
+ }
+
+ /***************
+ * THE FOLLOWING IS NOT NEEDED, SINCE BY THE TIME WE GET HERE,
+ * ALL OF OUR CHILDREN HAVE BEEN DESTROYED, AND THEIR ACCELERATORS
+ * ALREADY CLEARED.
+ *
+ * Remove translations for each menubutton accelerator
+ *
+ * for (i = 0; i < mw->menu_mgr.numAccels; i++)
+ * {
+ * RegisterTranslation (grandparent,
+ * mw->menu_mgr.menuBtnAccelTable[i].accelString,
+ * accelSelectTemplate, NULL);
+ * }
+ ****************/
+
+ /* Remove any grabs we have set on the widget */
+ if (XtIsRealized(grandparent))
+ {
+ if (mw->menu_mgr.associateChildren)
+ {
+ /* Remove post grab */
+ if (mw->menu_mgr.postString)
+ {
+ XUngrabButton (XtDisplay(grandparent), mw->menu_mgr.postButton,
+ (mw->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(grandparent));
+ }
+
+ /* Remove post accelerator grab */
+ if (mw->popup_mgr.postAccelerator)
+ {
+ XUngrabKey (XtDisplay(grandparent), mw->popup_mgr.accelKey,
+ mw->popup_mgr.accelModifiers, XtWindow(grandparent));
+ }
+
+ /***************
+ * THE FOLLOWING IS NOT NEEDED, SINCE BY THE TIME WE GET HERE,
+ * ALL OF OUR CHILDREN HAVE BEEN DESTROYED, AND THEIR ACCELERATORS
+ * ALREADY CLEARED.
+ *
+ * Remove grabs for each menubutton accelerator
+ * for (i = 0; i < mw->menu_mgr.numAccels; i++)
+ * {
+ * XUngrabKey (XtDisplay(grandparent),
+ * mw->menu_mgr.menuBtnAccelTable[i].accelKey,
+ * mw->menu_mgr.menuBtnAccelTable[i].accelModifiers,
+ * XtWindow(grandparent));
+ * }
+ ***************/
+ }
+ }
+ else
+ {
+ /* Simply remove the exposure handler we added at initialize time */
+ XtRemoveEventHandler (grandparent, ExposureMask|StructureNotifyMask,
+ False, ExposeEventHandler, mw);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * ClassPartInitialize(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassPartInitialize (wc)
+
+ register XwPopupMgrWidgetClass wc;
+
+{
+ register XwPopupMgrWidgetClass super;
+
+ super = (XwPopupMgrWidgetClass)wc->core_class.superclass;
+
+ if (wc->menu_mgr_class.attachPane == XtInheritAttachPane)
+ wc->menu_mgr_class.attachPane = super->menu_mgr_class.attachPane;
+
+ if (wc->menu_mgr_class.detachPane == XtInheritDetachPane)
+ wc->menu_mgr_class.detachPane = super->menu_mgr_class.detachPane;
+
+ if (wc->menu_mgr_class.addPane == XtInheritAddPane)
+ wc->menu_mgr_class.addPane = super->menu_mgr_class.addPane;
+
+ if (wc->menu_mgr_class.setSelectAccelerator == XtInheritSetSelectAccelerator)
+ wc->menu_mgr_class.setSelectAccelerator =
+ super->menu_mgr_class.setSelectAccelerator;
+
+ if (wc->menu_mgr_class.clearSelectAccelerator ==
+ XtInheritClearSelectAccelerator)
+ wc->menu_mgr_class.clearSelectAccelerator =
+ super->menu_mgr_class.clearSelectAccelerator;
+
+ if (wc->menu_mgr_class.setPostMnemonic == XtInheritSetPostMnemonic)
+ wc->menu_mgr_class.setPostMnemonic =super->menu_mgr_class.setPostMnemonic;
+
+ if (wc->menu_mgr_class.clearPostMnemonic == XtInheritClearPostMnemonic)
+ wc->menu_mgr_class.clearPostMnemonic =
+ super->menu_mgr_class.clearPostMnemonic;
+
+ if (wc->menu_mgr_class.setPostMnemonic == XtInheritSetPostMnemonic)
+ wc->menu_mgr_class.setPostMnemonic =super->menu_mgr_class.setPostMnemonic;
+
+ if (wc->menu_mgr_class.clearPostMnemonic==XtInheritClearPostMnemonic)
+ wc->menu_mgr_class.clearPostMnemonic =
+ super->menu_mgr_class.clearPostMnemonic;
+
+ if (wc->menu_mgr_class.addButton == XtInheritAddButton)
+ wc->menu_mgr_class.addButton = super->menu_mgr_class.addButton;
+
+ if (wc->menu_mgr_class.setSelectMnemonic == XtInheritSetSelectMnemonic)
+ wc->menu_mgr_class.setSelectMnemonic =
+ super->menu_mgr_class.setSelectMnemonic;
+
+ if (wc->menu_mgr_class.clearSelectMnemonic == XtInheritClearSelectMnemonic)
+ wc->menu_mgr_class.clearSelectMnemonic =
+ super->menu_mgr_class.clearSelectMnemonic;
+
+ if (wc->menu_mgr_class.processSelect == XtInheritProcessSelect)
+ wc->menu_mgr_class.processSelect = super->menu_mgr_class.processSelect;
+
+ if (wc->menu_mgr_class.validEvent == XtInheritValidEvent)
+ wc->menu_mgr_class.validEvent = super->menu_mgr_class.validEvent;
+
+ if (wc->menu_mgr_class.doICascade == XtInheritDoICascade)
+ wc->menu_mgr_class.doICascade = super->menu_mgr_class.doICascade;
+
+ if (wc->menu_mgr_class.paneManagedChildren == XtInheritPaneManagedChildren)
+ wc->menu_mgr_class.paneManagedChildren =
+ super->menu_mgr_class.paneManagedChildren;
+
+ if (wc->menu_mgr_class.setTitleAttributes == XtInheritSetTitleAttributes)
+ wc->menu_mgr_class.setTitleAttributes =
+ super->menu_mgr_class.setTitleAttributes;
+
+ if (wc->menu_mgr_class.traverseLeft == XtInheritPopupTravLeft)
+ wc->menu_mgr_class.traverseLeft = super->menu_mgr_class.traverseLeft;
+
+ if (wc->menu_mgr_class.traverseRight == XtInheritPopupTravRight)
+ wc->menu_mgr_class.traverseRight = super->menu_mgr_class.traverseRight;
+
+ if (wc->menu_mgr_class.traverseNext == XtInheritPopupTravNext)
+ wc->menu_mgr_class.traverseNext = super->menu_mgr_class.traverseNext;
+
+ if (wc->menu_mgr_class.traversePrev == XtInheritPopupTravPrev)
+ wc->menu_mgr_class.traversePrev = super->menu_mgr_class.traversePrev;
+
+ if (wc->menu_mgr_class.traverseHome == XtInheritPopupTravHome)
+ wc->menu_mgr_class.traverseHome = super->menu_mgr_class.traverseHome;
+
+ if (wc->menu_mgr_class.traverseUp == XtInheritPopupTravUp)
+ wc->menu_mgr_class.traverseUp = super->menu_mgr_class.traverseUp;
+
+ if (wc->menu_mgr_class.traverseDown == XtInheritPopupTravDown)
+ wc->menu_mgr_class.traverseDown = super->menu_mgr_class.traverseDown;
+
+ if (wc->menu_mgr_class.traverseNextTop == XtInheritPopupTravNextTop)
+ wc->menu_mgr_class.traverseNextTop=super->menu_mgr_class.traverseNextTop;
+
+ if (wc->menu_mgr_class.btnSensitivityChanged==XtInheritBtnSensitivityChanged)
+ wc->menu_mgr_class.btnSensitivityChanged =
+ super->menu_mgr_class.btnSensitivityChanged;
+
+ if (wc->menu_mgr_class.paneSensitivityChanged ==
+ XtInheritPaneSensitivityChanged)
+ wc->menu_mgr_class.paneSensitivityChanged =
+ super->menu_mgr_class.paneSensitivityChanged;
+}
+
+/*************************************<->*************************************
+ *
+ * RegisterTranslation (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void RegisterTranslation (widget, event, template, menuMgrId)
+
+ Widget widget;
+ String event;
+ String template;
+ Widget menuMgrId;
+
+
+{
+ register String workTemplate;
+ XtTranslations translations;
+
+ workTemplate = &workArea[0];
+
+ /*
+ * Construct the translation string, using the following format:
+ *
+ * "!<event>: ActionProc(menuMgrId)"
+ */
+
+ strcpy (workTemplate, "!");
+ strcat (workTemplate, event);
+ strcat (workTemplate, template);
+ if (menuMgrId)
+ strcat (workTemplate, _XwMapToHex(menuMgrId->core.self));
+ else
+ strcat (workTemplate, _XwMapToHex(NULL));
+ strcat (workTemplate, ")");
+
+ /* Compile the translation and attach to the widget */
+ translations = XtParseTranslationTable(workTemplate);
+ XtOverrideTranslations (widget, translations);
+ /* XtDestroyStateTable (XtClass(widget), translations); */
+}
+
+
+/*************************************<->*************************************
+ *
+ * PositionCascade (parameters)
+ *
+ * Description:
+ * -----------
+ * This routine positions a cacading submenu pane. When the new
+ * menupane is posted, it will slightly overlap the previous menu
+ * pane (in the x direction). In the y direction, the new menupane
+ * will be positioned such that its first menubutton is centered on
+ * the menubutton to which the menupane is attached.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void PositionCascade (menubutton, menupane)
+
+ register Widget menubutton;
+ XwManagerWidget menupane;
+
+{
+ Position x, y, yDelta;
+ Widget menubuttonGrandparent;
+ Widget menubuttonParent;
+ Widget menupaneShell;
+
+ menubuttonParent = (Widget)XtParent(menubutton);
+ menubuttonGrandparent = (Widget)XtParent(menubuttonParent);
+ menupaneShell = (Widget)XtParent(menupane);
+
+ /*
+ * In order for this algorithm to work, we need to make sure the
+ * menupane has been realized; this is because its size is not
+ * yet valid because it is not notified that it has any children
+ * until it is realized.
+ */
+ if (!XtIsRealized (menupaneShell))
+ XtRealizeWidget (menupaneShell);
+
+ /*
+ * Since the x and y need to be absolute positions, we need to
+ * use the shell widget coordinates in portions of these calculations.
+ */
+ x = menubuttonGrandparent->core.x +
+ menubuttonParent->core.border_width +
+ menubutton->core.border_width +
+ menubutton->core.width -
+ (XwCASCADEWIDTH + FUDGE_FACTOR + menupane->core.border_width);
+
+ y = menubuttonGrandparent->core.y +
+ menubuttonParent->core.border_width +
+ menubutton->core.border_width +
+ menubutton->core.y +
+ (menubutton->core.height >> 1);
+
+ /* Attempt to center on the first button in the new menupane */
+ if (menupane->manager.num_managed_children > 0)
+ {
+ Widget firstButton = menupane->manager.managed_children[0];
+/*
+ yDelta = firstButton->core.y +
+ firstButton->core.border_width +
+ (firstButton->core.height >> 1);
+*/
+ yDelta = 0;
+ }
+ else
+ yDelta = menupane->core.border_width + (menupane->core.height >> 1);
+
+ y -= yDelta;
+
+ ForceMenuPaneOnScreen (menupane, &x, &y);
+
+ XtMoveWidget (menupaneShell, x, y);
+}
+
+
+/*************************************<->*************************************
+ *
+ * ExposeEventHandler (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ExposeEventHandler (w, menuMgr, event)
+
+ Widget w;
+ register XwPopupMgrWidget menuMgr;
+ XEvent * event;
+
+{
+ register int i;
+
+ /*
+ * If the children inherit the menu tree, then set up grabs for
+ * the post button, the post accelerator key, and each menubutton
+ * accelerator.
+ */
+ if (menuMgr->menu_mgr.associateChildren)
+ {
+ if (menuMgr->menu_mgr.postString)
+ {
+ XGrabButton (XtDisplay(menuMgr), menuMgr->menu_mgr.postButton,
+ (menuMgr->menu_mgr.postModifiers & ~btnMask),
+ XtWindow(w), False,
+ ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, (Window)NULL, (Cursor)NULL);
+ }
+
+ if (menuMgr->popup_mgr.postAccelerator)
+ {
+ XGrabKey (XtDisplay(menuMgr), menuMgr->popup_mgr.accelKey,
+ menuMgr->popup_mgr.accelModifiers, XtWindow(w),
+ False, GrabModeAsync, GrabModeAsync);
+ }
+
+ for (i = 0; i < menuMgr->menu_mgr.numAccels; i++)
+ {
+ XGrabKey (XtDisplay(menuMgr),
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelKey,
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelModifiers,
+ XtWindow(w), False, GrabModeAsync, GrabModeAsync);
+ }
+ }
+
+ XtRemoveEventHandler (w, ExposureMask|StructureNotifyMask, False,
+ (XtEventHandler)ExposeEventHandler, menuMgr);
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwCascadeSelect(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void _XwCascadeSelect (menubutton, menupane, data)
+
+ Widget menubutton;
+ XwMenuPaneWidget menupane;
+ caddr_t data; /* not used */
+
+{
+ register int i;
+ register XwPopupMgrWidget menuMgr;
+
+ menuMgr = (XwPopupMgrWidget) XtParent(XtParent(menupane));
+
+ /* If the pane is already posted, then do nothing but return */
+ for (i = 0; i < menuMgr->popup_mgr.numCascades; i++)
+ {
+ if (menupane==(XwMenuPaneWidget)menuMgr->popup_mgr.currentCascadeList[i])
+ return;
+ }
+
+ /* Position the cascading menupane */
+ PositionCascade (menubutton, menupane);
+
+ /* Post the menupane */
+ Post (menuMgr, menupane, XtGrabNonexclusive);
+
+ /* Set the traversal focus, if necessary */
+ if (menuMgr->manager.traversal_on)
+ {
+ /* Force the highlight to the first item */
+ menupane->manager.active_child = NULL;
+ XtSetKeyboardFocus ((Widget)menupane, NULL);
+ XwMoveFocus (menupane);
+ SendFakeLeaveNotify(menubutton, SHELL_PARENT);
+ }
+ XFlush(XtDisplay(menuMgr));
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwCascadeUnselect (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void _XwCascadeUnselect (menubutton, menupane, params)
+
+ Widget menubutton;
+ Widget menupane;
+ register XwunselectParams * params;
+
+{
+ XwPopupMgrWidget menuMgr;
+ register Widget shell;
+
+ menuMgr = (XwPopupMgrWidget) XtParent(XtParent(menupane));
+ shell = (Widget)XtParent(menupane);
+
+ /*
+ * Determine if the cursor left the cascade region and entered
+ * the cascading menupane. If this happened, then tell the menu
+ * button to remain highlighted. If this did not happen, then we
+ * need to unpost the menupane, and tell the menubutton to unhighlight.
+ *
+ */
+
+ /* See if the cursor is in the menupane */
+ if ((params->rootX >= shell->core.x) && (params->rootX <
+ (shell->core.x + shell->core.width + (shell->core.border_width << 1))) &&
+ (params->rootY >= shell->core.y) && (params->rootY <
+ (shell->core.y + shell->core.height + (shell->core.border_width << 1))))
+ {
+ /* Yes, we're in the cascading menupane */
+ params->remainHighlighted = TRUE;
+ }
+ else
+ {
+ /* No, we've left the cascade region; unpost the menupane */
+ Unpost (menuMgr, menupane);
+ params->remainHighlighted = FALSE;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMenuPaneCleanup (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void _XwMenuPaneCleanup (menupane, menuMgr, data)
+
+ XwMenuPaneWidget menupane;
+ Widget menuMgr;
+ caddr_t data; /* not used */
+
+{
+ /*
+ * If this menupane is currently attached to a menubutton, or if this
+ * is the top level menupane, then we need to detach it before we
+ * allow it to be destroyed.
+ */
+ if (menupane->menu_pane.attach_to)
+ {
+ if (menupane->menu_pane.attachId == NULL)
+ DetachPane (menuMgr, menupane, menupane->menu_pane.attach_to);
+ else
+ DoDetach (menuMgr, menupane->menu_pane.attachId, menupane);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * _XwMenuButtonCleanup(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void _XwMenuButtonCleanup (menubutton, menuMgr, data)
+
+ Widget menubutton;
+ XwPopupMgrWidget menuMgr;
+ caddr_t data; /* not used */
+
+{
+ Arg arg[1];
+ XwMenuPaneWidget cascadeOn;
+
+ /*
+ * Remove any accelerators associated with this menubutton, and if
+ * there is a menupane cacading from us, then break that association,
+ * and add the menupane back into the pending attach list.
+ */
+ ClearSelectAccelerator (menuMgr, menubutton);
+
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) &cascadeOn);
+ XtGetValues (menubutton, arg, 1);
+
+ if (cascadeOn != NULL)
+ {
+ /* Detach, and add back into pending attach list */
+ DoDetach (menuMgr, menubutton, cascadeOn);
+ AddToPendingList (menuMgr, cascadeOn, cascadeOn->menu_pane.attach_to);
+ }
+
+ /*
+ * If this menubutton had been the last item selected, and if sticky
+ * menus is enabled, then we need to cleanup the saved cascade list,
+ * so that we don't dump core the next time the menu is posted.
+ */
+ if ((menuMgr->popup_mgr.stickyMode) &&
+ (menuMgr->popup_mgr.numSavedCascades > 0) &&
+ (menuMgr->popup_mgr.lastSelected == menubutton->core.self))
+ {
+ menuMgr->popup_mgr.numSavedCascades = 0;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * MMPost(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void MMPost (w, event, params, count)
+
+ Widget w;
+ XEvent * event;
+ String * params;
+ Cardinal count;
+
+{
+ XwPopupMgrWidget menuMgr;
+
+ /* Extract the menu manager widget id */
+ menuMgr = (XwPopupMgrWidget) _XwMapFromHex (params[0]);
+
+ /*
+ * If we have made it down here, then we know the post event is
+ * ours to handle.
+ */
+ if ((menuMgr) && (menuMgr->popup_mgr.topLevelPane))
+ ClassPost (menuMgr, event, TRUE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * MMUnpost(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void MMUnpost (w, event, params, count)
+
+ Widget w;
+ XEvent * event;
+ String * params;
+ Cardinal count;
+
+{
+ register XwPopupMgrWidget menuMgr;
+ Boolean traversalOn;
+
+ /* Extract the menu manager widget id */
+ menuMgr = (XwPopupMgrWidget) _XwMapFromHex (params[0]);
+
+ /*
+ * We need to use a temporary variable, because the application may
+ * change this value from underneath us if it has attached any unpost
+ * callbacks to any of the menupanes.
+ */
+ traversalOn = menuMgr->manager.traversal_on;
+
+ if ((menuMgr) && (menuMgr->menu_mgr.menuActive))
+ {
+ /*
+ * Unpost the menu.
+ * To prevent undesirable side effects, the menuActive flag must
+ * always be cleared before bring down the menu system.
+ */
+ menuMgr->menu_mgr.menuActive = FALSE;
+ Unpost (menuMgr, menuMgr->popup_mgr.topLevelPane);
+ XUngrabPointer (XtDisplay(menuMgr), CurrentTime);
+
+ /*
+ * If traversal is on, and there are no sticky menupanes currently
+ * being remembered, then we need to reset the focus item to the
+ * first item in the menupane.
+ */
+ if (traversalOn && (menuMgr->popup_mgr.numSavedCascades == 0))
+ {
+ ((XwPopupMgrWidget)menuMgr->popup_mgr.topLevelPane)->
+ manager.active_child = NULL;
+ XtSetKeyboardFocus (menuMgr->popup_mgr.topLevelPane, NULL);
+ }
+
+ /*
+ * If we warped the mouse because traversal was on, then we need
+ * to move it back to where it was.
+ */
+ if (traversalOn &&
+ (menuMgr->popup_mgr.origMouseX != -1) &&
+ (menuMgr->popup_mgr.origMouseY != -1))
+ {
+ XWarpPointer (XtDisplay (menuMgr), None,
+ RootWindowOfScreen(menuMgr->core.screen),
+ 0, 0, 0, 0,
+ menuMgr->popup_mgr.origMouseX,
+ menuMgr->popup_mgr.origMouseY);
+ menuMgr->popup_mgr.origMouseX = -1;
+ menuMgr->popup_mgr.origMouseY = -1;
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * MMAccelPost (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void MMAccelPost (w, event, params, count)
+
+ Widget w;
+ XEvent * event;
+ String * params;
+ Cardinal count;
+
+{
+ register XwPopupMgrWidget menuMgr;
+
+ /* Extract the menu manager widget id */
+ menuMgr = (XwPopupMgrWidget) _XwMapFromHex (params[0]);
+
+ /*
+ * If we have made it down here, then we know the accelerator event is
+ * ours to handle.
+ */
+ if ((menuMgr) && (menuMgr->popup_mgr.topLevelPane))
+ ClassPost (menuMgr, event, FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * MMAccelSelect (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void MMAccelSelect (w, event, params, count)
+
+ Widget w;
+ XEvent * event;
+ String * params;
+ Cardinal count;
+
+{
+ register XwPopupMgrWidget menuMgr;
+
+ /* Extract the menu manager widget id */
+ menuMgr = (XwPopupMgrWidget) _XwMapFromHex (params[0]);
+
+ if (menuMgr == NULL)
+ return;
+
+ /*
+ * if menus are not inherited, throw out events that did occur
+ * in the associated widget's children. This takes care of the case
+ * where the child does not select for key events, so they propagate
+ * to us.
+ */
+ if (menuMgr->menu_mgr.associateChildren == FALSE)
+ {
+ if ((event->xkey.window == XtWindow (XtParent (XtParent (menuMgr)))) &&
+ (event->xkey.subwindow != 0) &&
+ (XtWindowToWidget (XtDisplay (menuMgr), event->xkey.subwindow)))
+ return;
+ }
+
+ /*
+ * If we have made it down here, then we know the accelerator event is
+ * ours to handle.
+ */
+ if (menuMgr->popup_mgr.topLevelPane)
+ ClassSelect ((XwMenuMgrWidget)menuMgr, event);
+}
+
+
+/*************************************<->*************************************
+ *
+ * AttachPane(menuMgr, menupane, name)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void AttachPane (menuMgr, menupane, name)
+
+ register XwPopupMgrWidget menuMgr;
+ register XwMenuPaneWidget menupane;
+ String name;
+
+{
+ register XwMenuButtonWidget menubutton;
+ Arg arg[1];
+ register int i, j;
+ CompositeWidget shell, mpane;
+ XrmName nameQuark;
+
+ if (name == NULL)
+ return;
+
+ /*
+ * Save a copy of the menupane Id, since this has been called as
+ * a result of a SetValues being done on the menupane, and all of
+ * our lists only contain the old widget pointer.
+ */
+ menuMgr->popup_mgr.attachPane = menupane;
+
+ /*
+ * check if name is menu manager's name, then this is to be a top level
+ */
+ if ((strcmp (name, menuMgr->core.name) == 0) &&
+ (XwStrlen(name) == XwStrlen(menuMgr->core.name)))
+ {
+ /* Remove the cascade list when the top level pane changes */
+ menuMgr->popup_mgr.numSavedCascades = 0;
+
+ if (menuMgr->popup_mgr.topLevelPane != NULL)
+ {
+ /* Detach the previous top level pane */
+ XtSetArg (arg[0], XtNattachTo, (XtArgVal) NULL);
+ XtSetValues (menuMgr->popup_mgr.topLevelPane, arg, 1);
+ }
+
+ /*
+ * save menupane ID. Since this may be called from menupane's
+ * SetValues routine, the widget passed may be the new structure.
+ * Grab the self field in core to insure the right ID is used.
+ */
+ menuMgr->popup_mgr.topLevelPane = menupane->core.self;
+ menupane->menu_pane.attachId = NULL;
+
+ SetTreeAccelerators (menuMgr, menupane);
+ }
+ else
+ {
+ /*
+ * check if its a menubutton name in the menu system.
+ */
+ nameQuark = XrmStringToQuark(name);
+
+ for (i = 0; i < menuMgr->core.num_popups; i++)
+ {
+ /*
+ * for each shell, if its child is a menupane and the menupane
+ * has a menubutton of the passed in name, then do the attach
+ */
+ shell = (CompositeWidget) menuMgr->core.popup_list[i];
+ if ((shell->composite.num_children == 1) &&
+ (XtIsSubclass(shell->composite.children[0],
+ XwmenupaneWidgetClass)))
+ {
+ mpane = (CompositeWidget) shell->composite.children[0];
+ for (j = 0; j < mpane->composite.num_children; j++)
+ {
+ menubutton = (XwMenuButtonWidget)mpane->composite.children[j];
+ if (menubutton->core.xrm_name == nameQuark)
+ {
+ Widget dwidget = NULL;
+ /*
+ * If there is a menupane already attached to this
+ * button, then we need to first detach it.
+ */
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) &dwidget);
+ XtGetValues ((Widget)menubutton, arg, 1);
+ if (dwidget)
+ {
+ /* Detach the old pane */
+ Widget temppane = dwidget;
+ XtSetArg (arg[0], XtNattachTo, (XtArgVal) NULL);
+ XtSetValues (temppane, arg, 1);
+ }
+
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) menupane->core.self);
+ XtSetValues ((Widget)menubutton, arg, 1);
+
+ menupane->menu_pane.attachId = (Widget) menubutton;
+
+ XtAddCallback ((Widget) menubutton,
+ XtNcascadeSelect, (XtCallbackProc)_XwCascadeSelect,
+ menupane->core.self);
+
+ XtAddCallback ((Widget) menubutton,
+ XtNcascadeUnselect, (XtCallbackProc)_XwCascadeUnselect,
+ menupane->core.self);
+
+ if (CompletePath(menuMgr, menupane))
+ SetTreeAccelerators (menuMgr, menupane);
+
+ menuMgr->popup_mgr.attachPane = NULL;
+ return;
+ }
+ }
+ }
+ }
+ /*
+ * Couldn't find a menubutton with this name
+ */
+ AddToPendingList (menuMgr, menupane, name);
+ }
+
+ /* This always needs to be cleared out when we are done */
+ menuMgr->popup_mgr.attachPane = NULL;
+}
+
+/*************************************<->*************************************
+ *
+ * DetachPane (menuMgr, menupane, name)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void DetachPane (menuMgr, menupane, name)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuPaneWidget menupane;
+ String name;
+
+{
+ register int i;
+ Arg arg;
+ XwMenuButtonWidget menubutton;
+ CompositeWidget shell;
+
+ if (name == NULL)
+ return;
+
+ /*
+ * if menupane is on the pending attach list, remove it and return
+ */
+ for (i=0; i < menuMgr->menu_mgr.numAttachReqs; i++)
+ {
+ if (menuMgr->menu_mgr.pendingAttachList[i].menupaneId ==
+ menupane->core.self)
+ {
+ menuMgr->menu_mgr.pendingAttachList[i] =
+ menuMgr->menu_mgr.pendingAttachList
+ [--menuMgr->menu_mgr.numAttachReqs];
+ return;
+ }
+ }
+
+ /*
+ * Save a copy of the menupane Id, since this has been called as
+ * a result of a SetValues being done on the menupane, and all
+ * of our lists only contain the old widget pointer.
+ */
+ menuMgr->popup_mgr.detachPane = menupane;
+
+ /*
+ * if name is the menu manager's name, removing top level
+ */
+ if ((strcmp (name, menuMgr->core.name) == 0) &&
+ (XwStrlen(name) == XwStrlen(menuMgr->core.name)))
+ {
+ menupane->menu_pane.attachId = (Widget) NULL;
+
+ if (menupane->core.self == menuMgr->popup_mgr.topLevelPane)
+ {
+ ClearTreeAccelerators (menuMgr, menupane->core.self);
+ menuMgr->popup_mgr.topLevelPane = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * detach pane from menubutton. Look on each of the menu managers
+ * popup children for a menupane which contains this named menubutton.
+ */
+ for (i = 0; i < menuMgr->core.num_popups; i++)
+ {
+ shell = (CompositeWidget) menuMgr->core.popup_list[i];
+ if ((shell->composite.num_children == 1) &&
+ (XtIsSubclass(shell->composite.children[0],
+ XwmenupaneWidgetClass)))
+ {
+ if ((menubutton = (XwMenuButtonWidget)
+ XtNameToWidget(shell->composite.children[0], name))
+ != NULL)
+ {
+ /*
+ * Found it! Detach it
+ */
+ DoDetach (menuMgr, menubutton, menupane);
+ menuMgr->popup_mgr.detachPane = NULL;
+ return;
+ }
+ }
+ }
+ }
+
+ /* This must always be cleared when we leave */
+ menuMgr->popup_mgr.detachPane = NULL;
+}
+
+
+/*************************************<->*************************************
+ *
+ * DoDetach(parameters)
+ *
+ * Description:
+ * -----------
+ * This routine does the actual work of detaching a menupane from a
+ * menubutton. It has been separated out from DetachPane() due to
+ * a BUG in the X toolkits destroy scenario. When the toolkit is
+ * destroying popup children, it replaces the widget Id entry within
+ * the popup list with the window Id for that widget. DetachPane()
+ * attempts to traverse this list, looking for the named menubutton.
+ * Unfortunately, if this list contains any window Ids, then we may
+ * get a core dump; this only can happen when the menu is being
+ * destroyed.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void DoDetach (menuMgr, menubutton, menupane)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget menubutton;
+ XwMenuPaneWidget menupane;
+
+{
+ Arg arg[1];
+ register int i;
+
+ /* Detach a menupane from a menubutton */
+ XtRemoveCallback ((Widget)menubutton, XtNcascadeSelect,
+ (XtCallbackProc)_XwCascadeSelect, menupane->core.self);
+ XtRemoveCallback ((Widget)menubutton, XtNcascadeUnselect,
+ (XtCallbackProc)_XwCascadeUnselect, menupane->core.self);
+ ClearTreeAccelerators (menuMgr, menupane->core.self);
+
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) NULL);
+ XtSetValues ((Widget)menubutton, arg, 1);
+ menupane->menu_pane.attachId = NULL;
+
+ /*
+ * If this menupane is on the saved cascade list (because sticky
+ * menus are enabled), then we need to clean up the list, so that
+ * we don't dump core the next time we post.
+ */
+ if ((menuMgr->popup_mgr.stickyMode) &&
+ (menuMgr->popup_mgr.numSavedCascades > 0))
+ {
+ for (i = 0; i < menuMgr->popup_mgr.numSavedCascades; i++)
+ {
+ if (menuMgr->popup_mgr.savedCascadeList[i] ==
+ (Widget)menupane->core.self)
+ {
+ menuMgr->popup_mgr.numSavedCascades = 0;
+ break;
+ }
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * AddPane(menuMgr, menupane)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void AddPane (menuMgr, menupane)
+
+ register XwMenuMgrWidget menuMgr;
+ XwMenuPaneWidget menupane;
+
+{
+ register int k;
+ register int traversalType;
+ register XwMenuButtonWidget mbutton;
+
+ XtAddCallback ((Widget)menupane, XtNdestroyCallback,
+ (XtCallbackProc)_XwMenuPaneCleanup, menuMgr);
+
+ if (menuMgr->menu_mgr.selectString)
+ {
+ SetUpTranslation (menupane, menuMgr->menu_mgr.selectString,
+ selectTemplate);
+ }
+
+ if (menuMgr->menu_mgr.unpostString)
+ {
+ RegisterTranslation (menupane, menuMgr->menu_mgr.unpostString,
+ unpostTemplate, menuMgr);
+ }
+
+ if (menuMgr->menu_mgr.kbdSelectString)
+ {
+ SetUpTranslation (menupane, menuMgr->menu_mgr.kbdSelectString,
+ selectTemplate);
+ }
+
+ /* Propogate the state of our traversal flag */
+ if (XtIsSubclass ((Widget)menupane, XwmenupaneWidgetClass))
+ {
+ (*(((XwMenuPaneWidgetClass)
+ XtClass(menupane))-> menu_pane_class.setTraversalFlag))
+ ((Widget)menupane, menuMgr->manager.traversal_on);
+ }
+
+ /******************
+ * THE FOLLOWING IS NOT NEEDED, SINCE A MENUPANE CAN NEVER HAVE
+ * ANY CHILDREN AT THIS TIME.
+ *
+ * traversalType = (menuMgr->manager.traversal_on) ? XwHIGHLIGHT_TRAVERSAL:
+ * XwHIGHLIGHT_OFF;
+ *
+ * for (k = 0; k < menupane->manager.num_managed_children; k++)
+ * {
+ * /* Here we set the traversal flag for the menubuttons
+ * mbutton = (XwMenuButtonWidget)menupane->composite.children[k];
+ * if (XtIsSubclass (mbutton, XwmenubuttonWidgetClass))
+ * {
+ * (*(((XwMenuButtonWidgetClass)
+ * XtClass(mbutton))-> menubutton_class.setTraversalType))
+ * (mbutton, traversalType);
+ * }
+ * }
+ *********************/
+}
+
+/*************************************<->*************************************
+ *
+ * SetSelectAccelerator (menuMgr, menubutton, accelString, accelEventType,
+ * accelKey, accelModifiers)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetSelectAccelerator (menuMgr, menubutton, accelString,
+ accelEventType, accelKey, accelModifiers)
+Widget menuMgr;
+Widget menubutton;
+String accelString;
+unsigned int accelEventType;
+unsigned int accelKey;
+unsigned int accelModifiers;
+{
+ Widget widget;
+ XwKeyAccel * tempAccel;
+
+ if (CompletePath(menuMgr, menubutton->core.parent))
+ {
+ ClearSelectAccelerator (menuMgr, menubutton->core.self);
+ SetButtonAccelerators (menuMgr, menubutton->core.self, accelString,
+ accelEventType, accelKey, accelModifiers);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * ClearSelectAccelerator (menuMgr, menubutton)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClearSelectAccelerator (menuMgr, menubutton)
+
+ register XwPopupMgrWidget menuMgr;
+ Widget menubutton;
+
+{
+ register int i;
+ Widget widget;
+
+ /*
+ * search accelerator table for menubutton
+ */
+ for (i=0; i < menuMgr->menu_mgr.numAccels; i++)
+ {
+ if (menuMgr->menu_mgr.menuBtnAccelTable[i].menuBtn ==
+ menubutton->core.self)
+ {
+ /*
+ * remove translation in associated widget & toplevel pane
+ * and remove grab
+ */
+ widget = (Widget) XtParent (XtParent (menuMgr));
+ RegisterTranslation (widget,
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelString,
+ accelSelectTemplate, NULL);
+
+ if (menuMgr->popup_mgr.topLevelPane)
+ {
+ RegisterTranslation (menuMgr->popup_mgr.topLevelPane,
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelString,
+ accelSelectTemplate, NULL);
+
+ /*
+ * Because of a short coming in the toolkit, we need to
+ * potentially patch the top level widget's translations,
+ * if it was in the middle of a setvalues.
+ */
+ if ((menuMgr->popup_mgr.detachPane) &&
+ (menuMgr->popup_mgr.topLevelPane ==
+ menuMgr->popup_mgr.detachPane->core.self))
+ {
+ menuMgr->popup_mgr.detachPane->core.tm =
+ menuMgr->popup_mgr.topLevelPane->core.tm;
+ menuMgr->popup_mgr.detachPane->core.event_table =
+ menuMgr->popup_mgr.topLevelPane->core.event_table;
+ }
+ }
+
+ if ((menuMgr->menu_mgr.associateChildren) &&
+ (XtIsRealized (widget)))
+ {
+ XUngrabKey (XtDisplay (widget),
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelKey,
+ menuMgr->menu_mgr.menuBtnAccelTable[i].accelModifiers,
+ XtWindow (widget));
+ }
+
+ /*
+ * remove menubutton accelerator table entry
+ */
+ menuMgr->menu_mgr.menuBtnAccelTable[i] =
+ menuMgr->menu_mgr.menuBtnAccelTable[--menuMgr->menu_mgr.numAccels];
+
+ return;
+ }
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * AddButton(menuMgr, menubutton)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void AddButton (menuMgr, menubutton)
+
+ register XwMenuMgrWidget menuMgr;
+ register Widget menubutton;
+
+{
+ Arg args[2];
+ Widget pending;
+ int traversalType;
+
+ if (menuMgr->menu_mgr.selectString)
+ {
+ SetUpTranslation (menubutton, menuMgr->menu_mgr.selectString,
+ selectTemplate);
+ }
+ if (menuMgr->menu_mgr.unpostString)
+ {
+ RegisterTranslation (menubutton, menuMgr->menu_mgr.unpostString,
+ unpostTemplate, menuMgr);
+ }
+ if (menuMgr->menu_mgr.kbdSelectString)
+ {
+ SetUpTranslation (menubutton, menuMgr->menu_mgr.kbdSelectString,
+ selectTemplate);
+ }
+
+ XtSetArg (args[0], XtNcascadeOn, (XtArgVal) NULL);
+ XtSetArg (args[1], XtNmgrOverrideMnemonic, (XtArgVal) TRUE);
+ XtSetValues (menubutton, args, XtNumber(args));
+
+ XtAddCallback (menubutton, XtNdestroyCallback,
+ (XtCallbackProc)_XwMenuButtonCleanup, menuMgr);
+
+ /*
+ * Accelerators are now handled when the button is managed!
+ */
+
+ /*
+ * if this menubutton is on the pending attach list, do attach
+ */
+ if (pending = PendingAttach (menuMgr, menubutton))
+ AttachPane (menuMgr, pending, menubutton->core.name);
+
+ /* Propogate the our traversal state */
+ traversalType = (menuMgr->manager.traversal_on) ? XwHIGHLIGHT_TRAVERSAL:
+ XwHIGHLIGHT_OFF;
+
+ if (XtIsSubclass (menubutton, XwmenubuttonWidgetClass))
+ {
+ (*(((XwMenuButtonWidgetClass)
+ XtClass(menubutton))-> menubutton_class.setTraversalType))
+ (menubutton, traversalType);
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * Unpost (menuMgr, menupane)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void Unpost (menuMgr, menupane)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuPaneWidget menupane;
+
+{
+ register int i,j;
+ register XwMenuPaneWidget pane;
+ register Widget * currentCascadeList;
+ register WidgetList managed_children;
+
+ /*
+ * To keep all window managers happy, move the focus before we pop
+ * down the menupane with the current focus.
+ */
+ if ((menupane != (XwMenuPaneWidget) menuMgr->popup_mgr.topLevelPane) &&
+ (menuMgr->manager.traversal_on))
+ {
+ XwMoveFocus (XtParent(menupane->menu_pane.attachId));
+ }
+
+ currentCascadeList = menuMgr->popup_mgr.currentCascadeList;
+
+ /*
+ * popdown any cascading submenus including menupane
+ */
+ for (i = menuMgr->popup_mgr.numCascades - 1; i >= 0; i--)
+ {
+ /*
+ * for each button in pane, unhighlight it and clear cascade flag
+ */
+ pane = ((XwMenuPaneWidget) currentCascadeList[i]);
+ XtRemoveGrab ((Widget)pane);
+ XtPopdown (XtParent (pane));
+ managed_children = pane->manager.managed_children;
+
+ for (j = 0; j < pane->manager.num_managed_children; j++)
+ {
+ if (XtIsSubclass (managed_children[j], XwmenubuttonWidgetClass))
+ {
+ (*(((XwMenuButtonWidgetClass)
+ XtClass(managed_children[j]))->menubutton_class.unhighlightProc))
+ (managed_children[j]);
+ (*(((XwMenuButtonWidgetClass)
+ XtClass(managed_children[j]))->menubutton_class.clearCascadeProc))
+ (managed_children[j]);
+ }
+ }
+
+ --menuMgr->popup_mgr.numCascades;
+
+ /*
+ * if this is not the target pane then the next one must have had an enter
+ * window event handler added when cascaded out of it.
+ */
+ if ((pane != menupane) && (i > 0))
+ {
+ if (menuMgr->manager.traversal_on == FALSE)
+ {
+ XtRemoveEventHandler (currentCascadeList[i-1],
+ EnterWindowMask, FALSE,
+ (XtEventHandler)
+ ((XwMenuButtonWidgetClass)
+ XtClass(pane->menu_pane.attachId))->
+ menubutton_class.enterParentProc,
+ pane->menu_pane.attachId);
+ }
+ else
+ {
+ /* Kludge to force the grablist to get cleaned up */
+ XtSetKeyboardFocus (XtParent(pane), None);
+ }
+ }
+ else
+ {
+ if (menuMgr->manager.traversal_on)
+ {
+ /* Kludge to force the grablist to get cleaned up */
+ XtSetKeyboardFocus (XtParent(pane), None);
+ }
+ XFlush (XtDisplay(menuMgr));
+ return;
+ }
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * Post(menuMgr, menupane, grabtype)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ * _XtPopup
+ *
+ *************************************<->***********************************/
+
+static void Post (menuMgr, menupane, grabtype)
+
+ register XwPopupMgrWidget menuMgr;
+ Widget menupane;
+ XtGrabKind grabtype;
+
+{
+ register int i;
+
+ /*
+ * if already posted, do nothing
+ */
+ for (i=0; i < menuMgr->popup_mgr.numCascades; i++)
+ if (menuMgr->popup_mgr.currentCascadeList[i] == menupane)
+ return;
+
+ /*
+ * set up grabs
+ */
+ if (grabtype == XtGrabNonexclusive)
+ {
+ _XtPopup (XtParent (menupane), grabtype, FALSE);
+ XtAddGrab (menupane, FALSE, FALSE);
+ }
+ else
+ {
+ _XtPopup (XtParent (menupane), grabtype, TRUE);
+ XtAddGrab (menupane, TRUE, TRUE);
+ }
+
+ /*
+ * add menupane to current cascade list
+ */
+ if (menuMgr->popup_mgr.numCascades == menuMgr->popup_mgr.sizeCascadeList)
+ {
+ menuMgr->popup_mgr.sizeCascadeList =
+ 2 * menuMgr->popup_mgr.sizeCascadeList;
+ menuMgr->popup_mgr.currentCascadeList =
+ (Widget *) XtRealloc((char *)(menuMgr->popup_mgr.currentCascadeList),
+ menuMgr->popup_mgr.sizeCascadeList *
+ sizeof (Widget));
+ }
+
+ menuMgr->popup_mgr.currentCascadeList[menuMgr->popup_mgr.numCascades++] =
+ menupane;
+}
+
+/*************************************<->*************************************
+ *
+ * ProcessSelect(menuMgr, widget, event)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean ProcessSelect (menuMgr, widget, event)
+
+ register XwPopupMgrWidget menuMgr;
+ Widget widget;
+ XEvent * event;
+
+{
+ register XwKeyAccel * accelerator;
+ register int i;
+ Boolean found = FALSE;
+ Widget assocWidget;
+ Boolean traversalOn;
+
+ /*
+ * If the menu manager or the associated widget is insensitive, then
+ * ignore the select request.
+ */
+ assocWidget = XtParent(XtParent(menuMgr));
+ if (!XtIsSensitive((Widget)menuMgr) || !XtIsSensitive(assocWidget))
+ return (FALSE);
+
+ /*
+ * is this a valid button event?
+ */
+ if ((event->xany.type==ButtonPress) || (event->xany.type==ButtonRelease))
+ {
+
+ if (_XwMatchBtnEvent (event, menuMgr->menu_mgr.selectEventType,
+ menuMgr->menu_mgr.selectButton,
+ menuMgr->menu_mgr.selectModifiers))
+ {
+ if (menuMgr->menu_mgr.menuActive == FALSE)
+ return (FALSE);
+
+ /*
+ * During traversal, since menupanes are not unposted when
+ * the mouse enters a different menupane, we need to ignore
+ * selects which occur in a menubtn in one of these panes.
+ */
+ if ((menuMgr->manager.traversal_on) &&
+ (XtIsSubclass (widget, XwmenubuttonWidgetClass)) &&
+ (XtParent(widget) != menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]))
+ {
+ return (FALSE);
+ }
+
+ SetUpStickyList (menuMgr, widget);
+ }
+ else
+ return (FALSE);
+ }
+ /*
+ * if its not key accelerator, return false
+ */
+ else if ((event->xany.type == KeyPress) || (event->xany.type == KeyRelease))
+ {
+ /* Check for the kbd select event */
+ if (_XwMatchKeyEvent (event,
+ menuMgr->menu_mgr.kbdSelectEventType,
+ menuMgr->menu_mgr.kbdSelectKey,
+ menuMgr->menu_mgr.kbdSelectModifiers))
+ {
+ SetUpStickyList (menuMgr, widget);
+ }
+ else
+ {
+ for (i=0; (i < menuMgr->menu_mgr.numAccels) && (found == FALSE); i++)
+ {
+ accelerator = menuMgr->menu_mgr.menuBtnAccelTable + i;
+ found = _XwMatchKeyEvent (event,
+ accelerator->accelEventType,
+ accelerator->accelKey,
+ accelerator->accelModifiers);
+ }
+
+ if (found == FALSE)
+ return (FALSE);
+
+ menuMgr->popup_mgr.numSavedCascades = 0;
+ if (menuMgr->manager.traversal_on)
+ {
+ /* Force the first item to be highlighted next time */
+ ((XwPopupMgrWidget)menuMgr->popup_mgr.topLevelPane)->
+ manager.active_child = NULL;
+ XtSetKeyboardFocus (menuMgr->popup_mgr.topLevelPane, NULL);
+ }
+ /* SetUpStickyList (menuMgr, widget); */
+ }
+ }
+ else
+ return (FALSE);
+
+ /*
+ * if the menu system is active, bring it down
+ */
+ if (menuMgr->menu_mgr.menuActive)
+ {
+ /*
+ * We need to use a temporary variable because the application has
+ * the chance to change this from underneath us if they have set up
+ * an unpost callback.
+ */
+ traversalOn = menuMgr->manager.traversal_on;
+
+ menuMgr->menu_mgr.menuActive = FALSE;
+
+ Unpost (menuMgr, menuMgr->popup_mgr.topLevelPane);
+
+ /* We need to remove the grab we set in ClassPost() */
+ XUngrabPointer (XtDisplay(menuMgr), CurrentTime);
+
+ /*
+ * If we warped the mouse because traversal was on, then we need
+ * to move it back to where it was.
+ */
+ if (traversalOn &&
+ (menuMgr->popup_mgr.origMouseX != -1) &&
+ (menuMgr->popup_mgr.origMouseY != -1))
+ {
+ XWarpPointer (XtDisplay (menuMgr), None,
+ RootWindowOfScreen(menuMgr->core.screen),
+ 0, 0, 0, 0,
+ menuMgr->popup_mgr.origMouseX,
+ menuMgr->popup_mgr.origMouseY);
+ menuMgr->popup_mgr.origMouseX = -1;
+ menuMgr->popup_mgr.origMouseY = -1;
+ }
+ }
+ return (TRUE);
+}
+
+/*************************************<->*************************************
+ *
+ * ValidEvent(menuMgr, menubutton, event)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean ValidEvent (menuMgr, menubutton, event)
+
+ XwPopupMgrWidget menuMgr;
+ Widget menubutton;
+ XEvent * event;
+
+{
+ /* Ignore enter and leave events if traversal is active */
+ if (menuMgr->manager.traversal_on)
+ return (FALSE);
+ else
+ return (TRUE);
+}
+
+/*************************************<->*************************************
+ *
+ * DoICascade (menuMgr)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean DoICascade (menuMgr, menuBtn)
+
+ register XwPopupMgrWidget menuMgr;
+ Widget menuBtn;
+
+{
+ /* Ignore cascade events if traversal is currently active */
+ if ((menuMgr->menu_mgr.menuActive) &&
+ (menuMgr->manager.traversal_on == FALSE))
+ {
+ Widget lastCascade = menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades -1];
+
+ if ((XtParent(menuBtn) == lastCascade) ||
+ (menuBtn == ((XwMenuPaneWidget)(lastCascade))->menu_pane.attachId))
+ {
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
+/*************************************<->*************************************
+ *
+ * ClassPost(menuMgr, event, warpOn)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassPost (menuMgr, event, warpOn)
+
+ register XwPopupMgrWidget menuMgr;
+ XEvent * event;
+ Boolean warpOn;
+
+{
+ register int i;
+ Position posx, posy;
+ int x, y, relativeX, relativeY;
+ int yDelta;
+ XButtonEvent * buttonEvent = (XButtonEvent *) event;
+ Widget assocWidget, w;
+ Widget menuBtn;
+ XwMenuPaneWidget tempPane;
+ XwManagerWidget topLevelPane;
+ XWindowChanges windowChanges;
+ ShellWidget shell;
+ Window root, child;
+ int rootx, rooty, childx, childy;
+ unsigned int returnMask;
+
+ /*
+ * If either the menu manager or the associated widget is insensitive,
+ * then ignore the post request.
+ */
+ assocWidget = XtParent (XtParent (menuMgr));
+ if (!XtIsSensitive((Widget)menuMgr) || !XtIsSensitive(assocWidget))
+ return;
+
+ /*
+ * if menus are not inherited, throw out events that did occur
+ * in the associated widget's children.
+ */
+ if (menuMgr->menu_mgr.associateChildren == FALSE)
+ {
+ if ((event->xkey.window == XtWindow (XtParent (XtParent (menuMgr)))) &&
+ (event->xkey.subwindow != 0) &&
+ (XtWindowToWidget (XtDisplay (menuMgr), event->xkey.subwindow)))
+ return;
+ }
+
+ /*
+ * The following is a kludge fix to bypass a shortcoming within Xtk.
+ * We need to manually inform the previous focus widget that it has
+ * lost the cursor; this is because once we add our popups to the
+ * grablist, the LeaveNotify will be ignored for the focus widget,
+ * because it is not on the grablist.
+ */
+ /* if (menuMgr->manager.traversal_on) */
+ SendFakeLeaveNotify(menuMgr, ULTIMATE_PARENT);
+
+ /* Mark the menu system as 'active' */
+ menuMgr->menu_mgr.menuActive = TRUE;
+
+ /*
+ * Position the menupane's parent shell. If its a post, position to
+ * the pointer position. If its an accelerator, position to the center
+ * of the associated widget
+ */
+ topLevelPane =(XwManagerWidget)menuMgr->popup_mgr.topLevelPane;
+
+ /*
+ * In order for this algorithm to work, we need to make sure the
+ * menupane has been realized; this is because its size is not
+ * yet valid because it is not notified that it has any children
+ * until it is realized.
+ */
+ if (!XtIsRealized (XtParent(topLevelPane )))
+ XtRealizeWidget (XtParent (topLevelPane ));
+
+ if ((event->type == ButtonPress) ||
+ (event->type == ButtonRelease))
+ {
+
+ /*
+ * The server does an implicit grab, but doesn't do it in the
+ * manner we need for menupanes and menubuttons to continue
+ * to highlight and function.
+ */
+ if (event->type == ButtonPress)
+ XUngrabPointer (XtDisplay(menuMgr), CurrentTime);
+
+ /*
+ * If traversal is on, then save the current mouse position,
+ * so that we can restore the mouse to its original position
+ * when the menu is unposted.
+ */
+ if (menuMgr->manager.traversal_on)
+ {
+ menuMgr->popup_mgr.origMouseX = buttonEvent->x_root;
+ menuMgr->popup_mgr.origMouseY = buttonEvent->y_root;
+ }
+
+ x = buttonEvent->x_root - (XwCASCADEWIDTH + FUDGE_FACTOR +
+ topLevelPane ->core.border_width);
+ y = buttonEvent->y_root;
+
+ /* Attempt to center on the first button in the new menupane */
+ {
+
+ if (topLevelPane->manager.num_managed_children > 0)
+ {
+ Widget firstButton = topLevelPane->manager.managed_children[0];
+
+/*
+ yDelta = firstButton->core.y +
+ firstButton->core.border_width +
+ (firstButton->core.height >> 1);
+*/
+ yDelta = 0;
+ }
+ else
+ {
+ yDelta = topLevelPane->core.border_width +
+ (topLevelPane->core.height >> 1);
+ }
+ }
+
+ y -= yDelta;
+ }
+ else
+ {
+ /*
+ * center on the associated widget
+ */
+ relativeX = (assocWidget->core.width>>1);
+ relativeY = (assocWidget->core.height>>1);
+
+ /* Get our coordinates, relative to the root window */
+ XTranslateCoordinates (XtDisplay(menuMgr),
+ assocWidget->core.window,
+ RootWindowOfScreen(XtScreen(menuMgr)),
+ relativeX,
+ relativeY,
+ &x, &y, &child);
+
+ /*
+ * If traversal is on, then save the current mouse position,
+ * so that we can restore the mouse to its original position
+ * when the menu is unposted.
+ */
+ if (menuMgr->manager.traversal_on)
+ {
+ if (XQueryPointer(XtDisplay(menuMgr),
+ RootWindowOfScreen(menuMgr->core.screen),
+ &root, &child, &rootx, &rooty, &childx,
+ &childy, &returnMask))
+ {
+ menuMgr->popup_mgr.origMouseX = rootx;
+ menuMgr->popup_mgr.origMouseY = rooty;
+ }
+ }
+ }
+
+ posx = x; posy = y;
+ ForceMenuPaneOnScreen (topLevelPane, &posx, &posy);
+ x = posx; y = posy;
+ XtMoveWidget (XtParent(topLevelPane), x, y);
+
+ /*
+ * This allows us to catch all selects, and unpost the menus
+ * regardless where the select event occurs.
+ */
+ XGrabPointer (XtDisplay(menuMgr), XtWindow(assocWidget), TRUE,
+ ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|
+ PointerMotionMask, GrabModeAsync, GrabModeAsync, None, (Cursor)NULL,
+ CurrentTime);
+
+ if ((menuMgr->popup_mgr.stickyMode) &&
+ (menuMgr->popup_mgr.numSavedCascades))
+ {
+ /*
+ * Attempt to gracefully handle the case where one of the menupanes
+ * or menubuttons in the current cascade list has become insensitive
+ * since the last posting.
+ */
+ for (i=0; i < menuMgr->popup_mgr.numSavedCascades; i++)
+ {
+ tempPane = (XwMenuPaneWidget)menuMgr->popup_mgr.savedCascadeList[i];
+
+ if ((tempPane->menu_pane.attachId) &&
+ (!XtIsSensitive(tempPane->menu_pane.attachId)))
+ {
+ /*
+ * We are cascading from an insensitive menubutton.
+ * Stop at the preceeding menupane.
+ */
+ menuMgr->popup_mgr.numSavedCascades = i;
+ menuMgr->popup_mgr.lastSelected = tempPane->menu_pane.attachId;
+ break;
+ }
+ else if (!XtIsSensitive((Widget)tempPane))
+ {
+ /*
+ * If this menupane is insensitive, then stop here.
+ */
+ menuMgr->popup_mgr.numSavedCascades = i + 1;
+ if (tempPane->manager.num_managed_children > 0)
+ {
+ menuMgr->popup_mgr.lastSelected = tempPane->manager.
+ managed_children[0];
+ }
+ else
+ menuMgr->popup_mgr.lastSelected = (Widget)tempPane;
+ break;
+ }
+ }
+
+ /* Set up grab for the top level menupane */
+ XtAddGrab (XtParent(topLevelPane), TRUE, TRUE);
+ XtAddGrab ((Widget)topLevelPane, TRUE, TRUE);
+ menuMgr->popup_mgr.currentCascadeList[menuMgr->popup_mgr.numCascades++] =
+ (Widget)topLevelPane;
+
+ /*
+ * position the menupanes on the sticky cascade list
+ */
+ for (i=1; i < menuMgr->popup_mgr.numSavedCascades; i++)
+ {
+ tempPane = (XwMenuPaneWidget) menuMgr->popup_mgr.savedCascadeList[i];
+ PositionCascade (tempPane->menu_pane.attachId, tempPane);
+ XtAddGrab (XtParent(tempPane), FALSE, FALSE);
+ XtAddGrab ((Widget)tempPane, FALSE, FALSE);
+ menuMgr->popup_mgr.currentCascadeList
+ [menuMgr->popup_mgr.numCascades++] = (Widget)tempPane;
+ }
+
+ /*
+ * warp the pointer to its final destination. This must be done
+ * AFTER the panes are positioned, but BEFORE they are posted.
+ */
+ if (warpOn)
+ {
+ XWarpPointer (XtDisplay (menuMgr), None,
+ XtWindow(menuMgr->popup_mgr.lastSelected),
+ 0, 0, 0, 0, 5, 5);
+ }
+
+ /* Post the last menupane */
+ shell = (ShellWidget)XtParent (menuMgr->popup_mgr.savedCascadeList
+ [menuMgr->popup_mgr.numSavedCascades - 1]);
+ shell->shell.popped_up = TRUE;
+ shell->shell.grab_kind = XtGrabNonexclusive;
+ shell->shell.spring_loaded = FALSE;
+ if (!XtIsRealized((Widget)shell))
+ XtRealizeWidget ((Widget)shell);
+ XMapRaised (XtDisplay(shell), XtWindow(shell));
+
+ /*
+ * Post and then configure the menupanes and menubuttons.
+ * THIS MUST BE DONE AFTER THE WARP POINTER!!!
+ */
+ for (i= menuMgr->popup_mgr.numSavedCascades - 2; i >= 0; i--)
+ {
+ /*
+ * Popup the pane and add to the grablist.
+ * This cannot use _XtPopup() because it used XMapRaised().
+ */
+ tempPane = (XwMenuPaneWidget) menuMgr->popup_mgr.savedCascadeList[i];
+ shell = (ShellWidget) XtParent(tempPane);
+ windowChanges.sibling = XtWindow(XtParent(menuMgr->popup_mgr.
+ savedCascadeList[i+1]));
+ windowChanges.stack_mode = Below;
+ XConfigureWindow (XtDisplay(menuMgr), XtWindow(shell),
+ CWSibling | CWStackMode, &windowChanges);
+ shell->shell.popped_up = TRUE;
+ shell->shell.grab_kind = XtGrabNonexclusive;
+ shell->shell.spring_loaded = FALSE;
+ if (!XtIsRealized ((Widget)shell))
+ XtRealizeWidget ((Widget)shell);
+ XMapWindow (XtDisplay(shell), XtWindow(shell));
+
+ /*
+ * highlight menubutton, set its cascade flag and set up event
+ * handler on its parent
+ */
+ menuBtn = (((XwMenuPaneWidget)(menuMgr->popup_mgr.
+ savedCascadeList[i+1]))->menu_pane.attachId);
+
+ if (menuMgr->manager.traversal_on == FALSE)
+ {
+ (*(((XwMenuButtonWidgetClass)
+ XtClass(menuBtn))->menubutton_class.highlightProc)) (menuBtn);
+ }
+
+ (*(((XwMenuButtonWidgetClass) XtClass(menuBtn))->
+ menubutton_class.setCascadeProc)) (menuBtn);
+
+ if (menuMgr->manager.traversal_on == FALSE)
+ {
+ XtAddEventHandler ((Widget)tempPane, EnterWindowMask, False,
+ (XtEventHandler)
+ ((XwMenuButtonWidgetClass) XtClass(menuBtn))->
+ menubutton_class.enterParentProc,
+ menuBtn);
+ }
+ }
+
+ /*
+ * DON'T DO THE FOLLOWING; HAVE THE ITEM HILIGHT WHEN THE CURSOR
+ * ENTERS IT.
+ */
+ /********
+ * for keyboard posts, highlight the last selected menubutton.
+ *
+ *if ((warpOn == FALSE) && (menuMgr->manager.traversal_on == FALSE))
+ *{
+ * (*(((XwMenuButtonWidgetClass)
+ * XtClass(menuMgr->popup_mgr.lastSelected))->
+ * menubutton_class.highlightProc))
+ * (menuMgr->popup_mgr.lastSelected);
+ *}
+ *******/
+ }
+ else
+ {
+ /*
+ * post only the toplevel.
+ * post the toplevel menupane with exclusive grabs. All other panes
+ * have nonexclusive grabs.
+ */
+ Post (menuMgr, topLevelPane, XtGrabExclusive);
+ }
+
+ /* Set the traversal focus to the last pane, if necessary */
+ if (menuMgr->manager.traversal_on)
+ {
+ XwMoveFocus (menuMgr->popup_mgr.currentCascadeList [
+ menuMgr->popup_mgr.numCascades - 1]);
+ }
+
+ XFlush(XtDisplay(menuMgr));
+}
+
+/*************************************<->*************************************
+ *
+ * ClassSelect(menuMgr, event)
+ *
+ * Description:
+ * -----------
+ * Called only when a menubutton select accelerator is received.
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClassSelect (menuMgr, event)
+
+ XwMenuMgrWidget menuMgr;
+ XEvent * event;
+
+{
+ register int i;
+ Widget assocWidget;
+ register XwKeyAccel * accelerator;
+
+ /*
+ * If either the menu manager or the associated widget is insensitive,
+ * then ignore the select accelerator.
+ */
+ assocWidget = XtParent(XtParent(menuMgr));
+ if (!XtIsSensitive((Widget)menuMgr) || !XtIsSensitive(assocWidget))
+ return;
+
+ /*
+ * map the event into an accelerator and call the menubuttons select rtn.
+ */
+ for (i=0; i < menuMgr->menu_mgr.numAccels; i++)
+ {
+ accelerator = menuMgr->menu_mgr.menuBtnAccelTable + i;
+
+ if (_XwMatchKeyEvent (event,
+ accelerator->accelEventType,
+ accelerator->accelKey,
+ accelerator->accelModifiers))
+ {
+ if (XtIsSensitive(accelerator->menuBtn) &&
+ _XwAllAttachesAreSensitive(accelerator->menuBtn))
+ {
+ (*(((XwMenuButtonWidgetClass)
+ XtClass (accelerator->menuBtn))-> primitive_class.select_proc))
+ (accelerator->menuBtn, event);
+ }
+
+ return;
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * AddToPendingList(menuMgr, menupane, name)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void AddToPendingList (menuMgr, menupane, name)
+
+ register XwMenuMgrWidget menuMgr;
+ Widget menupane;
+ String name;
+
+{
+ register int nameLen;
+ register int i;
+ Arg arg[1];
+ register String button;
+
+ /*
+ * If there is already a request in the pending list for an attach
+ * to the same menu button, then we need to remove the older one.
+ */
+ nameLen = XwStrlen(name);
+ for (i = 0; i < menuMgr->menu_mgr.numAttachReqs; i++)
+ {
+ button = menuMgr->menu_mgr.pendingAttachList[i].menuBtnName;
+ if ((strcmp(name, button) == 0) && (nameLen == XwStrlen(button)))
+ {
+ /* Detach the older request */
+ XtSetArg (arg[0], XtNattachTo, (XtArgVal) NULL);
+ XtSetValues (menuMgr->menu_mgr.pendingAttachList[i].menupaneId,
+ arg, 1);
+ break;
+ }
+ }
+
+ if (menuMgr->menu_mgr.numAttachReqs == menuMgr->menu_mgr.sizeAttachList)
+ {
+ /*
+ * resize the list
+ */
+ menuMgr->menu_mgr.sizeAttachList = 2 * menuMgr->menu_mgr.sizeAttachList;
+ menuMgr->menu_mgr.pendingAttachList =
+ (XwAttachList *) XtRealloc((char *)(menuMgr->menu_mgr.pendingAttachList),
+ menuMgr->menu_mgr.sizeAttachList *
+ sizeof(XwAttachList));
+ }
+ menuMgr->menu_mgr.pendingAttachList
+ [menuMgr->menu_mgr.numAttachReqs].menuBtnName = name;
+ menuMgr->menu_mgr.pendingAttachList
+ [menuMgr->menu_mgr.numAttachReqs++].menupaneId = menupane->core.self;
+}
+
+/*************************************<->*************************************
+ *
+ * SetButtonAccelerators (menuMgr, menubutton, accelString, accelEventType,
+ * accelKey, accelModifiers)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetButtonAccelerators (menuMgr, menubutton, accelString,
+ accelEventType, accelKey, accelModifiers)
+
+ register XwPopupMgrWidget menuMgr;
+ Widget menubutton;
+ String accelString;
+ unsigned int accelEventType;
+ unsigned int accelKey;
+ unsigned int accelModifiers;
+
+{
+ Widget widget;
+ register XwKeyAccel * accelerator;
+
+ /*
+ * add entry to menubutton accelerator table
+ */
+ if (menuMgr->menu_mgr.numAccels == menuMgr->menu_mgr.sizeAccelTable)
+ {
+ menuMgr->menu_mgr.sizeAccelTable =
+ 2 * menuMgr->menu_mgr.sizeAccelTable;
+ menuMgr->menu_mgr.menuBtnAccelTable =
+ (XwKeyAccel *) XtRealloc((char *)(menuMgr->menu_mgr.menuBtnAccelTable),
+ menuMgr->menu_mgr.sizeAccelTable *
+ sizeof(XwKeyAccel));
+ }
+
+ accelerator = menuMgr->menu_mgr.menuBtnAccelTable +
+ menuMgr->menu_mgr.numAccels;
+ accelerator->accelString = accelString;
+ accelerator->accelEventType = accelEventType;
+ accelerator->accelKey = accelKey;
+ accelerator->accelModifiers = accelModifiers;
+ accelerator->menuBtn = menubutton->core.self;
+ menuMgr->menu_mgr.numAccels++;
+
+ /*
+ * set translation in associated widget & toplevel pane for accelerator
+ */
+ widget = (Widget) XtParent (XtParent (menuMgr));
+ RegisterTranslation (widget, accelString, accelSelectTemplate, menuMgr);
+
+ if (menuMgr->popup_mgr.topLevelPane)
+ {
+ RegisterTranslation (menuMgr->popup_mgr.topLevelPane, accelString,
+ accelSelectTemplate, menuMgr);
+
+ /*
+ * Because of a short coming in the toolkit, we need to
+ * potentially patch the top level widget's translations,
+ * if it was in the middle of a setvalues.
+ */
+ if ((menuMgr->popup_mgr.attachPane) &&
+ (menuMgr->popup_mgr.topLevelPane ==
+ menuMgr->popup_mgr.attachPane->core.self))
+ {
+ menuMgr->popup_mgr.attachPane->core.tm =
+ menuMgr->popup_mgr.topLevelPane->core.tm;
+ menuMgr->popup_mgr.attachPane->core.event_table =
+ menuMgr->popup_mgr.topLevelPane->core.event_table;
+ }
+ }
+
+ /*
+ * set up key grabs if possible
+ */
+ if ((menuMgr->menu_mgr.associateChildren) && (XtIsRealized (widget)))
+ XGrabKey (XtDisplay (widget), accelKey, accelModifiers,
+ XtWindow (widget), False, GrabModeAsync, GrabModeAsync);
+}
+
+/*************************************<->*************************************
+ *
+ * SetTreeAccelerators (menuMgr, menupane)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetTreeAccelerators (menuMgr, menupane)
+
+ XwMenuMgrWidget menuMgr;
+ XwMenuPaneWidget menupane;
+
+{
+ register int i;
+ Arg args[2];
+ unsigned int eventType;
+ KeyCode key;
+ unsigned int modifiers;
+ KeySym tempKeysym;
+ register WidgetList managed_children;
+
+ managed_children = menupane->manager.managed_children;
+
+ for (i=0; i < menupane->manager.num_managed_children; i++)
+ {
+ if (XtIsSubclass (managed_children[i], XwmenubuttonWidgetClass))
+ {
+ String dkey = NULL;
+ Widget dtree = NULL;
+
+ XtSetArg (args[0], XtNkbdAccelerator, (XtArgVal)(&dkey));
+ XtSetArg (args[1], XtNcascadeOn, (XtArgVal)(&dtree));
+ XtGetValues (managed_children[i], args, XtNumber(args));
+
+ /*
+ * set up keyboard accelerators
+ */
+ if (dkey)
+ {
+ _XwMapKeyEvent (dkey, &eventType, &tempKeysym, &modifiers);
+ key = XKeysymToKeycode (XtDisplay (menupane), tempKeysym);
+ SetButtonAccelerators (menuMgr, managed_children[i],
+ dkey, eventType, key, modifiers);
+ }
+ /*
+ * traverse any submenus
+ */
+ if (dtree)
+ SetTreeAccelerators (menuMgr, dtree);
+ }
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * ClearTreeAccelerators (menuMgr, menupane)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClearTreeAccelerators (menuMgr, menupane)
+
+ Widget menuMgr;
+ XwMenuPaneWidget menupane;
+
+{
+ register int i;
+ Arg arg[1];
+ register WidgetList managed_children;
+
+ managed_children = menupane->manager.managed_children;
+
+ for (i=0; i < menupane->manager.num_managed_children; i++)
+ {
+ if (XtIsSubclass (managed_children[i], XwmenubuttonWidgetClass))
+ {
+ Widget twidg = NULL;
+ ClearSelectAccelerator(menuMgr, managed_children[i]);
+
+ /*
+ * clear accelerators from any submenu
+ */
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) &twidg);
+ XtGetValues (managed_children[i], arg, 1);
+ if (twidg)
+ ClearTreeAccelerators (menuMgr, twidg);
+ }
+ }
+}
+
+/*************************************<->*************************************
+ *
+ * CompletePath(menuMgr, menupane)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean CompletePath (menuMgr, menupane)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuPaneWidget menupane;
+
+{
+ register XwMenuPaneWidget pane;
+
+ if (menuMgr->popup_mgr.topLevelPane == FALSE)
+ return (FALSE);
+
+ for (pane = menupane; pane != NULL;
+ pane = (XwMenuPaneWidget) XtParent (pane->menu_pane.attachId))
+ {
+ if (pane == (XwMenuPaneWidget) menuMgr->popup_mgr.topLevelPane)
+ return (TRUE);
+
+ if (pane->menu_pane.attachId == NULL)
+ return (FALSE);
+
+ if (pane->core.managed == False)
+ return (FALSE);
+
+ if ((pane->menu_pane.attachId)->core.mapped_when_managed == FALSE)
+ return (FALSE);
+
+ if ((pane->menu_pane.attachId)->core.managed == FALSE)
+ return (FALSE);
+ }
+ return (FALSE);
+}
+
+/*************************************<->*************************************
+ *
+ * PendingAttach (menuMgr, menubutton)
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Widget PendingAttach (menuMgr, menubutton)
+
+ XwMenuMgrWidget menuMgr;
+ register Widget menubutton;
+
+{
+ register int i;
+ Widget id;
+ register String buttonName = menubutton->core.name;
+ register int buttonNameLen = XwStrlen(buttonName);
+ register XwAttachList * pendingAttachList;
+
+ pendingAttachList = menuMgr->menu_mgr.pendingAttachList;
+
+ for (i=0; i < menuMgr->menu_mgr.numAttachReqs; i++)
+ {
+ if ((strcmp (pendingAttachList[i].menuBtnName, buttonName) == 0) &&
+ (XwStrlen(pendingAttachList[i].menuBtnName) == buttonNameLen))
+ {
+ id = pendingAttachList[i].menupaneId;
+
+ /* Remove from pending attach list */
+ pendingAttachList[i] = pendingAttachList[--menuMgr->menu_mgr.
+ numAttachReqs];
+
+ return (id);
+ }
+ }
+
+ return (NULL);
+}
+
+/*************************************<->*************************************
+ *
+ * SetUpTranslation (widget, event, action)
+ *
+ * Description:
+ * -----------
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetUpTranslation (widget, event, action)
+
+ Widget widget;
+ String event;
+ String action;
+
+{
+ register String workSpace;
+ XtTranslations translations;
+
+ workSpace = &workArea[0];
+
+ strcpy (workSpace, "!");
+ strcat (workSpace, event);
+ strcat (workSpace, action);
+
+ /*
+ * compile the translation and attach to the menupane
+ */
+ translations = XtParseTranslationTable(workSpace);
+ XtOverrideTranslations (widget, translations);
+ /* XtDestroyStateTable (XtClass(widget), translations); */
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetPostMnemonic (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetPostMnemonic (menuMgr, menupane, mnemonic)
+
+ Widget menuMgr;
+ Widget menupane;
+ String mnemonic;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * ClearPostMnemonic (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClearPostMnemonic (menuMgr, menupane)
+
+ Widget menuMgr;
+ Widget menupane;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetTitleAttributes (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetTitleAttributes(w, x)
+ Widget w, x;
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * ForceMenuPaneOnScreen (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ForceMenuPaneOnScreen (menupane, x, y)
+
+ register Widget menupane;
+ register Position * x;
+ register Position * y;
+
+{
+ int rightEdgeOfMenu, dispWidth;
+ int bottomEdgeOfMenu, dispHeight;
+
+ /*
+ * In order for this algorithm to work, we need to make sure the
+ * menupane has been realized; this is because its size is not
+ * yet valid because it is not notified that it has any children
+ * until it is realized.
+ */
+ if (!XtIsRealized (XtParent(menupane)))
+ XtRealizeWidget (XtParent (menupane));
+
+ /* Force the menupane to be completely visible */
+
+ rightEdgeOfMenu = *x + (menupane->core.border_width << 1) +
+ menupane->core.width;
+ bottomEdgeOfMenu = *y + (menupane->core.border_width << 1) +
+ menupane->core.height;
+ dispWidth = WidthOfScreen (XtScreen(menupane));
+ dispHeight = HeightOfScreen (XtScreen(menupane));
+
+ if (*x < 0)
+ *x = 0;
+
+ if (*y < 0)
+ *y = 0;
+
+ if (rightEdgeOfMenu >= dispWidth)
+ *x -= (rightEdgeOfMenu - dispWidth + 1);
+
+ if (bottomEdgeOfMenu >= dispHeight)
+ *y -= (bottomEdgeOfMenu - dispHeight + 1);
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetSelectMnemonic (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetSelectMnemonic (menuMgr, menubutton, mnemonic)
+
+ Widget menuMgr;
+ Widget menubutton;
+ String mnemonic;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * ClearSelectMnemonic (parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ClearSelectMnemonic (menuMgr, menupane)
+
+ Widget menuMgr;
+ Widget menupane;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * OnCascadeList(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean OnCascadeList (menuMgr, menupane)
+
+ register XwPopupMgrWidget menuMgr;
+ register XwMenuPaneWidget menupane;
+{
+ register int i;
+
+ if ((menuMgr->popup_mgr.stickyMode) &&
+ (menuMgr->popup_mgr.numSavedCascades > 0))
+ {
+ for (i=0; i < menuMgr->popup_mgr.numSavedCascades; i++)
+ {
+ if ((Widget)menupane->core.self ==
+ menuMgr->popup_mgr.savedCascadeList[i])
+ {
+ return (True);
+ }
+ }
+ }
+
+ return (False);
+}
+
+/*************************************<->*************************************
+ *
+ * PaneManagedChildren()
+ *
+ * Description:
+ * -----------
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ *
+ * Outputs:
+ * -------
+ *
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void PaneManagedChildren (menuMgr, menupane)
+
+ register XwPopupMgrWidget menuMgr;
+ register XwMenuPaneWidget menupane;
+
+{
+ register Widget child;
+ Boolean * wasManaged;
+ Arg args[2];
+ unsigned int event;
+ unsigned int tempKeySym;
+ unsigned int modifiers;
+ KeyCode key;
+ register int i;
+ Boolean parentOnCascadeList;
+ String dkey;
+ Widget dtree;
+
+
+ if (CompletePath (menuMgr, menupane))
+ {
+ /*
+ * If the parent menupane is in the sticky menu list, then we
+ * need to remember this, so that we can check if any of its
+ * children which are now being unmanaged are cascading to
+ * another entry in the sticky menu list. We will then clean
+ * up the list, if necessary.
+ */
+ parentOnCascadeList = OnCascadeList (menuMgr, menupane);
+
+ for (i=0; i < menupane->composite.num_children; i++)
+ {
+ child = menupane->composite.children[i];
+ wasManaged = (Boolean *) child->core.constraints;
+
+ if ((*wasManaged == FALSE) && (child->core.managed == TRUE))
+ {
+ dkey = NULL;
+ dtree = NULL;
+
+ /*
+ * child has gone from unmanaged to managed
+ */
+ *wasManaged = TRUE;
+ XtSetArg (args[0], XtNkbdAccelerator, (XtArgVal) &dkey);
+ XtSetArg (args[1], XtNcascadeOn, (XtArgVal) &dtree);
+ XtGetValues (child, args, XtNumber(args));
+
+ /*
+ * keyboard accelerator?
+ */
+ if (dkey)
+ {
+ _XwMapKeyEvent (dkey, &event, &tempKeySym, &modifiers);
+ key = XKeysymToKeycode (XtDisplay(menuMgr), tempKeySym);
+ SetSelectAccelerator (menuMgr, child, dkey,
+ event, key, modifiers);
+ }
+
+ /*
+ * Does this menubutton cascade?
+ */
+ if (dtree)
+ SetTreeAccelerators (menuMgr, dtree);
+ }
+ else if ((*wasManaged == TRUE) && (child->core.managed == FALSE))
+ {
+ dkey = NULL;
+ dtree = NULL;
+
+ /*
+ * child went from managed to unmanaged
+ */
+ *wasManaged = FALSE;
+ XtSetArg (args[0], XtNkbdAccelerator, (XtArgVal) &dkey);
+ XtSetArg (args[1], XtNcascadeOn, (XtArgVal) &dtree);
+ XtGetValues (child, args, XtNumber(args));
+
+ /*
+ * accelerator to clear out?
+ */
+ if (dkey)
+ ClearSelectAccelerator (menuMgr, child);
+
+ /*
+ * Does this menubutton cascade?
+ */
+ if (dtree)
+ {
+ ClearTreeAccelerators (menuMgr, dtree);
+ if (Visible (menuMgr, dtree))
+ Unpost (menuMgr, dtree);
+
+ /*
+ * If this button cascaded to a menupane which was on
+ * the saved cascade list, then we need to clean up the
+ * saved cascade list.
+ */
+ if (parentOnCascadeList && OnCascadeList(menuMgr, dtree))
+ {
+ parentOnCascadeList = False;
+ menuMgr->popup_mgr.numSavedCascades = 0;
+ }
+ }
+
+ /*
+ * If this button was the last selected item on the saved
+ * cascade list, then we need to clean up the list.
+ */
+ if (parentOnCascadeList &&
+ (child == menuMgr->popup_mgr.lastSelected))
+ {
+ parentOnCascadeList = False;
+ menuMgr->popup_mgr.numSavedCascades = 0;
+ }
+ }
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * Visible
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static Boolean Visible (menuMgr, menupane)
+
+ XwPopupMgrWidget menuMgr;
+ Widget menupane;
+
+{
+ register int i;
+ register Widget * currentCascadeList =menuMgr->popup_mgr.currentCascadeList;
+
+ for (i=0; i < menuMgr->popup_mgr.numCascades; i++)
+ if (currentCascadeList[i] == menupane)
+ return (TRUE);
+
+ return (FALSE);
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetMenuTranslations
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetMenuTranslations (menuMgr, translation)
+
+ XwPopupMgrWidget menuMgr;
+ XtTranslations translation;
+
+{
+ register int i, j, k;
+ register CompositeWidget shell;
+ register XwMenuPaneWidget menupane;
+
+ /*
+ * Since the menupanes are our popup grand children, we
+ * will process them simply by traversing our popup children list.
+ */
+ for (i = 0; i < menuMgr->core.num_popups; i++)
+ {
+ shell = (CompositeWidget) menuMgr->core.popup_list[i];
+
+ for (j = 0; j < shell->composite.num_children; j++)
+ {
+ /* Here we set the translation for the menupanes */
+ menupane = (XwMenuPaneWidget)shell->composite.children[j];
+ XtOverrideTranslations ((Widget)menupane, translation);
+
+ for (k = 0; k < menupane->manager.num_managed_children; k++)
+ {
+ /* Here we set the translation for the menubuttons */
+ XtOverrideTranslations(menupane->manager.managed_children[k],
+ translation);
+ }
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseRight(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseRight (menuMgr, w)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+ XwMenuPaneWidget menupane;
+ Arg arg[1];
+
+ if ((menuMgr->manager.traversal_on) && (menuMgr->menu_mgr.menuActive) &&
+ (XtParent(w) == menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]))
+ {
+ /* Cascade to the menupane attached to the specified menubutton */
+ XtSetArg (arg[0], XtNcascadeOn, (XtArgVal) &menupane);
+ XtGetValues ((Widget)w, arg, XtNumber(arg));
+
+ /*
+ * Only cascade if there is a traversable primitive widget in
+ * the pane we would be cascading to.
+ */
+ if (_XwFindTraversablePrim (menupane) == FALSE)
+ return;
+
+ if (menupane)
+ _XwCascadeSelect (w, menupane, NULL);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseLeft(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseLeft (menuMgr, w)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+ /* Traverse to the previous menupane, if there is one */
+ if ((menuMgr->menu_mgr.menuActive) &&
+ (menuMgr->manager.traversal_on) &&
+ (menuMgr->popup_mgr.numCascades > 1) &&
+ (XtParent(w) == menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]))
+ {
+ /* Unpost() will set the traversal focus, if needed */
+ Unpost (menuMgr, menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseUp(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseUp (menuMgr, w)
+
+ register XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+ if ((menuMgr->manager.traversal_on) && (menuMgr->menu_mgr.menuActive) &&
+ (XtParent(w) == menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]))
+ {
+ XwProcessTraversal (w, XwTRAVERSE_UP, TRUE);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseDown(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseDown (menuMgr, w)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+ if ((menuMgr->manager.traversal_on) && (menuMgr->menu_mgr.menuActive) &&
+ (XtParent(w) == menuMgr->popup_mgr.currentCascadeList[
+ menuMgr->popup_mgr.numCascades - 1]))
+ {
+ XwProcessTraversal (w, XwTRAVERSE_DOWN, TRUE);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseNextTop(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseNextTop (menuMgr, w)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseNext(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseNext (menuMgr, w)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraversePrev(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraversePrev (menuMgr, w)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * TraverseHome(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void TraverseHome (menuMgr, w)
+
+ XwPopupMgrWidget menuMgr;
+ XwMenuButtonWidget w;
+
+{
+}
+
+
+/*************************************<->*************************************
+ *
+ * ManualPost(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void ManualPost (menuMgr, pane, relativeTo, x, y)
+
+ register XwPopupMgrWidget menuMgr;
+ register Widget pane;
+ Widget relativeTo;
+ Position x;
+ Position y;
+
+{
+ int introotx, introoty, intchildx, intchildy;
+ Position rootx, rooty;
+ Position childx, childy;
+ Widget assocWidget;
+ Window root, child;
+ unsigned int returnMask;
+
+ if (pane == (Widget)NULL)
+ pane = (Widget) menuMgr->popup_mgr.topLevelPane;
+
+ /* Get the widget Id for the associated widget */
+ assocWidget = XtParent (XtParent (menuMgr));
+
+ /*
+ * Do nothing if the menu is already active, there is no top level
+ * menupane, the menu manager is insensitive, or the associated
+ * widget is insensitive.
+ */
+ if ((menuMgr->menu_mgr.menuActive == TRUE) || (pane == NULL) ||
+ !XtIsSensitive((Widget)menuMgr) || !XtIsSensitive(assocWidget)) {
+ return;
+ }
+
+ /*
+ * Determine where to post the menu and translate coordinates,
+ * if necessary.
+ */
+ if (relativeTo)
+ {
+ /*
+ * If the coordinates are relative to a widget, then we need
+ * to map them relative to the root window.
+ */
+ /* XtTranslateCoords (relativeTo, x, y, &rootx, &rooty); */
+ XTranslateCoordinates (XtDisplay(relativeTo), XtWindow(relativeTo),
+ RootWindowOfScreen(XtScreen(menuMgr)),
+ x, y, &introotx, &introoty, &child);
+ rootx = introotx;
+ rooty = introoty;
+ }
+ else
+ {
+ /*
+ * If no widget is specified, then the coordinates are assumed
+ * to already be relative to the root window.
+ */
+ rootx = x;
+ rooty = y;
+ }
+
+ /*
+ * The following is a kludge fix to bypass a shortcoming within Xtk.
+ * We need to manually inform the previous focus widget that it has
+ * lost the cursor; this is because once we add our popups to the
+ * grablist, the LeaveNotify will be ignored for the focus widget,
+ * because it is not on the grablist.
+ */
+ /* if (menuMgr->manager.traversal_on) */
+ SendFakeLeaveNotify(menuMgr, ULTIMATE_PARENT);
+
+ /* Mark the menu system as active */
+ menuMgr->menu_mgr.menuActive = TRUE;
+
+ /* Position the menupane */
+ if (!XtIsRealized (XtParent(pane)))
+ XtRealizeWidget (XtParent(pane));
+ ForceMenuPaneOnScreen (pane, &rootx, &rooty);
+ XtMoveWidget (XtParent(pane), rootx, rooty);
+
+ /*
+ * Set up a pointer grab; this allows us to catch all selects and
+ * to then unpost the menus, regardless as to where the select
+ * occurred.
+ */
+ XGrabPointer (XtDisplay(menuMgr), XtWindow(assocWidget), TRUE,
+ ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|
+ PointerMotionMask, GrabModeAsync, GrabModeAsync, None, (Cursor)NULL,
+ CurrentTime);
+
+ /* Post the menupane */
+ Post (menuMgr, pane, XtGrabExclusive);
+
+ /*
+ * If traversal is on, then save the current mouse position,
+ * so that we can restore the mouse to its original position
+ * when the menu is unposted.
+ */
+ if (menuMgr->manager.traversal_on)
+ {
+ if (XQueryPointer(XtDisplay(menuMgr),
+ RootWindowOfScreen(menuMgr->core.screen),
+ &root, &child, &introotx, &introoty, &intchildx,
+ &intchildy, &returnMask))
+ {
+ menuMgr->popup_mgr.origMouseX = introotx;
+ menuMgr->popup_mgr.origMouseY = introoty;
+ }
+
+ /* Set the traversal focus to the pane */
+ XwMoveFocus (pane);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * XwPostPopup(parameters)
+ *
+ * Description:
+ * -----------
+ * This is a utility routine which may be used by an application to
+ * manually post a popup menu pane.
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+void XwPostPopup (menuMgr, pane, relativeTo, x, y)
+
+ Widget menuMgr, pane, relativeTo;
+ Position x, y;
+
+{
+ /* Only popup a menu if it is a subclass of the popup menu manager */
+ /* Do nothing if invalid menu manager Id */
+ if (menuMgr == NULL)
+ return;
+
+ if (XtIsSubclass (menuMgr, XwpopupmgrWidgetClass))
+ {
+ (*(((XwPopupMgrWidgetClass)
+ XtClass(menuMgr))-> popup_mgr_class.manualPost))
+ (menuMgr, pane, relativeTo, x, y);
+ }
+ else
+ {
+ XtWarning ("PopupMgr: Widget is not a subclass of menuMgr");
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * SendFakeLeaveNotify(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SendFakeLeaveNotify (focus_widget, mode)
+
+ Widget focus_widget;
+ int mode;
+
+{
+ XEvent event;
+
+ if (mode == ULTIMATE_PARENT)
+ {
+ /* Search up to top level shell */
+ while (XtParent(focus_widget) != NULL)
+ focus_widget = XtParent(focus_widget);
+ }
+ else
+ {
+ /* Search up to the shell in which this menubtn resides */
+ while ((!XtIsSubclass (focus_widget, shellWidgetClass)) &&
+ (XtParent(focus_widget) != NULL))
+ focus_widget = XtParent(focus_widget);
+ }
+
+ event.type = FocusOut;
+ event.xfocus.serial = LastKnownRequestProcessed(XtDisplay(focus_widget));
+ event.xfocus.send_event = True;
+ event.xfocus.display = XtDisplay(focus_widget);
+ event.xfocus.window = XtWindow(focus_widget);
+ event.xfocus.mode = NotifyNormal;
+ event.xfocus.detail = NotifyAncestor;
+
+ XtDispatchEvent (&event);
+}
+
+
+/*************************************<->*************************************
+ *
+ * SetUpStickyList(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void SetUpStickyList (menuMgr, widget)
+
+ XwPopupMgrWidget menuMgr;
+ Widget widget;
+
+{
+ int i;
+
+ menuMgr->popup_mgr.numSavedCascades = 0;
+
+ if ((XtIsSubclass (widget, XwmenubuttonWidgetClass)) &&
+ (menuMgr->popup_mgr.stickyMode) &&
+ (XtParent(widget) == menuMgr->popup_mgr.currentCascadeList
+ [menuMgr->popup_mgr.numCascades -1]))
+ {
+ if (menuMgr->popup_mgr.numCascades >
+ menuMgr->popup_mgr.sizeSavedCascadeList)
+ {
+ menuMgr->popup_mgr.sizeSavedCascadeList =
+ menuMgr->popup_mgr.sizeCascadeList;
+ menuMgr->popup_mgr.savedCascadeList =
+ (Widget *) XtRealloc((char *)(menuMgr->popup_mgr.savedCascadeList),
+ menuMgr->popup_mgr.sizeSavedCascadeList *
+ sizeof (Widget));
+ }
+
+ menuMgr->popup_mgr.numSavedCascades = menuMgr->popup_mgr.numCascades;
+ menuMgr->popup_mgr.lastSelected = widget;
+
+ /* Set this widget as the traversal item */
+ if (menuMgr->manager.traversal_on)
+ {
+ XwMenuPaneWidget pane;
+
+ pane = ((XwMenuPaneWidget)(menuMgr->popup_mgr.currentCascadeList
+ [menuMgr->popup_mgr.numCascades -1]));
+ pane->manager.active_child = widget;
+ XtSetKeyboardFocus ((Widget)pane, widget);
+ }
+
+ for (i=0; i < menuMgr->popup_mgr.numSavedCascades; i++)
+ menuMgr->popup_mgr.savedCascadeList[i] =
+ menuMgr->popup_mgr.currentCascadeList[i];
+ }
+ else if (menuMgr->manager.traversal_on)
+ {
+ /* Force the first item to be highlighted next time */
+ ((XwPopupMgrWidget)menuMgr->popup_mgr.topLevelPane)->
+ manager.active_child = NULL;
+ XtSetKeyboardFocus (menuMgr->popup_mgr.topLevelPane, NULL);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * BtnSensitivityChanged(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void BtnSensitivityChanged (menuMgr, btn)
+
+ XwPopupMgrWidget menuMgr;
+ Widget btn;
+
+{
+ /* Noop */
+}
+
+
+/*************************************<->*************************************
+ *
+ * PaneSensitivityChanged(parameters)
+ *
+ * Description:
+ * -----------
+ * xxxxxxxxxxxxxxxxxxxxxxx
+ *
+ *
+ * Inputs:
+ * ------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Outputs:
+ * -------
+ * xxxxxxxxxxxx = xxxxxxxxxxxxx
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+
+static void PaneSensitivityChanged (menuMgr, pane)
+
+ XwPopupMgrWidget menuMgr;
+ Widget pane;
+
+{
+ /* Noop */
+}
diff --git a/Xw/PopupMgr.h b/Xw/PopupMgr.h
new file mode 100644
index 0000000..b0ed296
--- /dev/null
+++ b/Xw/PopupMgr.h
@@ -0,0 +1,45 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PopupMgr.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for popup menu manager class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Popup Menu Manager Widget (subclass of MenuMgr)
+ *
+ ***********************************************************************/
+
+
+/* Class record constants */
+
+extern WidgetClass XwpopupmgrWidgetClass;
+/* synonym added for consistent naming conventions */
+extern WidgetClass XwpopupMgrWidgetClass;
+
+typedef struct _XwPopupMgrClassRec *XwPopupMgrWidgetClass;
+typedef struct _XwPopupMgrRec *XwPopupMgrWidget;
+
+extern void XwAppInitialize(XtAppContext);
+extern void XwPostPopup(Widget, Widget, Widget, Position, Position);
diff --git a/Xw/PopupMgrP.h b/Xw/PopupMgrP.h
new file mode 100644
index 0000000..a904134
--- /dev/null
+++ b/Xw/PopupMgrP.h
@@ -0,0 +1,99 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: PopupMgrP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for Popup Menu Manager class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Popup Menu Manager Widget Private Data
+ *
+ ***********************************************************************/
+
+/* New fields for the PopupMgr widget class record */
+typedef struct {
+ XwPostProc manualPost;
+} XwPopupMgrClassPart;
+
+/* Full class record declaration */
+typedef struct _XwPopupMgrClassRec {
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwMenuMgrClassPart menu_mgr_class;
+ XwPopupMgrClassPart popup_mgr_class;
+} XwPopupMgrClassRec;
+
+extern XwPopupMgrClassRec XwpopupmgrClassRec;
+
+/* New fields for the PopupMgr widget record */
+typedef struct {
+ /* Internal fields */
+ unsigned int accelEventType;
+ KeyCode accelKey;
+ unsigned int accelModifiers;
+ Widget topLevelPane;
+ Widget lastSelected;
+ Widget * savedCascadeList;
+ int numSavedCascades;
+ int sizeSavedCascadeList;
+ Widget * currentCascadeList;
+ int numCascades;
+ int sizeCascadeList;
+ XwMenuPaneWidget attachPane;
+ XwMenuPaneWidget detachPane;
+ Position origMouseX;
+ Position origMouseY;
+
+ /* User settable fields */
+ Boolean stickyMode;
+ String postAccelerator;
+} XwPopupMgrPart;
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwPopupMgrRec {
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwMenuMgrPart menu_mgr;
+ XwPopupMgrPart popup_mgr;
+} XwPopupMgrRec;
+
+
+#define XtInheritPopupTravLeft ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravRight ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravUp ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravDown ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravNext ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravPrev ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravHome ((XwEventProc) _XtInherit)
+#define XtInheritPopupTravNextTop ((XwEventProc) _XtInherit)
diff --git a/Xw/Primitive.c b/Xw/Primitive.c
new file mode 100644
index 0000000..89a8b2c
--- /dev/null
+++ b/Xw/Primitive.c
@@ -0,0 +1,1146 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Primitive.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: This file contains source for the Primitive Meta Widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/MenuBtn.h>
+#include <X11/StringDefs.h>
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: default translation table for class: Primitive.
+ * -----------
+ *
+ * These translations will be compiled at class initialize. When
+ * a subclass of primitive is created then these translations will
+ * be used to augment the translations of the subclass IFF
+ * traversal is on. The SetValues routine will also augment
+ * a subclass's translations table IFF traversal goes from off to on.
+ * Since we are augmenting it should not be a problem when
+ * traversal goes from off to on to off and on again.
+ *
+ *************************************<->***********************************/
+
+static char defaultTranslations[] =
+ "<FocusIn>: focusIn() \n\
+ <FocusOut>: focusOut() \n\
+ <Visible>: visibility() \n\
+ <Unmap>: unmap()";
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: action list for class: Primtive
+ * -----------
+ * Used to provide actions for subclasses with traversal on.
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ {"focusIn", (XtActionProc) _XwPrimitiveFocusIn},
+ {"focusOut", (XtActionProc) _XwPrimitiveFocusOut},
+ {"visibility", (XtActionProc) _XwPrimitiveVisibility},
+ {"unmap", (XtActionProc) _XwPrimitiveUnmap},
+};
+
+
+/* Resource definitions for Subclasses of Primitive */
+
+static Cursor defaultCursor = None;
+
+static XtResource resources[] =
+{
+ {
+ XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
+ XtOffset (XwPrimitiveWidget, primitive.foreground),
+ XtRString, "XtDefaultForeground"
+ },
+
+ {
+ XtNbackgroundTile, XtCBackgroundTile, XtRTileType, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.background_tile),
+ XtRString, "background"
+ },
+
+ {
+ XtNcursor, XtCCursor, XtRCursor, sizeof (Cursor),
+ XtOffset (XwPrimitiveWidget, primitive.cursor),
+ XtRCursor, (caddr_t) &defaultCursor
+ },
+
+ {
+ XtNtraversalType, XtCTraversalType, XtRTraversalType, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.traversal_type),
+ XtRString, "highlight_off"
+ },
+
+ {
+ XtNhighlightThickness, XtCHighlightThickness, XtRInt, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.highlight_thickness),
+ XtRString, "0"
+ },
+
+ {
+ XtNhighlightStyle, XtCHighlightStyle, XtRHighlightStyle, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.highlight_style),
+ XtRString, "pattern_border"
+ },
+
+ {
+ XtNhighlightColor, XtCForeground, XtRPixel, sizeof (Pixel),
+ XtOffset (XwPrimitiveWidget, primitive.highlight_color),
+ XtRString, "Black"
+ },
+
+ {
+ XtNhighlightTile, XtCHighlightTile, XtRTileType, sizeof (int),
+ XtOffset (XwPrimitiveWidget, primitive.highlight_tile),
+ XtRString, "foreground"
+ },
+
+ {
+ XtNrecomputeSize, XtCRecomputeSize, XtRBoolean, sizeof(Boolean),
+ XtOffset (XwPrimitiveWidget, primitive.recompute_size),
+ XtRString, "True"
+ },
+
+ {
+ XtNselect, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset (XwPrimitiveWidget, primitive.select),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNrelease, XtCCallback, XtRCallback, sizeof(caddr_t),
+ XtOffset (XwPrimitiveWidget, primitive.release),
+ XtRPointer, (caddr_t) NULL
+ },
+};
+
+
+
+/* Routine definiton used for initializing the class record. */
+
+static void ClassInitialize();
+static void ClassPartInitialize();
+static void Initialize();
+static void Realize();
+static void Destroy();
+static Boolean SetValues();
+
+static void GetHighlightGC();
+
+
+
+/* The primitive class record definition */
+
+XwPrimitiveClassRec XwprimitiveClassRec =
+{
+ {
+ (WidgetClass) &widgetClassRec, /* superclass */
+ "XwPrimitive", /* class_name */
+ sizeof(XwPrimitiveRec), /* widget_size */
+ (XtProc) ClassInitialize, /* class_initialize */
+ (XtWidgetClassProc) ClassPartInitialize, /* class_part_initialize */
+ FALSE, /* class_inited */
+ (XtInitProc) Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ (XtRealizeProc) Realize, /* realize */
+ actionsList, /* actions */
+ XtNumber(actionsList), /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ TRUE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ (XtWidgetProc) Destroy, /* destroy */
+ NULL, /* resize */
+ NULL, /* expose */
+ (XtSetValuesFunc) SetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback private */
+ NULL, /* tm_table */
+ NULL, /* query_geometry */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+
+ {
+ NULL, /* Primitive border_highlight */
+ NULL, /* Primitive border_unhighlight */
+ NULL, /* Primitive select_proc */
+ NULL, /* Primitive release_proc */
+ NULL, /* Primitive toggle_proc */
+ NULL, /* default translations */
+ }
+};
+
+WidgetClass XwprimitiveWidgetClass = (WidgetClass) &XwprimitiveClassRec;
+
+
+
+/************************************************************************
+ *
+ * ClassInitialize
+ * Initialize the primitive class structure. This is called only
+ * the first time a primitive widget is created. It registers the
+ * resource type converters unique to this class.
+ *
+ *
+ * After class init, the "translations" variable will contain the compiled
+ * translations to be used to augment a widget's translation
+ * table if they wish to have keyboard traversal on.
+ *
+ ************************************************************************/
+
+static void ClassInitialize()
+{
+ XwRegisterConverters();
+ XwprimitiveClassRec.primitive_class.translations =
+ XtParseTranslationTable(defaultTranslations);
+}
+
+
+
+
+/************************************************************************
+ *
+ * ClassPartInitialize
+ * Set up the inheritance mechanism for the routines exported by
+ * primitives class part.
+ *
+ ************************************************************************/
+
+static void ClassPartInitialize (w)
+WidgetClass w;
+
+{
+ register XwPrimitiveWidgetClass wc = (XwPrimitiveWidgetClass) w;
+ register XwPrimitiveWidgetClass super =
+ (XwPrimitiveWidgetClass) wc->core_class.superclass;
+
+ if (wc -> primitive_class.border_highlight == XtInheritBorderHighlight)
+ wc -> primitive_class.border_highlight =
+ super -> primitive_class.border_highlight;
+
+ if (wc->primitive_class.border_unhighlight == XtInheritBorderUnhighlight)
+ wc -> primitive_class.border_unhighlight =
+ super -> primitive_class.border_unhighlight;
+
+ if (wc -> primitive_class.select_proc == XtInheritSelectProc)
+ wc -> primitive_class.select_proc =
+ super -> primitive_class.select_proc;
+
+ if (wc -> primitive_class.release_proc == XtInheritReleaseProc)
+ wc -> primitive_class.release_proc =
+ super -> primitive_class.release_proc;
+
+ if (wc -> primitive_class.toggle_proc == XtInheritToggleProc)
+ wc -> primitive_class.toggle_proc =
+ super -> primitive_class.toggle_proc;
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * GetHighlightGC
+ * Get the graphics context used for drawing the border.
+ *
+ ************************************************************************/
+
+static void GetHighlightGC (pw)
+XwPrimitiveWidget pw;
+
+{
+ XGCValues values;
+ XtGCMask valueMask;
+
+ valueMask = GCForeground | GCBackground;
+ values.foreground = pw -> primitive.highlight_color;
+ values.background = pw -> core.background_pixel;
+
+ if (pw -> primitive.highlight_tile == XwBACKGROUND)
+ {
+ values.foreground = pw -> core.background_pixel;
+ values.background = pw -> primitive.highlight_color;
+ }
+
+ pw -> primitive.highlight_GC = XtGetGC ((Widget) pw, valueMask, &values);
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * Initialize
+ * The main widget instance initialization routine.
+ *
+ ************************************************************************/
+
+static void Initialize (request, new)
+XwPrimitiveWidget request, new;
+
+{
+ XwPrimitiveWidget pw = (XwPrimitiveWidget) new;
+ Arg args[1];
+
+
+ /* initialize traversal flag */
+
+ pw->primitive.I_have_traversal = FALSE;
+
+
+ /* Check the pw widget for invalid data */
+
+ if (pw -> primitive.traversal_type != XwHIGHLIGHT_OFF &&
+ pw -> primitive.traversal_type != XwHIGHLIGHT_ENTER &&
+ pw -> primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
+ {
+ XtWarning ("Primitive: Incorrect traversal type");
+ pw -> primitive.traversal_type = XwHIGHLIGHT_OFF;
+ }
+
+ if (pw -> primitive.highlight_style != XwPATTERN_BORDER &&
+ pw -> primitive.highlight_style != XwWIDGET_DEFINED)
+ {
+ XtWarning("Primitive: Incorrect highlight style.");
+ pw -> primitive.highlight_style = XwPATTERN_BORDER;
+ }
+
+ if (pw -> primitive.highlight_tile != XwFOREGROUND)
+ {
+ XtWarning("Primitive: Incorrect highlight tile.");
+ pw -> primitive.highlight_tile = XwFOREGROUND;
+ }
+
+ if (pw -> primitive.highlight_thickness < 0)
+ {
+ XtWarning("Primitive: Invalid highlight thickness.");
+ pw -> primitive.highlight_thickness = 0;
+ }
+
+ if (pw -> primitive.background_tile != XwBACKGROUND)
+ {
+ XtWarning("Primitive: Incorrect background tile.");
+ pw -> primitive.background_tile = XwBACKGROUND;
+ }
+
+
+ /* Check the geometry information for the widget */
+
+ if (request -> core.width == 0)
+ pw -> core.width += pw -> primitive.highlight_thickness * 2;
+ else if (request -> core.width < pw -> primitive.highlight_thickness * 2)
+ {
+ pw -> primitive.highlight_thickness = request -> core.width / 2;
+ }
+
+ if (request -> core.height == 0)
+ pw -> core.height += pw -> primitive.highlight_thickness * 2;
+ else if (request -> core.height < pw -> primitive.highlight_thickness * 2)
+ {
+ pw -> primitive.highlight_thickness = request -> core.height / 2;
+ }
+
+
+ /* Get the graphics contexts for the border drawing */
+
+ GetHighlightGC (pw);
+
+ /* Set some additional fields of the widget */
+
+ pw -> primitive.display_sensitive = FALSE;
+ pw -> primitive.highlighted = FALSE;
+ pw -> primitive.display_highlighted = FALSE;
+
+ /* If this widget is requesting traversal then augment its
+ * translation table with some additional events.
+ */
+ if (pw->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
+ {
+ XtAugmentTranslations((Widget) pw,
+ XwprimitiveClassRec.primitive_class.translations);
+ pw->core.widget_class->core_class.visible_interest = True;
+ }
+
+}
+
+
+
+/************************************************************************
+ *
+ * Realize
+ *
+ ************************************************************************/
+
+static void Realize (widget, value_mask, attributes)
+ Widget widget;
+ Mask *value_mask;
+ XSetWindowAttributes *attributes;
+{
+ XwPrimitiveWidget pw = (XwPrimitiveWidget) widget;
+
+ if (pw -> primitive.cursor != None) *value_mask |= CWCursor;
+
+ attributes->cursor = pw->primitive.cursor;
+
+ XtCreateWindow(widget, (unsigned int) InputOutput,
+ (Visual *) CopyFromParent, *value_mask, attributes);
+}
+
+
+/************************************************************************
+ *
+ * Destroy
+ * Clean up allocated resources when the widget is destroyed.
+ *
+ ************************************************************************/
+
+static void Destroy (pw)
+XwPrimitiveWidget pw;
+{
+ XwManagerWidget parent;
+
+ XtRemoveCallbacks ((Widget)pw, XtNselect, pw -> primitive.select);
+ XtRemoveCallbacks ((Widget)pw, XtNrelease, pw -> primitive.release);
+ if (pw->primitive.I_have_traversal)
+ XwProcessTraversal (pw, XwTRAVERSE_HOME, TRUE);
+ else if ((XtIsSubclass((Widget)(parent = (XwManagerWidget)XtParent(pw)),
+ XwmanagerWidgetClass)) &&
+ (parent->manager.traversal_on) &&
+ (parent->manager.active_child == (Widget)pw))
+ {
+ parent->manager.active_child = NULL;
+
+ /* Find the top most manager */
+ while ((parent->core.parent != NULL) &&
+ (XtIsSubclass(parent->core.parent, XwmanagerWidgetClass)))
+ parent = (XwManagerWidget)parent->core.parent;
+
+ /* Clear the toolkit kbd focus from us */
+ XtSetKeyboardFocus((Widget)parent, NULL);
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * SetValues
+ * Perform and updating necessary for a set values call.
+ *
+ ************************************************************************/
+
+static Boolean SetValues (current, request, new)
+Widget current, request, new;
+
+{
+ Boolean tempSensitive, tempAnSensitive;
+ int tempTrav;
+
+ XwPrimitiveWidget curpw = (XwPrimitiveWidget) current;
+ XwPrimitiveWidget reqpw = (XwPrimitiveWidget) request;
+ XwPrimitiveWidget newpw = (XwPrimitiveWidget) new;
+ Boolean returnFlag = FALSE;
+ int difference;
+
+
+ /* Verify correct new values. */
+
+ if (newpw->primitive.traversal_type != XwHIGHLIGHT_OFF &&
+ newpw->primitive.traversal_type != XwHIGHLIGHT_ENTER &&
+ newpw->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
+ {
+ XtWarning("Primitive: Incorrect traversal type.");
+ newpw->primitive.traversal_type = curpw->primitive.traversal_type;
+ }
+
+
+ /* If traversal has been turned on, then augment the translations */
+ /* of the new widget. */
+
+ if ((newpw->primitive.traversal_type != curpw->primitive.traversal_type)
+ && (newpw->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL))
+ {
+ /* XXX this was a hard bug! where were the XXX's?
+ *
+ * In R2 we could not pass newpw to this toolkit call! But I
+ * have found the bug!!!! In R2 it was a temporary structure (stack)
+ * but now curmw is the temporary one and newpw is real!
+ * I can see why they were worried before. Now there is no worry.
+ * Go ahead and pass newpw!
+ */
+ XtAugmentTranslations((Widget) newpw,
+ XwprimitiveClassRec.primitive_class.translations);
+ newpw->core.widget_class->core_class.visible_interest = True;
+ }
+
+
+ /* IF we have the traversal and something is happening to
+ * make that not possible then move it somewhere else!
+ */
+
+ if (((curpw->core.sensitive != newpw->core.sensitive) ||
+ (curpw->core.ancestor_sensitive != newpw->core.ancestor_sensitive) ||
+ (newpw->primitive.traversal_type != curpw->primitive.traversal_type))
+ && (curpw->primitive.I_have_traversal))
+ {
+ newpw->primitive.highlighted = FALSE;
+
+ tempTrav= curpw->primitive.traversal_type;
+ tempSensitive = curpw->core.sensitive;
+ tempAnSensitive = curpw->core.ancestor_sensitive;
+
+ curpw->primitive.traversal_type = newpw->primitive.traversal_type;
+ curpw->core.ancestor_sensitive = newpw->core.ancestor_sensitive;
+ curpw->core.sensitive = newpw->core.sensitive;
+
+ XwProcessTraversal (curpw, XwTRAVERSE_HOME, FALSE);
+
+ curpw->primitive.traversal_type = tempTrav;
+ curpw->core.sensitive = tempSensitive;
+ curpw->core.ancestor_sensitive = tempAnSensitive;
+
+ returnFlag = TRUE;
+ }
+
+
+ if (newpw->primitive.highlight_style != XwPATTERN_BORDER &&
+ newpw->primitive.highlight_style != XwWIDGET_DEFINED)
+ {
+ XtWarning ("Primitive: Incorrect highlight style.");
+ newpw->primitive.highlight_style = curpw->primitive.highlight_style;
+ }
+
+ if (newpw -> primitive.highlight_tile != XwFOREGROUND)
+ {
+ XtWarning ("Primitive: Incorrect highlight tile.");
+ newpw->primitive.highlight_tile = curpw->primitive.highlight_tile;
+ }
+
+ if (newpw->primitive.highlight_thickness < 0)
+ {
+ XtWarning ("Primtive: Invalid highlight thickness.");
+ newpw -> primitive.highlight_thickness =
+ curpw -> primitive.highlight_thickness;
+ }
+
+
+ if (newpw -> primitive.background_tile != XwBACKGROUND)
+ {
+ XtWarning("Primitive: Incorrect background tile.");
+ newpw -> primitive.background_tile =
+ curpw -> primitive.background_tile;
+ }
+
+
+ /* Set the widgets background tile */
+
+ if (newpw -> primitive.background_tile !=
+ curpw -> primitive.background_tile ||
+ newpw -> primitive.foreground !=
+ curpw -> primitive.foreground ||
+ newpw -> core.background_pixel !=
+ curpw -> core.background_pixel)
+ {
+ Mask valueMask;
+ XSetWindowAttributes attributes;
+
+ if (newpw -> primitive.background_tile == XwFOREGROUND)
+ {
+ valueMask = CWBackPixel;
+ attributes.background_pixel = newpw -> primitive.foreground;
+ }
+ else
+ {
+ valueMask = CWBackPixel;
+ attributes.background_pixel = newpw -> core.background_pixel;
+ }
+
+ if (XtIsRealized ((Widget)newpw))
+ XChangeWindowAttributes (XtDisplay(newpw), newpw -> core.window,
+ valueMask, &attributes);
+
+ returnFlag = TRUE;
+ }
+
+ if (newpw -> primitive.cursor != curpw -> primitive.cursor) {
+ Mask valueMask = 0;
+ XSetWindowAttributes attributes;
+
+ if (newpw->primitive.cursor != None) valueMask = CWCursor;
+ attributes.cursor = newpw->primitive.cursor;
+
+ if (XtIsRealized ((Widget)newpw))
+ XChangeWindowAttributes (XtDisplay(newpw), newpw -> core.window,
+ valueMask, &attributes);
+
+ returnFlag = TRUE;
+ }
+
+ /* Check the geometry in relationship to the highlight thickness */
+
+ if (reqpw -> core.width == 0)
+ if (curpw -> core.width == 0)
+ newpw -> core.width += newpw -> primitive.highlight_thickness * 2;
+ else if (reqpw -> core.width < newpw -> primitive.highlight_thickness * 2)
+ {
+ newpw -> primitive.highlight_thickness = reqpw -> core.width / 2;
+ }
+
+ if (reqpw -> core.height == 0)
+ if (curpw -> core.height == 0)
+ newpw -> core.height += newpw -> primitive.highlight_thickness * 2;
+ else if (reqpw -> core.height < newpw -> primitive.highlight_thickness * 2)
+ {
+ XtWarning("Primitive: The highlight thickness is too large.");
+ newpw -> primitive.highlight_thickness = reqpw -> core.height / 2;
+ }
+
+
+ /* If the highlight color, traversal type, highlight tile or highlight */
+ /* thickness has changed, regenerate the GC's. */
+
+ if (curpw->primitive.highlight_color != newpw->primitive.highlight_color ||
+ curpw->primitive.highlight_thickness !=
+ newpw->primitive.highlight_thickness ||
+ curpw->primitive.highlight_style != newpw->primitive.highlight_style ||
+ curpw->primitive.highlight_tile != newpw->primitive.highlight_tile)
+ {
+ XtDestroyGC (newpw -> primitive.highlight_GC);
+
+ GetHighlightGC (newpw);
+
+ returnFlag = TRUE;
+ }
+
+
+ /* Return a flag which may indicate that a redraw needs to occur. */
+
+ return (returnFlag);
+}
+
+
+
+/************************************************************************
+ *
+ * The traversal event processing routines.
+ * The following set of routines are the entry points invoked from
+ * each primitive widget when one of the traversal event conditions
+ * occur. These routines are externed in Xw.h.
+ *
+ ************************************************************************/
+
+void _XwTraverseLeft (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_LEFT, TRUE);
+}
+
+
+void _XwTraverseRight (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_RIGHT, TRUE);
+}
+
+
+void _XwTraverseUp (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_UP, TRUE);
+}
+
+
+void _XwTraverseDown (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_DOWN, TRUE);
+}
+
+
+void _XwTraverseNext (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_NEXT, TRUE);
+}
+
+
+void _XwTraversePrev (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_PREV, TRUE);
+}
+
+
+void _XwTraverseHome (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_HOME, TRUE);
+}
+
+
+void _XwTraverseNextTop (w, event)
+Widget w;
+XEvent * event;
+
+{
+ XwProcessTraversal (w, XwTRAVERSE_NEXT_TOP, TRUE);
+}
+
+
+
+/************************************************************************
+ *
+ * XwProcessTraversal
+ * This function handles all of the directional traversal conditions.
+ * It first verifies that traversal is active, and then searches up
+ * the widget hierarchy until a composite widget class is found.
+ * If this widget also contains a ManagerWidgetClass, it invokes
+ * the class's traversal handler giving the widget and direction.
+ * If not a ManagerWidgetClass, it invokes the composits
+ * move_focus_to_next or move_focus_to_prev functions for directions
+ * of TRAVERSE_NEXT and TRAVERSE_PREV respectively.
+ *
+ ************************************************************************/
+
+void XwProcessTraversal (w, dir, check)
+Widget w;
+int dir;
+Boolean check;
+
+{
+ Widget tw;
+ XPoint ul, lr;
+ XwPrimitiveWidget pw = (XwPrimitiveWidget) w;
+
+ if (check && (pw -> primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL))
+ return;
+
+ /* Initialize the traversal checklist */
+ _XwInitCheckList();
+
+ tw = w -> core.parent;
+
+ ul.x = w -> core.x;
+ ul.y = w -> core.y;
+ lr.x = ul.x + w->core.width - 1;
+ lr.y = ul.y + w->core.height - 1;
+
+ if (XtIsSubclass (tw, XwmanagerWidgetClass))
+ {
+ (*(((XwManagerWidgetClass) (tw -> core.widget_class)) ->
+ manager_class.traversal_handler))
+ (tw, ul, lr, dir);
+ }
+/* *** R3
+ else if (dir == XwTRAVERSE_NEXT &&
+ ((CompositeWidgetClass)(tw -> core.widget_class)) ->
+ composite_class.move_focus_to_next != NULL)
+ {
+ (*(((CompositeWidgetClass) tw -> core.widget_class) ->
+ composite_class.move_focus_to_next))(w);
+ }
+
+ else if (dir == XwTRAVERSE_PREV &&
+ ((CompositeWidgetClass)(tw -> core.widget_class)) ->
+ composite_class.move_focus_to_prev != NULL)
+ {
+ (*(((CompositeWidgetClass) tw -> core.widget_class) ->
+ composite_class.move_focus_to_prev))(w);
+ }
+ *** R3 */
+}
+
+
+
+/************************************************************************
+ *
+ * The border highlighting and unhighlighting routines.
+ *
+ * These routines are called through primitive widget translations and
+ * by primitive widget redisplay routines. They provide for the border
+ * drawing for active and inactive cases.
+ *
+ ************************************************************************/
+
+void _XwHighlightBorder (pw)
+XwPrimitiveWidget pw;
+
+{
+ if ((pw -> primitive.highlight_thickness == 0
+ ) && (!XtIsSubclass ((Widget)pw, XwmenubuttonWidgetClass)))
+ return;
+
+ pw -> primitive.highlighted = TRUE;
+ pw -> primitive.display_highlighted = TRUE;
+
+ switch (pw -> primitive.highlight_style)
+ {
+
+ case XwWIDGET_DEFINED:
+ {
+ if (((XwPrimitiveWidgetClass) (pw -> core.widget_class)) ->
+ primitive_class.border_highlight != NULL)
+ (*(((XwPrimitiveWidgetClass) (pw -> core.widget_class)) ->
+ primitive_class.border_highlight))((Widget)pw);
+ }
+ break;
+
+ case XwPATTERN_BORDER:
+ {
+ XRectangle rect[4];
+ int windowWidth = pw -> core.width;
+ int windowHeight = pw -> core.height;
+ int highlightWidth = pw -> primitive.highlight_thickness;
+
+ rect[0].x = 0;
+ rect[0].y = 0;
+ rect[0].width = windowWidth;
+ rect[0].height = highlightWidth;
+
+ rect[1].x = 0;
+ rect[1].y = 0;
+ rect[1].width = highlightWidth;
+ rect[1].height = windowHeight;
+
+ rect[2].x = windowWidth - highlightWidth;
+ rect[2].y = 0;
+ rect[2].width = highlightWidth;
+ rect[2].height = windowHeight;
+
+ rect[3].x = 0;
+ rect[3].y = windowHeight - highlightWidth;
+ rect[3].width = windowWidth;
+ rect[3].height = highlightWidth;
+
+ XFillRectangles (XtDisplay (pw), XtWindow (pw),
+ pw -> primitive.highlight_GC, &rect[0], 4);
+ }
+ break;
+ }
+}
+
+
+
+
+void _XwUnhighlightBorder (pw)
+XwPrimitiveWidget pw;
+
+{
+ if ((pw -> primitive.highlight_thickness == 0
+ ) && (!XtIsSubclass ((Widget)pw, XwmenubuttonWidgetClass)))
+ return;
+
+
+ pw -> primitive.highlighted = FALSE;
+ pw -> primitive.display_highlighted = FALSE;
+
+ switch (pw -> primitive.highlight_style)
+ {
+ case XwWIDGET_DEFINED:
+ {
+ if (((XwPrimitiveWidgetClass) (pw -> core.widget_class)) ->
+ primitive_class.border_unhighlight != NULL)
+ (*(((XwPrimitiveWidgetClass) (pw -> core.widget_class)) ->
+ primitive_class.border_unhighlight))((Widget)pw);
+ }
+ break;
+
+
+ case XwPATTERN_BORDER:
+ {
+ int windowWidth = pw -> core.width;
+ int windowHeight = pw -> core.height;
+ int highlightWidth = pw -> primitive.highlight_thickness;
+
+
+ XClearArea (XtDisplay (pw), XtWindow (pw),
+ 0, 0, windowWidth, highlightWidth, False);
+
+ XClearArea (XtDisplay (pw), XtWindow (pw),
+ 0, 0, highlightWidth, windowHeight, False);
+
+ XClearArea (XtDisplay (pw), XtWindow (pw),
+ windowWidth - highlightWidth, 0,
+ highlightWidth, windowHeight, False);
+
+ XClearArea (XtDisplay (pw), XtWindow (pw),
+ 0, windowHeight - highlightWidth,
+ windowWidth, highlightWidth, False);
+ }
+ break;
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * Enter & Leave
+ * Enter and leave event processing routines. Handle border
+ * highlighting and dehighlighting.
+ *
+ ************************************************************************/
+
+void _XwPrimitiveEnter (pw, event)
+XwPrimitiveWidget pw;
+XEvent * event;
+
+{
+ if (pw -> primitive.traversal_type == XwHIGHLIGHT_ENTER)
+ _XwHighlightBorder (pw);
+}
+
+
+void _XwPrimitiveLeave (pw, event)
+XwPrimitiveWidget pw;
+XEvent * event;
+
+{
+ if (pw -> primitive.traversal_type == XwHIGHLIGHT_ENTER)
+ _XwUnhighlightBorder (pw);
+}
+
+
+/************************************************************************
+ *
+ * Visibility
+ * Track whether a widget is visible.
+ *
+ ***********************************************************************/
+void _XwPrimitiveVisibility (pw, event)
+ XwPrimitiveWidget pw;
+ XEvent * event;
+{
+ XVisibilityEvent * vEvent = (XVisibilityEvent *)event;
+
+ if (vEvent->state == VisibilityFullyObscured)
+ {
+ pw->core.visible = False;
+ if (pw->primitive.I_have_traversal)
+ XwProcessTraversal (pw, XwTRAVERSE_HOME, FALSE);
+ }
+ else
+ pw->core.visible = True;
+
+
+}
+
+
+
+/************************************************************************
+ *
+ * Unmap
+ * Track whether a widget is visible.
+ *
+ ***********************************************************************/
+void _XwPrimitiveUnmap (pw, event)
+ XwPrimitiveWidget pw;
+ XEvent * event;
+{
+ pw->core.visible = False;
+ if (pw->primitive.I_have_traversal)
+ XwProcessTraversal (pw, XwTRAVERSE_HOME, FALSE);
+
+}
+
+/************************************************************************
+ *
+ * Focus In & Out
+ * Handle border highlighting and dehighlighting.
+ *
+ ************************************************************************/
+
+void _XwPrimitiveFocusIn (pw, event)
+XwPrimitiveWidget pw;
+XEvent * event;
+
+{
+ int widgetType;
+
+
+ /* SET THE FOCUS PATH DOWN TO THIS WIDGET. */
+
+ XwSetFocusPath((Widget)pw);
+
+
+ /* IF THE SPECIFIED WIDGET CANNOT BE TRAVERSED TO, THEN INVOKE */
+ /* MANAGER'S TRAVERSAL HANDLER WITH DIRECTION = HOME. */
+
+ if (! XwTestTraversability((Widget)pw, &widgetType))
+ XwProcessTraversal (pw, XwTRAVERSE_HOME, FALSE);
+ else
+ {
+ _XwHighlightBorder (pw);
+ pw->primitive.I_have_traversal = TRUE;
+ }
+}
+
+
+void _XwPrimitiveFocusOut (pw, event)
+XwPrimitiveWidget pw;
+XEvent * event;
+
+{
+ if (pw -> primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
+ {
+ _XwUnhighlightBorder (pw);
+ pw->primitive.I_have_traversal = FALSE;
+ }
+}
+
+
+void XwSetFocusPath(w)
+Widget w;
+
+{
+ XwManagerWidget mw;
+ Widget tempoldActive, oldActive;
+
+
+ /* IF THE PARENT OF THIS WIDGET IS NOT A MANAGER THEN THERE'S NO */
+ /* PATH TO SET, SO RETURN. */
+
+ if (! XtIsSubclass(w->core.parent, XwmanagerWidgetClass)) return;
+
+ mw = (XwManagerWidget)w->core.parent;
+
+
+ /* IF THIS WIDGET IS ALREADY THE ACTIVE CHID THEN THERE'S NOTHING */
+ /* TO DO. */
+
+ if (mw->manager.active_child == w) return;
+
+ oldActive = mw->manager.active_child;
+ mw->manager.active_child = w;
+ XwProcessTraversal (w, XwTRAVERSE_CURRENT, FALSE);
+
+
+ /* TRAVERSE DOWN THE OTHER BRANCH OF TREE TO CLEAN UP ACTIVE CHILD */
+ /* PATH. */
+
+ while (oldActive != NULL)
+ {
+ if (! XtIsSubclass(oldActive, XwmanagerWidgetClass))
+ oldActive = NULL;
+ else
+ {
+ tempoldActive = ((XwManagerWidget)oldActive)->manager.active_child;
+ ((XwManagerWidget)oldActive)->manager.active_child = NULL;
+ oldActive=tempoldActive;
+ }
+ }
+
+ XwSetFocusPath((Widget)mw);
+}
+
+
+
+
+
+
+/************************************************************************
+ *
+ * _XwDrawBox
+ * Draw the bordering on the drawable d, thick pixels wide,
+ * using the provided GC and rectangle.
+ *
+ ************************************************************************/
+
+void _XwDrawBox (display, d, normal_GC, thick, x, y, width, height)
+Display * display;
+Drawable d;
+GC normal_GC;
+register int thick;
+register int x;
+register int y;
+register int width;
+register int height;
+
+{
+ XRectangle rect[4];
+
+ rect[0].x = x; /* top */
+ rect[0].y = y;
+ rect[0].width = width;
+ rect[0].height = 2;
+
+ rect[1].x = x; /* left */
+ rect[1].y = y + 2;
+ rect[1].width = 2;
+ rect[1].height = height - 4;
+
+ rect[2].x = x; /* bottom */
+ rect[2].y = y + height - 2;
+ rect[2].width = width;
+ rect[2].height = 2;
+
+ rect[3].x = x + width - 2; /* Right two segments */
+ rect[3].y = y + 2;
+ rect[3].width = 2;
+ rect[3].height = height - 4;
+
+ XFillRectangles (display, d, normal_GC, &rect[0], 4);
+}
diff --git a/Xw/ResConvert.c b/Xw/ResConvert.c
new file mode 100644
index 0000000..d705c26
--- /dev/null
+++ b/Xw/ResConvert.c
@@ -0,0 +1,797 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: ResConvert.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains a function to register all of the resource
+ ** type converters used within Xw and the converter
+ ** routines.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/Xlib.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/TextEdit.h>
+#include <X11/StringDefs.h>
+
+
+static void _XwCvtStringToTraversalType ();
+static void _XwCvtStringToHighlightStyle ();
+static void _XwCvtStringToTileType();
+static void _XwCvtStringToLayoutPolicy();
+static void _XwCvtStringToLabelLocation();
+static Boolean StringsAreEqual();
+static void _XwCvtStringToAlignment();
+static void _XwCvtStringToWidgetType();
+static void _XwCvtStringToSelectionMethod();
+static void _XwCvtStringToSelectionStyle();
+static void _XwCvtStringToSelectionBias();
+static void _XwCvtStringToElementHighlight();
+static void _XwCvtStringToDestroyMode();
+static void _XwCvtStringToGravity ();
+static void _XwCvtStringToTitlePositionType();
+static void _XwCvtStringToLabelType();
+static void _XwCvtStringToTitleType();
+static void _XwCvtLongToLong();
+static void CvtStringToEditMode();
+static void CvtStringToSourceType();
+static void CvtStringToWrap();
+static void CvtStringToWrapBreak();
+static void CvtStringToWrapForm();
+static void CvtStringToScroll();
+static void CvtStringToGrow();
+
+typedef struct {
+ unsigned char *string;
+ int value;
+} XwSetValuePair;
+
+#define NUMVALUESETS 7
+#define XwEditTypeValueSetNum 0
+#define XwSourceTypeValueSetNum 1
+#define XwWrapValueSetNum 2
+#define XwWrapFormValueSetNum 3
+#define XwWrapBreakValueSetNum 4
+#define XwScrollValueSetNum 5
+#define XwGrowValueSetNum 6
+
+static XwSetValuePair XwEditTypeValueSet[] =
+ { {(unsigned char *)"edit", (int) XwtextEdit},
+ {(unsigned char *)"append", (int) XwtextAppend},
+ {(unsigned char *)"read", (int) XwtextRead},
+ NULL };
+static XwSetValuePair XwSourceTypeValueSet[] =
+ {{(unsigned char *)"stringsrc", (int) XwstringSrc},
+ {(unsigned char *)"disksrc", (int) XwdiskSrc},
+ {(unsigned char *)"userdefined", (int) XwprogDefinedSrc},
+ NULL };
+static XwSetValuePair XwWrapValueSet[] =
+ {{(unsigned char *)"wrapoff", (int) XwWrapOff},
+ {(unsigned char *)"softwrap", (int) XwSoftWrap},
+ {(unsigned char *)"hardwrap", (int) XwHardWrap},
+ NULL };
+static XwSetValuePair XwWrapFormValueSet[] =
+ {{(unsigned char *)"sourceform", (int) XwSourceForm},
+ {(unsigned char *)"displayform", (int) XwDisplayForm},
+ NULL };
+static XwSetValuePair XwWrapBreakValueSet[] =
+ {{(unsigned char *)"wrapany", (int) XwWrapAny},
+ {(unsigned char *)"wrapwhitespace", (int) XwWrapWhiteSpace},
+ NULL };
+static XwSetValuePair XwScrollValueSet[] =
+ {{(unsigned char *)"autoscrolloff", (int) XwAutoScrollOff},
+ {(unsigned char *)"autoscrollvertical", (int) XwAutoScrollVertical},
+ {(unsigned char *)"autoscrollhorizontal", (int) XwAutoScrollHorizontal},
+ {(unsigned char *)"autoscrollboth", (int) XwAutoScrollBoth},
+ NULL };
+static XwSetValuePair XwGrowValueSet[] =
+ {{(unsigned char *)"growoff", (int) XwGrowOff},
+ {(unsigned char *)"growhorizontal", (int) XwGrowHorizontal},
+ {(unsigned char *)"growvertical", (int) XwGrowVertical},
+ {(unsigned char *)"growboth", (int) XwGrowBoth},
+ NULL };
+
+static XwSetValuePair *valuepairsets[NUMVALUESETS];
+
+/************************************************************************
+ *
+ * XwRegisterConverters
+ * Register all of the Xw resource type converters. Retain a
+ * flag indicating whether the converters have already been
+ * registered.
+ *
+ ************************************************************************/
+
+XwRegisterConverters ()
+{
+ static Boolean registered = False;
+
+ if (!registered)
+ {
+ XtAddConverter (XtRString, XtRTraversalType,
+ _XwCvtStringToTraversalType, NULL, 0);
+ XtAddConverter (XtRString, XtRLayout,
+ _XwCvtStringToLayoutPolicy, NULL, 0);
+ XtAddConverter (XtRString, XtRHighlightStyle,
+ _XwCvtStringToHighlightStyle, NULL, 0);
+ XtAddConverter (XtRString, XtRTileType,
+ _XwCvtStringToTileType, NULL, 0);
+ XtAddConverter (XtRString, XtRLabelLocation,
+ _XwCvtStringToLabelLocation, NULL, 0);
+ XtAddConverter (XtRString, XtRAlignment,
+ _XwCvtStringToAlignment, NULL, 0);
+ XtAddConverter (XtRString, XtRWidgetType,
+ _XwCvtStringToWidgetType, NULL, 0);
+ XtAddConverter (XtRString, XtRGravity,
+ _XwCvtStringToGravity, NULL,0);
+ XtAddConverter (XtRString, XtRTitlePositionType,
+ _XwCvtStringToTitlePositionType, NULL, 0);
+ XtAddConverter (XtRString, XtRTitleType, _XwCvtStringToTitleType,
+ NULL, 0);
+ XtAddConverter (XtRString, XtRLabelType, _XwCvtStringToLabelType,
+ NULL, 0);
+ XtAddConverter (XtRLong, XtRLong, _XwCvtLongToLong, NULL, 0);
+
+ valuepairsets[XwEditTypeValueSetNum] = XwEditTypeValueSet;
+ valuepairsets[XwSourceTypeValueSetNum] = XwSourceTypeValueSet;
+ valuepairsets[XwWrapValueSetNum] = XwWrapValueSet;
+ valuepairsets[XwWrapFormValueSetNum] = XwWrapFormValueSet;
+ valuepairsets[XwWrapBreakValueSetNum] = XwWrapBreakValueSet;
+ valuepairsets[XwScrollValueSetNum] = XwScrollValueSet;
+ valuepairsets[XwGrowValueSetNum] = XwGrowValueSet;
+
+ XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0);
+ XtAddConverter(XtRString, XtRSourceType, CvtStringToSourceType, NULL, 0);
+ XtAddConverter(XtRString, XtRWrap, CvtStringToWrap, NULL, 0);
+ XtAddConverter(XtRString, XtRWrapBreak, CvtStringToWrapBreak, NULL, 0);
+ XtAddConverter(XtRString, XtRWrapForm, CvtStringToWrapForm, NULL, 0);
+ XtAddConverter(XtRString, XtRScroll, CvtStringToScroll, NULL, 0);
+ XtAddConverter(XtRString, XtRGrow, CvtStringToGrow, NULL, 0);
+
+ }
+ registered = True;
+}
+
+
+
+
+/************************************************************************
+ *
+ * Resource Conversion Functions
+ * The following set of functions are used by the resource
+ * manager to convert the resource types defined for this class.
+ *
+ ************************************************************************/
+
+
+/* Convert a string to a traversal type. */
+
+static void _XwCvtStringToTraversalType (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ char * in_str = (char *) (fromVal->addr);
+ static int i;
+
+ i = XwHIGHLIGHT_OFF;
+
+ if (((*in_str) == 'H') || ((*in_str) == 'h'))
+ {
+ if (StringsAreEqual (in_str, "highlight_traversal"))
+ i = XwHIGHLIGHT_TRAVERSAL;
+ else if (StringsAreEqual (in_str, "highlight_enter"))
+ i = XwHIGHLIGHT_ENTER;
+ }
+
+ (*toVal).size = sizeof (int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+/******************************************************/
+/* Convert a string to a ButtonClass Label Location. */
+/******************************************************/
+static void _XwCvtStringToLabelLocation (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ char * in_str = (char *) (fromVal->addr);
+ static int i;
+
+ if (((*in_str)== 'L') || ((*in_str)=='l'))
+ {
+ if (StringsAreEqual(in_str,"left")) i = XwLEFT;
+ }
+ else
+ i = XwRIGHT;
+
+ (*toVal).size = sizeof (int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+/********************************************************/
+/* Convert a string to ManagerClass layout mode type. */
+/********************************************************/
+static void _XwCvtStringToLayoutPolicy (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ char * in_str = (char *) (fromVal->addr);
+ static int i;
+
+ i = XwMINIMIZE;
+
+ switch(*in_str)
+ {
+ case 'I':
+ case 'i':
+ if (StringsAreEqual(in_str,"ignore")) i = XwIGNORE;
+ break;
+
+ case 'M':
+ case 'm':
+ if (StringsAreEqual(in_str,"maximize")) i = XwMAXIMIZE;
+
+ }
+
+ (*toVal).size = sizeof (int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+
+
+static Boolean StringsAreEqual(in_str, test_str)
+char *in_str, *test_str;
+{
+ int i, j;
+
+ for (;;)
+ {
+ i = *in_str;
+ j = *test_str;
+
+ if (isupper(i)) i = tolower(i);
+ if (isupper(j)) j = tolower(j);
+ if (i != j) return (False);
+ if (i == 0) return (True);
+
+ in_str++;
+ test_str++;
+ }
+}
+
+
+/* Convert a string to a highlight type. */
+
+static void _XwCvtStringToHighlightStyle (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ char * in_str = (char *) (fromVal->addr);
+ static int i;
+
+ i = XwWIDGET_DEFINED;
+
+ if (((*in_str) == 'P') || ((*in_str) == 'p'))
+ if (StringsAreEqual (in_str, "pattern_border"))
+ i = XwPATTERN_BORDER;
+
+ (*toVal).size = sizeof (int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+/* Convert a string to an tile type. */
+
+static void _XwCvtStringToTileType (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ char * in_str = (char *) (fromVal->addr);
+ static int i;
+
+ i = XwFOREGROUND;
+
+ switch (*in_str)
+ {
+ case 'F':
+ case 'f':
+ if (StringsAreEqual (in_str, "foreground")) i = XwFOREGROUND;
+ break;
+
+ case 'B':
+ case 'b':
+ if (StringsAreEqual (in_str, "background")) i = XwBACKGROUND;
+ break;
+ }
+
+
+ (*toVal).size = sizeof (int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void _XwCvtStringToAlignment()
+ * Display *display;
+ * XrmValue *p_fromVal;
+ * XrmValue *toVal;
+ *
+ * Description:
+ * -----------
+ * This is a type conversion procedure for the resource manager.
+ * converts strings to type XwAlignment. The conversion is case
+ * insensitive.
+ *
+ * Inputs:
+ * ------
+ * See "Xlib - C Language X Interface Protocol Version 11"
+ *
+ * Outputs:
+ * -------
+ * See "Xlib - C Language X Interface Protocol Version 11"
+ *
+ * Procedures Called
+ * -----------------
+ * StringsAreEqual
+ *
+ *************************************<->***********************************/
+static void _XwCvtStringToAlignment(args,num,p_fromVal,toVal)
+ XrmValue *args;
+ Cardinal num;
+ XrmValue *p_fromVal;
+ XrmValue *toVal;
+{
+ static XwAlignment Align = XwALIGN_LEFT;
+ char *from_str;
+ Boolean match = FALSE;
+
+ from_str = (char *) (p_fromVal->addr);
+ toVal->addr = (caddr_t) &Align;
+ toVal->size = sizeof(XwAlignment);
+
+ switch(*from_str)
+ {
+ case 'L':
+ case 'l':
+ if (match = StringsAreEqual(from_str,"left"))
+ Align = XwALIGN_LEFT;
+ break;
+ case 'C':
+ case 'c':
+ if (match = StringsAreEqual(from_str,"center"))
+ Align = XwALIGN_CENTER;
+ break;
+ case 'R':
+ case 'r':
+ if (match = StringsAreEqual(from_str,"right"))
+ Align = XwALIGN_RIGHT;
+ break;
+ case 'N':
+ case 'n':
+ if (match = StringsAreEqual(from_str,"none"))
+ Align = XwALIGN_NONE;
+ break;
+ default:
+ match = FALSE;
+ break;
+ }
+
+ if(!match)
+ {
+ toVal->addr = NULL;
+ toVal->size = 0;
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void _XwCvtStringToWidgetType()
+ * Display *display;
+ * XrmValue *p_fromVal;
+ * XrmValue *toVal;
+ *
+ * Description:
+ * -----------
+ * This is a type conversion procedure for the resource manager.
+ * converts strings to type XwWidgetType. The conversion is case
+ * insensitive.
+ *
+ * Inputs:
+ * ------
+ * See "Xlib - C Language X Interface Protocol Version 11"
+ *
+ * Outputs:
+ * -------
+ * See "Xlib - C Language X Interface Protocol Version 11"
+ *
+ * Procedures Called
+ * -----------------
+ * StringsAreEqual
+ *
+ *************************************<->***********************************/
+static void _XwCvtStringToWidgetType(args,num,p_fromVal,toVal)
+ XrmValue *args;
+ Cardinal num;
+ XrmValue *p_fromVal;
+ XrmValue *toVal;
+{
+ static XwWidgetType WType = XwUNKNOWN;
+ char *from_str;
+ Boolean match = FALSE;
+
+ from_str = (char *) (p_fromVal->addr);
+ toVal->addr = (caddr_t) &WType;
+ toVal->size = sizeof(XwWidgetType);
+
+ switch(*from_str)
+ {
+ case 'T':
+ case 't':
+ if (match = StringsAreEqual(from_str,"title"))
+ WType = XwTITLE;
+ break;
+ case 'P':
+ case 'p':
+ if (match = StringsAreEqual(from_str,"pulldown"))
+ WType = XwPULLDOWN;
+ break;
+ case 'W':
+ case 'w':
+ if (match = StringsAreEqual(from_str,"work space"))
+ WType = XwWORK_SPACE;
+ break;
+ case 'U':
+ case 'u':
+ if (match = StringsAreEqual(from_str,"unknown"))
+ WType = XwUNKNOWN;
+ break;
+ default:
+ match = FALSE;
+ break;
+ }
+
+ if(!match)
+ {
+ toVal->addr = NULL;
+ toVal->size = 0;
+ }
+}
+
+
+
+
+/************************************************************************
+ *
+ * _XwCvtStringToGravity
+ * Convert a resource string to a gravity value.
+ *
+ ************************************************************************/
+
+static void _XwCvtStringToGravity (args, numArgs, fromVal, toVal)
+XrmValue * args;
+Cardinal numArgs;
+XrmValue * fromVal;
+XrmValue * toVal;
+
+{
+ static int gravity = CenterGravity;
+ char *from_str;
+ Boolean match = FALSE;
+
+ from_str = (char *) (fromVal->addr);
+ toVal->addr = (caddr_t) &gravity;
+ toVal->size = sizeof(int);
+
+ switch (*from_str)
+ {
+ case 'N':
+ case 'n':
+ if (match = StringsAreEqual(from_str,"NorthGravity"))
+ gravity = NorthGravity;
+ else if (match = StringsAreEqual(from_str,"NorthWestGravity"))
+ gravity = NorthWestGravity;
+ else if (match = StringsAreEqual(from_str,"NorthEastGravity"))
+ gravity = NorthEastGravity;
+ break;
+ case 'S':
+ case 's':
+ if (match = StringsAreEqual(from_str,"SouthGravity"))
+ gravity = SouthGravity;
+ else if (match = StringsAreEqual(from_str,"SouthWestGravity"))
+ gravity = SouthWestGravity;
+ else if (match = StringsAreEqual(from_str,"SouthEastGravity"))
+ gravity = SouthEastGravity;
+ break;
+ case 'W':
+ case 'w':
+ if (match = StringsAreEqual(from_str,"WestGravity"))
+ gravity = WestGravity;
+ break;
+ case 'E':
+ case 'e':
+ if (match = StringsAreEqual(from_str,"EastGravity"))
+ gravity = EastGravity;
+ break;
+ case 'C':
+ case 'c':
+ if (match = StringsAreEqual(from_str,"CenterGravity"))
+ gravity = CenterGravity;
+ break;
+ default:
+ match = FALSE;
+ break;
+ }
+
+ if(!match)
+ {
+ toVal->addr = NULL;
+ toVal->size = 0;
+ }
+}
+
+static void _XwCvtStringToTitleType (args, num_args, fromVal, toVal)
+
+ XrmValuePtr args;
+ Cardinal * num_args;
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+
+{
+ static int i;
+ String source = (String) fromVal->addr;
+
+ if (source)
+ {
+ if (strcmp ("string", source) == 0)
+ i = XwSTRING;
+ else if (strcmp ("image", source) == 0)
+ i = XwIMAGE;
+ else if (strcmp ("rect", source) == 0)
+ i = XwRECT;
+ else
+ {
+ i = XwSTRING;
+ XtWarning (
+ "MenuPane: Unknown title type specified; using string title");
+ }
+ }
+ else
+ {
+ i = XwSTRING;
+ XtWarning ("MenuPane: Unknown title type specified; using string title");
+ }
+
+ (*toVal).size = sizeof(int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+
+static void _XwCvtStringToLabelType (args, num_args, fromVal, toVal)
+
+ XrmValuePtr args;
+ Cardinal * num_args;
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+
+{
+ static int i;
+
+ if (strcmp ("string", (char *) fromVal->addr) == 0)
+ i = XwSTRING;
+ else if (strcmp ("image", (char *) fromVal->addr) == 0)
+ i = XwIMAGE;
+ else
+ {
+ i = XwSTRING;
+ XtWarning
+ ("MenuButton: Unknown label type specified; using string label");
+ }
+
+ (*toVal).size = sizeof(int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+static void _XwCvtStringToTitlePositionType (args, num_args, fromVal, toVal)
+
+ XrmValuePtr args;
+ Cardinal * num_args;
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+
+{
+ static int i;
+ String source = (char *) fromVal->addr;
+
+ if (source)
+ {
+ /* Force the comparison to be case insensitive */
+ for (i = 0; i < XwStrlen(source); i++)
+ {
+ if (isupper (source[i]))
+ source[i] = tolower(source[i]);
+ }
+
+ if (strcmp ("bottom", source) == 0)
+ i = XwBOTTOM;
+ else if (strcmp ("top", source) == 0)
+ i = XwTOP;
+ else if (strcmp ("both", source) == 0)
+ i = XwTOP | XwBOTTOM;
+ else
+ {
+ i = XwTOP;
+ XtWarning ("Cascade: Invalid title position; position set to top");
+ }
+ }
+ else
+ {
+ i = XwTOP;
+ XtWarning ("Cascade: Invalid title position; position set to top");
+ }
+
+ (*toVal).size = sizeof(int);
+ (*toVal).addr = (caddr_t) &i;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Type long to type long conversion (mostly to satisfy picky 64-bit OSF) */
+/*---------------------------------------------------------------------------*/
+
+static void _XwCvtLongToLong (args, num_args, fromVal, toVal)
+
+ XrmValuePtr args;
+ Cardinal * num_args;
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+
+{
+ long result = (long) fromVal->addr;
+
+ if (!result) {
+ XtWarning ("SourceStr: Invalid max_size; max_size set to -1");
+ result = -1;
+ }
+ (*toVal).size = sizeof(long);
+ (*toVal).addr = (caddr_t) &result;
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SetConverter(fromVal, toVal, setNum)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr fromVal, toVal;
+ int setNum;
+{
+ int j;
+ XwSetValuePair *ptr;
+ static int value;
+ unsigned char *fromstr;
+
+ fromstr = (unsigned char *)fromVal->addr;
+ ptr = valuepairsets[setNum];
+ for(j=0; *ptr[j].string; j++)
+ if (!strcmp(ptr[j].string, fromstr)) {
+ value = ptr[j].value;
+ toVal->size = sizeof(int);
+ toVal->addr = (caddr_t)&value;
+ return;
+ };
+ toVal->size = 0;
+ toVal->addr = NULL;
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToEditMode(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwEditTypeValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToSourceType(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwSourceTypeValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToWrap(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwWrapValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToWrapForm(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwWrapFormValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToWrapBreak(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwWrapBreakValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToScroll(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwScrollValueSetNum);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void CvtStringToGrow(args, num_args, fromVal, toVal)
+/*--------------------------------------------------------------------------+*/
+ XrmValuePtr *args; /* unused */
+ Cardinal *num_args; /* unused */
+ XrmValuePtr fromVal;
+ XrmValuePtr toVal;
+{
+ SetConverter(fromVal, toVal, XwGrowValueSetNum);
+}
diff --git a/Xw/SText.c b/Xw/SText.c
new file mode 100644
index 0000000..bbdcba8
--- /dev/null
+++ b/Xw/SText.c
@@ -0,0 +1,1474 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: SText.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code/Definitions for StaticText widget class.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/*
+ * Include files & Static Routine Definitions
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/StringDefs.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <X11/keysymdef.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/SText.h>
+#include <Xw/STextP.h>
+
+static void Initialize ();
+static void Realize();
+static void Destroy();
+static void Resize();
+static Boolean SetValues();
+static void Redisplay();
+static void Select();
+static void Release();
+static void Toggle();
+static void ClassInitialize();
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: default translation table for class: StaticText
+ * -----------
+ *
+ * Matches events with string descriptors for internal routines.
+ *
+ *************************************<->***********************************/
+
+static char defaultTranslations[] =
+ "<EnterWindow>: enter()\n\
+ <LeaveWindow>: leave()\n\
+ <Btn1Down>: select()\n\
+ <Btn1Up>: release()\n\
+ <KeyDown>Select: select() \n\
+ <KeyUp>Select: release()";
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: action list for class: StaticText
+ * -----------
+ *
+ * Matches string descriptors with internal routines.
+ * Note that Primitive will register additional event handlers
+ * for traversal.
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ { "enter", (XtActionProc) _XwPrimitiveEnter },
+ { "leave", (XtActionProc) _XwPrimitiveLeave },
+ { "select", (XtActionProc) Select },
+ { "release", (XtActionProc) Release },
+ {"toggle", (XtActionProc) Toggle },
+};
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: resource list for class: StaticText
+ * -----------
+ *
+ * Provides default resource settings for instances of this class.
+ * To get full set of default settings, examine resouce list of super
+ * classes of this class.
+ *
+ *************************************<->***********************************/
+
+static XtResource resources[] = {
+ { XtNhSpace,
+ XtCHSpace,
+ XtRDimension,
+ sizeof(Dimension),
+ XtOffset(XwStaticTextWidget, static_text.internal_width),
+ XtRString,
+ "2"
+ },
+ { XtNvSpace,
+ XtCVSpace,
+ XtRDimension,
+ sizeof(Dimension),
+ XtOffset(XwStaticTextWidget, static_text.internal_height),
+ XtRString,
+ "2"
+ },
+ { XtNalignment,
+ XtCAlignment,
+ XtRAlignment,
+ sizeof(XwAlignment),
+ XtOffset(XwStaticTextWidget,static_text.alignment),
+ XtRString,
+ "Left"
+ },
+ { XtNgravity,
+ XtCGravity,
+ XtRGravity,
+ sizeof(int),
+ XtOffset(XwStaticTextWidget,static_text.gravity),
+ XtRString,
+ "CenterGravity"
+ },
+ { XtNwrap,
+ XtCWrap,
+ XtRBoolean,
+ sizeof(Boolean),
+ XtOffset(XwStaticTextWidget,static_text.wrap),
+ XtRString,
+ "TRUE"
+ },
+ { XtNstrip,
+ XtCStrip,
+ XtRBoolean,
+ sizeof(Boolean),
+ XtOffset(XwStaticTextWidget,static_text.strip),
+ XtRString,
+ "TRUE"
+ },
+ { XtNlineSpace,
+ XtCLineSpace,
+ XtRInt,
+ sizeof(int),
+ XtOffset(XwStaticTextWidget,static_text.line_space),
+ XtRString,
+ "0"
+ },
+ { XtNfont,
+ XtCFont,
+ XtRFontStruct,
+ sizeof(XFontStruct *),
+ XtOffset(XwStaticTextWidget,static_text.font),
+ XtRString,
+ "Fixed"
+ },
+ { XtNstring,
+ XtCString,
+ XtRString,
+ sizeof(char *),
+ XtOffset(XwStaticTextWidget, static_text.input_string),
+ XtRString,
+ NULL
+ },
+};
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: global class record for instances of class: StaticText
+ * -----------
+ *
+ * Defines default field settings for this class record.
+ *
+ *************************************<->***********************************/
+
+XwStaticTextClassRec XwstatictextClassRec = {
+ { /* core_class fields */
+ /* superclass */ (WidgetClass) &XwprimitiveClassRec,
+ /* class_name */ "XwStaticText",
+ /* widget_size */ sizeof(XwStaticTextRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ (XtInitProc) Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ (XtRealizeProc) Realize,
+ /* actions */ actionsList,
+ /* num_actions */ XtNumber(actionsList),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ (XtWidgetProc) Destroy,
+ /* resize */ (XtWidgetProc) Resize,
+ /* expose */ (XtExposeProc) Redisplay,
+ /* set_values */ (XtSetValuesFunc) SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ (XtAlmostProc) XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback private */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ }
+};
+
+WidgetClass XwstatictextWidgetClass = (WidgetClass) &XwstatictextClassRec;
+WidgetClass XwstaticTextWidgetClass = (WidgetClass) &XwstatictextClassRec;
+
+
+
+/*************************************<->*************************************
+ *
+ * ClassInitialize
+ *
+ * Description:
+ * -----------
+ * Set fields in primitive class part of our class record so that
+ * the traversal code can invoke our select/release procedures (note
+ * that for this class toggle is a empty proc).
+ *
+ *************************************<->***********************************/
+static void ClassInitialize()
+{
+ XwstatictextClassRec.primitive_class.select_proc = (XwEventProc) Select;
+ XwstatictextClassRec.primitive_class.release_proc = (XwEventProc) Release;
+ XwstatictextClassRec.primitive_class.toggle_proc = (XwEventProc) Toggle;
+}
+
+
+/*************************************<->*************************************
+ *
+ * Procedures and variables private to StaticText
+ *
+ *************************************<->************************************/
+
+static void ValidateInputs();
+static void SetNormalGC();
+static int RetCount();
+static int Maxline();
+static void FormatText();
+static void GetTextRect();
+static void SetSize();
+
+
+/*************************************<->*************************************
+ *
+ * static void ValidateInputs(stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * Checks a StaticText widget for nonsensical values, and changes
+ * nonsense values into meaninful values.
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtWarning
+ *
+ *************************************<->***********************************/
+static void ValidateInputs(stw)
+ XwStaticTextWidget stw;
+{
+ XwStaticTextPart *stp;
+
+ stp = &(stw->static_text);
+
+ /*
+ *Check line_spacing. We will allow text to over write,
+ * we will not allow it to move from bottom to top.
+ */
+ if (stp->line_space < -100)
+ {
+ XtWarning("XwStaticTextWidget: line_space was less than -100, set to 0\n");
+ stp->line_space = 0;
+ }
+
+ /*
+ * Check Alignment
+ */
+
+ switch(stp->alignment)
+ {
+ case XwALIGN_LEFT:
+ case XwALIGN_CENTER:
+ case XwALIGN_RIGHT:
+ /* Valid values. */
+ break;
+ default:
+ XtWarning("XwStaticTextWidget: Unknown alignment, set to Left instead");
+ stp->alignment = XwALIGN_LEFT;
+ break;
+ }
+
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void SetNormalGC (stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * Sets up a GC for the static text widget to write to.
+ *
+ * Inputs:
+ * ------
+ * stw = Points to an instance structure which has primitive.foreground
+ * core.background_pixel and static_text.font appropriately
+ * filled in with values.
+ *
+ * Outputs:
+ * -------
+ * Associates static_text.normal_GC with a GC.
+ *
+ * Procedures Called
+ * -----------------
+ * XCreateGC
+ * XSetClipRectangles
+ *
+ *************************************<->***********************************/
+static void SetNormalGC(stw)
+ XwStaticTextWidget stw;
+{
+ XGCValues values;
+ XtGCMask valueMask;
+ XRectangle ClipRect;
+
+ valueMask = GCForeground | GCBackground | GCFont;
+
+ values.foreground = stw->primitive.foreground;
+ values.background = stw->core.background_pixel;
+ values.font = stw->static_text.font->fid;
+
+ stw->static_text.normal_GC = XCreateGC(XtDisplay(stw),XtWindow(stw),
+ valueMask,&values);
+ /*
+ * Set the Clip Region.
+ */
+ ClipRect.width = stw->core.width -
+ (2 * (stw->static_text.internal_width +
+ stw->primitive.highlight_thickness));
+ ClipRect.height = stw->core.height -
+ (2 * (stw->static_text.internal_height +
+ stw->primitive.highlight_thickness));
+ ClipRect.x = stw->primitive.highlight_thickness +
+ stw->static_text.internal_width;
+ ClipRect.y = stw->primitive.highlight_thickness +
+ stw->static_text.internal_height;
+
+ XSetClipRectangles(XtDisplay(stw),stw->static_text.normal_GC,
+ 0,0, &ClipRect,1,Unsorted);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static int RetCount(string)
+ * char *string;
+ *
+ * Description:
+ * -----------
+ * This routine returns the number of '\n' characters in "string"
+ *
+ * Inputs:
+ * ------
+ * string = The string to be counted.
+ *
+ * Outputs:
+ * -------
+ * The number of '\n' characters in the string.
+ *
+ * Procedures Called
+ * -----------------
+ *
+ *************************************<->***********************************/
+static int RetCount(string)
+ char *string;
+{
+ int numlines;
+
+ numlines = (*string ? 1 : 0);
+ while (*string)
+ {
+ if (*string == '\n')
+ numlines++;
+ string++;
+ }
+ return(numlines);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static int Maxline(string, font)
+ * char *string;
+ * XFontStruct *font;
+ *
+ * Description:
+ * -----------
+ * For a given string and a given font, returns the length of
+ * '\n' delimited series of characters.
+ *
+ * Inputs:
+ * ------
+ * string = The string to be analyzed.
+ * font = The font in which string is to be analyzed.
+ *
+ * Outputs:
+ * -------
+ * The maximun length in pixels of the longest '\n' delimited series of
+ * characters.
+ *
+ * Procedures Called
+ * -----------------
+ * XTextWidth
+ *
+ *************************************<->***********************************/
+static int Maxline(stw)
+ XwStaticTextWidget stw;
+{
+ int i, cur;
+ int max = 0;
+ char *str1, *str2, *str3;
+ XwAlignment alignment = stw->static_text.alignment;
+ XFontStruct *font = stw->static_text.font;
+ XwStaticTextPart *stp;
+
+ stp = &(stw->static_text);
+ str1 = stp->output_string;
+ while(*str1)
+ {
+ if ((stp->strip) &&
+ ((alignment == XwALIGN_LEFT) ||
+ (alignment == XwALIGN_CENTER)))
+ while (*str1 == ' ')
+ str1++;
+ str2 = str1;
+ for(i=0; ((*str1 != '\n') && *str1); i++, str1++);
+ if ((stp->strip) &&
+ ((alignment == XwALIGN_RIGHT) ||
+ (alignment == XwALIGN_CENTER)))
+ {
+ str3 = str1;
+ str3--;
+ while (*str3 == ' ')
+ i--, str3--;
+ }
+ if (i)
+ cur = XTextWidth(font,str2,i);
+ else
+ cur = 0;
+ if (cur > max)
+ max = cur;
+ if (*str1)
+ str1++; /* Step past the \n */
+ }
+ return(max);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void FormatText(stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * Inserts newlines where necessary to fit stw->static_text.output_string
+ * into stw->core.width (if specified).
+ *
+ * Inputs:
+ * ------
+ * stw = The StaticText widget to be formatted.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XTextWidth
+ *
+ *************************************<->***********************************/
+static void FormatText(stw)
+ XwStaticTextWidget stw;
+{
+ int i, width, win, wordindex;
+ char *str1, *str2;
+ Boolean gotone;
+ XwStaticTextPart *stp;
+
+ stp = &(stw->static_text);
+ str1 = stp->output_string;
+
+ /* The available text window width is... */
+ win = stw->core.width - (2 * stp->internal_width)
+ - (2 * stw->primitive.highlight_thickness);
+
+ while (*str1)
+ {
+ i = 0;
+ width = 0;
+ wordindex = -1;
+ gotone = FALSE;
+ str2 = str1;
+ while (!gotone)
+ {
+ if ((stp->strip) && (wordindex == -1))
+ while (*str1 == ' ')
+ str1++;
+ /*
+ *Step through until a character that we can
+ * break on.
+ */
+ while ((*str1 != ' ') && (*str1 != '\n') && (*str1))
+ i++, str1++;
+
+ wordindex++;
+ width = (i ? XTextWidth(stp->font,str2,i) : 0);
+ width;
+ if (width < win)
+ {
+ /*
+ * If the current string fragment is shorter than the
+ * available window. Check to see if we are at a
+ * forced break or not, and process accordingly.
+ */
+ switch (*str1)
+ {
+ case ' ':
+ /*
+ * Add the space to the char count
+ */
+ i++;
+ /*
+ * Check to see there's room to start another
+ * word.
+ */
+ width = XTextWidth(stw->static_text.font,
+ str2,i);
+ if (width >= win)
+ {
+ /*
+ * Break the line if we can't start
+ * another word.
+ */
+ *str1 = '\n';
+ gotone = TRUE;
+ }
+ /*
+ * Step past the space
+ */
+ str1++;
+ break;
+ case '\n':
+ /*
+ * Forced break. Step pase the \n.
+ * Note the fall through to default.
+ */
+ str1++;
+ default:
+ /*
+ * End of string.
+ */
+ gotone = TRUE;
+ break;
+ }
+ }
+ else if (width > win)
+ {
+ /*
+ * We know that we have something
+ */
+ gotone = TRUE;
+
+ /*
+ * See if there is at least one space to back up for.
+ */
+ if (wordindex)
+ {
+ str1--;
+ while (*str1 != ' ')
+ str1--;
+ *str1++ = '\n';
+ }
+ else
+ /*
+ * We have a single word which is too long
+ * for the available window. Let the text
+ * clip rectangle handle it.
+ */
+ if (*str1)
+ *str1++ = '\n';
+ }
+ else /* (width == win) */
+ {
+ switch (*str1)
+ {
+ case ' ':
+ /*
+ * If we stopped on a space, change it.
+ */
+ *str1 = '\n';
+ case '\n':
+ /*
+ * Step past the \n.
+ */
+ str1++;
+ default:
+ gotone = TRUE;
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void GetTextRect(newstw)
+ * XwStaticTextWidget newstw;
+ *
+ * Description:
+ * -----------
+ * Sets newstw->static_text.TextRect to appropriate values given
+ * newstw->core.width and newstw->static_text.input_string. The
+ * string is formatted if necessary.
+ *
+ * A newstw->core.width value of 0 tells this procedure to choose
+ * its own size based soley on newstw->static_text.input_string.
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Maxline
+ * RetCount
+ *
+ *************************************<->***********************************/
+static void GetTextRect(newstw)
+ XwStaticTextWidget newstw;
+{
+ int maxlen, maxwin, fheight, numrets;
+ XwStaticTextPart *stp;
+
+ stp = &(newstw->static_text);
+ /*
+ * Set the line height from the font structure.
+ */
+ fheight = stp->font->ascent + stp->font->descent;
+ if (newstw->core.width)
+ {
+ /*
+ * We were requested with a specific width. We must
+ * fit ourselves to it.
+ *
+ * The maximum available window width is...
+ */
+ maxwin = newstw->core.width - (2 * stp->internal_width)
+ - (2 * newstw->primitive.highlight_thickness);
+ if (stp->wrap)
+ {
+ if ((maxlen = Maxline(newstw)) <=
+ maxwin)
+ /*
+ * We fit without formatting.
+ */
+ stp->TextRect.width = maxlen;
+ else
+ {
+ stp->TextRect.width = maxwin;
+ /*
+ * Make the string fit.
+ */
+ FormatText(newstw);
+ }
+ }
+ else
+ stp->TextRect.width = Maxline(newstw);
+ }
+ else
+ stp->TextRect.width = Maxline(newstw);
+ /*
+ * See how tall the string wants to be.
+ */
+ numrets = RetCount(stp->output_string);
+ stp->TextRect.height = (fheight * numrets)
+ + (((numrets - 1) * (stp->line_space / 100.0)) * fheight);
+
+ if ((newstw->core.height) &&
+ ((newstw->core.height - (2 * stp->internal_height)
+ - (2 * newstw->primitive.highlight_thickness)) <
+ stp->TextRect.height))
+ /*
+ * Shorten the TextRect if the string wants
+ * to be too tall.
+ */
+ stp->TextRect.height = newstw->core.height
+ - (2 * stp->internal_height)
+ - (2 * newstw->primitive.highlight_thickness);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void SetSize(newstw)
+ * XwStaticTextWidget newstw;
+ *
+ * Description:
+ * -----------
+ * Copies newstw->static_text.input_string into output_string
+ *
+ * Sets newstw->core.width, newstw->core.height, and
+ * newstw->static_text.TextRect appropriately, formatting the
+ * string if necessary.
+ *
+ * The Clip Rectangle is placed in the window.
+ *
+ * Inputs:
+ * ------
+ * stw = A meaningful StaticTextWidget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * strcpy
+ * GetTextRect
+ *
+ *************************************<->***********************************/
+static void SetSize(newstw)
+ XwStaticTextWidget newstw;
+{
+ XwStaticTextPart *stp;
+
+ stp = &(newstw->static_text);
+ /*
+ * Copy the input string into the output string.
+ */
+ if (stp->output_string != NULL)
+ XtFree(stp->output_string);
+ stp->output_string = XtMalloc(XwStrlen(stp->input_string)+1);
+ if(stp->input_string)
+ strcpy(stp->output_string,stp->input_string);
+ if (*(stp->output_string))
+ /*
+ * If we have a string then size it.
+ */
+ GetTextRect(newstw);
+ else
+ {
+ stp->TextRect.width = 0;
+ stp->TextRect.height = 0;
+ }
+ /*
+ * Has a size been specified?
+ */
+ if (newstw->core.width)
+ {
+ if ((newstw->core.width
+ - (2 * newstw->primitive.highlight_thickness)
+ - (2 * stp->internal_width)) > stp->TextRect.width)
+ {
+ /*
+ * Use the extra space according to the gravity
+ * resource setting.
+ */
+ switch (stp->gravity)
+ {
+ case EastGravity:
+ case NorthEastGravity:
+ case SouthEastGravity:
+ stp->TextRect.x = newstw->core.width -
+ (newstw->primitive.highlight_thickness +
+ stp->TextRect.width + stp->internal_width);
+ break;
+ case WestGravity:
+ case NorthWestGravity:
+ case SouthWestGravity:
+ stp->TextRect.x = stp->internal_width +
+ newstw->primitive.highlight_thickness;
+ break;
+ default:
+ stp->TextRect.x = (newstw->core.width
+ - stp->TextRect.width) / 2;
+ break;
+ }
+ }
+ else
+ /*
+ * We go to the left.
+ */
+ stp->TextRect.x = newstw->primitive.highlight_thickness
+ + stp->internal_width;
+ }
+ else
+ {
+ /*
+ * We go to the left.
+ */
+ stp->TextRect.x = newstw->primitive.highlight_thickness
+ + stp->internal_width;
+ newstw->core.width = stp->TextRect.width
+ + (2 * stp->internal_width)
+ + (2 * newstw->primitive.highlight_thickness);
+ }
+ /*
+ * Has a height been specified?
+ */
+ if (newstw->core.height)
+ {
+ if ((newstw->core.height - (2 * stp->internal_height)
+ - (2 * newstw->primitive.highlight_thickness)) >
+ stp->TextRect.height)
+ {
+ /*
+ * Use the extra space according to the gravity
+ * resource setting.
+ */
+ switch (stp->gravity)
+ {
+ case NorthGravity:
+ case NorthEastGravity:
+ case NorthWestGravity:
+ stp->TextRect.y = stp->internal_height +
+ newstw->primitive.highlight_thickness;
+ break;
+ case SouthGravity:
+ case SouthEastGravity:
+ case SouthWestGravity:
+ stp->TextRect.y = newstw->core.height -
+ (newstw->primitive.highlight_thickness +
+ stp->TextRect.height + stp->internal_width);
+ break;
+ default:
+ stp->TextRect.y = (newstw->core.height
+ - stp->TextRect.height)/ 2;
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * We go to the top.
+ */
+ stp->TextRect.y = newstw->primitive.highlight_thickness
+ + stp->internal_height;
+ }
+ }
+ else
+ {
+ /*
+ * We go to the top.
+ */
+ stp->TextRect.y = newstw->primitive.highlight_thickness
+ + stp->internal_height;
+ /*
+ * We add our size to the current size.
+ * (Primitive has already added highlight_thicknesses.)
+ */
+ newstw->core.height = stp->TextRect.height
+ + (2 * stp->internal_height)
+ + (2 * newstw->primitive.highlight_thickness);
+ }
+}
+
+
+static void ProcessBackslashes(output,input)
+ char *output, *input;
+{
+ char *out, *in;
+
+ out = output;
+ in = input;
+ while(*in)
+ if (*in == '\\')
+ {
+ in++;
+ switch (*in)
+ {
+ case 'n':
+ *out++ = '\n';
+ break;
+ case 't':
+ *out++ = '\t';
+ break;
+ case 'b':
+ *out++ = '\b';
+ break;
+ case 'r':
+ *out++ = '\r';
+ break;
+ case 'f':
+ *out++ = '\f';
+ break;
+ default:
+ *out++ = '\\';
+ *out++ = *in;
+ break;
+ }
+ in++;
+ }
+ else
+ *out++ = *in++;
+ *out = '\0';
+}
+
+/*************************************<->*************************************
+ *
+ * static void Initialize (request, new)
+ * Widget request, new;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * Xmalloc
+ * ProcessBackslashes
+ * XwStrlen
+ * SetSize
+ *
+ *************************************<->***********************************/
+static void Initialize (req, new)
+ XwStaticTextWidget req, new;
+{
+ char *s;
+
+ new->static_text.output_string = NULL;
+
+ if (new->static_text.input_string != NULL)
+ {
+
+ /*
+ * Copy the input string into local space.
+ */
+ s = XtMalloc(XwStrlen(new->static_text.input_string)+1);
+ ProcessBackslashes(s,new->static_text.input_string);
+ new->static_text.input_string = s;
+ }
+
+ ValidateInputs(new);
+ new->core.width = req->core.width;
+ new->core.height = req->core.height;
+ SetSize(new);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static Boolean SetValues(current, request, new, last)
+ * XwStaticTextWidget current, request, new;
+ * Boolean last;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * ValidateInputs
+ * strcmp
+ * SetSize
+ * SetNormalGC
+ *
+ *************************************<->***********************************/
+static Boolean SetValues(current, request, new, last)
+ XwStaticTextWidget current, request, new;
+ Boolean last;
+{
+ Boolean flag = FALSE;
+ Boolean newstring = FALSE;
+ Boolean layoutchanges = FALSE;
+ Boolean otherchanges = FALSE;
+ char *newstr, *curstr;
+ char *s;
+ XwStaticTextPart *newstp, *curstp;
+ int new_w, new_h;
+
+ newstp = &(new->static_text);
+ curstp = &(current->static_text);
+ if (newstp->input_string != curstp->input_string)
+ {
+ newstring = TRUE;
+ /*
+ * Copy the input string into local space.
+ */
+ s = XtMalloc(XwStrlen(newstp->input_string)+1);
+ ProcessBackslashes(s,new->static_text.input_string);
+ /*
+ * Deallocate the old string.
+ */
+ XtFree(curstp->input_string);
+ /*
+ * Have everybody point to the new string.
+ */
+ newstp->input_string = s;
+ curstp->input_string = s;
+ request->static_text.input_string = s;
+ }
+
+ ValidateInputs(new);
+
+ if ((newstring) ||
+ (newstp->font != curstp->font) ||
+ (newstp->internal_height != curstp->internal_height) ||
+ (newstp->internal_width != curstp->internal_width) ||
+ ((new->core.width <= 0) || (new->core.height <= 0)) ||
+ (request->core.width != current->core.width) ||
+ (request->core.height != current->core.height))
+ {
+ if (request->primitive.recompute_size)
+ {
+ if (request->core.width == current->core.width)
+ new->core.width = 0;
+ if (request->core.height == current->core.height)
+ new->core.height = 0;
+ }
+
+ /*
+ * Call SetSize to get the new size.
+ */
+ SetSize(new);
+
+ /*
+ * Save changes that SetSize does to the layout.
+ */
+ new_w = new->core.width;
+ new_h = new->core.height;
+ /*
+ * In case our parent won't let us change size we must
+ * now restore the widget to the current size.
+ */
+ new->core.width = current->core.width;
+ new->core.height = current->core.height;
+ SetSize(new);
+ /*
+ * Reload new with the new sizes in order cause XtSetValues
+ * to invoke our parent's geometry management procedure.
+ */
+ new->core.width = new_w;
+ new->core.height = new_h;
+
+ flag = TRUE;
+ }
+
+ if ((new->primitive.foreground !=
+ current->primitive.foreground) ||
+ (new->core.background_pixel !=
+ current->core.background_pixel) ||
+ (newstp->font != curstp->font))
+ {
+ if (XtIsRealized((Widget)new))
+ {
+ XFreeGC(XtDisplay(new),new->static_text.normal_GC);
+ SetNormalGC(new);
+ }
+ flag = TRUE;
+ }
+
+ return(flag);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void Realize(w , valueMask, attributes)
+ * Widget w;
+ * XtValueMask *valueMask;
+ * XSetWindowAttributes *attributes;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtCreateWindow
+ * SetNormalGC
+ *
+ *************************************<->***********************************/
+static void Realize(stw , valueMask, attributes)
+ XwStaticTextWidget stw;
+ XtValueMask *valueMask;
+ XSetWindowAttributes *attributes;
+{
+
+ XtCreateWindow((Widget)stw,InputOutput,(Visual *) CopyFromParent,
+ *valueMask,attributes);
+ SetNormalGC(stw);
+ _XwRegisterName(stw);
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void Destroy(stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XtFree
+ * XFreeGC
+ *
+ *************************************<->***********************************/
+static void Destroy(stw)
+ XwStaticTextWidget stw;
+{
+ XtFree(stw->static_text.input_string);
+ XtFree(stw->static_text.output_string);
+ if (XtIsRealized((Widget)stw))
+ {
+ XFreeGC(XtDisplay(stw),stw->static_text.normal_GC);
+ }
+}
+
+
+/*************************************<->*************************************
+ *
+ * static void Redisplay(stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XTextExtents
+ * XDrawString
+ * XtWarning
+ *
+ *************************************<->***********************************/
+static void Redisplay(stw)
+ XwStaticTextWidget stw;
+{
+ GC normal_GC;
+ int i;
+ int cur_x, cur_y; /* Current start of baseline */
+ int y_delta; /* Absolute space between baselines */
+ int x_delta; /* For left bearing of the first char in a line */
+ int dir, asc, desc; /* Junk parameters for XTextExtents */
+ char *str1, *str2, *str3;
+ XFontStruct *font;
+ XCharStruct overall;
+ XRectangle *ClipRect;
+ XwStaticTextPart *stp;
+
+ /*
+ * This is to save typing for me and
+ * pointer arithmetic for the machine.
+ */
+ stp = &(stw->static_text);
+ str1 = str2 = stp->output_string;
+ font = stp->font;
+ normal_GC = stp->normal_GC;
+ ClipRect = &(stp->TextRect);
+
+ if (XtIsRealized((Widget)stw))
+ XClearArea(XtDisplay(stw),XtWindow(stw),
+ 0,0,stw->core.width,stw->core.height,FALSE);
+
+ /*
+ * We don't get to start drawing at the top of the text box.
+ * See X11 font manual pages.
+ */
+ cur_y = ClipRect->y + font->ascent;
+
+ /*
+ * Set up the total line spacing.
+ */
+ y_delta = ((stp->line_space / 100.0) + 1) * (font->descent + font->ascent);
+
+ switch (stp->alignment)
+ {
+ case XwALIGN_LEFT:
+ cur_x = ClipRect->x;
+ while(*str1)
+ {
+ /*
+ * Left alignment strips leading blanks.
+ */
+ if (stp->strip)
+ while(*str1 == ' ')
+ str1++;
+ str2 = str1;
+ /*
+ * Look for a newline and count characters.
+ */
+ for(i=0; ((*str1 != '\n') && *str1); i++, str1++);
+ /*
+ * Did we get anything?
+ */
+ if (i)
+ {
+ /*
+ * Handle the left bearing of the first char
+ * in this substring.
+ */
+ XTextExtents(font,str2,1,&dir,&asc,&desc,
+ &overall);
+ x_delta = overall.lbearing;
+ /*
+ * Write to the window
+ */
+ XDrawString(XtDisplay(stw),XtWindow(stw),
+ normal_GC,(cur_x + x_delta),cur_y,str2,i);
+ x_delta = overall.lbearing = 0;/* I'm paranoid...*/
+ }
+ /*
+ * Move to the next line.
+ */
+ cur_y += y_delta;
+ if (*str1)
+ str1++; /* Step past the \n */
+ }
+ break;
+ case XwALIGN_CENTER:
+ cur_x = ClipRect->x + (ClipRect->width / 2);
+ while(*str1)
+ {
+ /*
+ * Strip leading blanks.
+ */
+ if (stp->strip)
+ while(*str1 == ' ')
+ str1++;
+ str2 = str1;
+ for(i=0; ((*str1 != '\n') && *str1); i++, str1++);
+ /*
+ * Strip trailing blanks.
+ */
+ if (stp->strip)
+ {
+ str3 = str1;
+ str3--;
+ while (*str3 == ' ')
+ i--, str3--;
+ }
+ if (i)
+ {
+ /*
+ * Center the substring.
+ */
+ x_delta = XTextWidth(font,str2,i) / 2;
+ XDrawString(XtDisplay(stw),XtWindow(stw),
+ normal_GC,(cur_x - x_delta),cur_y,str2,i);
+ x_delta = 0; /* ... still paranoid...*/
+ }
+ cur_y += y_delta;
+ if (*str1)
+ str1++; /* Step past the \n */
+ }
+ break;
+ case XwALIGN_RIGHT:
+ cur_x = ClipRect->x + ClipRect->width;
+ while(*str1)
+ {
+ str2 = str1;
+ for(i=0; ((*str1 != '\n') && *str1); i++, str1++);
+ /*
+ * Strip trailing blanks.
+ */
+ if (stp->strip)
+ {
+ str3 = str1;
+ str3--;
+ while (*str3 == ' ')
+ i--, str3--;
+ }
+ if (i)
+ {
+ XDrawString(XtDisplay(stw),XtWindow(stw),
+ normal_GC,
+ (cur_x - XTextWidth(font,str2,i)),
+ cur_y,str2,i);
+ }
+ cur_y += y_delta;
+ if (*str1)
+ str1++; /* Step past the \n */
+ }
+ break;
+ default:
+ /*
+ * How did we get here?
+ */
+ XtWarning("XwStaticTextWidget: An Unknown Alignment has crept into the code\n");
+ break;
+ }
+
+ /*
+ * We don't want to lose the highlight on redisplay
+ * do we?
+ */
+ if (stw->primitive.highlighted)
+ {
+ _XwHighlightBorder(stw);
+ stw->primitive.display_highlighted = TRUE;
+ }
+ else
+ if (stw->primitive.display_highlighted)
+ {
+ _XwUnhighlightBorder(stw);
+ stw->primitive.display_highlighted = FALSE;
+ }
+
+}
+
+/*************************************<->*************************************
+ *
+ * static void Resize(stw)
+ * XwStaticTextWidget stw;
+ *
+ * Description:
+ * -----------
+ * See XToolKit Documentation
+ *
+ * Inputs:
+ * ------
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * SetSize
+ * XSetClipRectangles
+ *
+ *************************************<->***********************************/
+static void Resize(stw)
+ XwStaticTextWidget stw;
+{
+ XRectangle ClipRect;
+
+ /*
+ * Same as at initialization except just look at the new widget.
+ */
+ SetSize(stw);
+
+ if (XtIsRealized((Widget)stw))
+ {
+ /*
+ * Set the Clip Region.
+ */
+ ClipRect.width = stw->core.width -
+ (2 * (stw->static_text.internal_width +
+ stw->primitive.highlight_thickness));
+ ClipRect.height = stw->core.height -
+ (2 * (stw->static_text.internal_height +
+ stw->primitive.highlight_thickness));
+ ClipRect.x = stw->primitive.highlight_thickness +
+ stw->static_text.internal_width;
+ ClipRect.y = stw->primitive.highlight_thickness +
+ stw->static_text.internal_height;
+
+ XSetClipRectangles(XtDisplay(stw),stw->static_text.normal_GC,
+ 0,0, &ClipRect,1,Unsorted);
+ }
+}
+
+
+
+
+/****************************************************************
+ *
+ * Event Routines.
+ *
+ * Select - Call the callback when the left button goes down.
+ *
+ * Release - Call the callback when the left button goes up.
+ *
+ ****************************************************************/
+
+static void Select(w,event)
+ XwStaticTextWidget w;
+ XEvent *event;
+{
+ XtCallCallbacks((Widget)w,XtNselect,event);
+}
+
+static void Release(w,event)
+ XwStaticTextWidget w;
+ XEvent *event;
+{
+ XtCallCallbacks((Widget)w,XtNrelease,event);
+}
+
+static void Toggle(w,event)
+ XwStaticTextWidget w;
+ XEvent *event;
+{
+}
diff --git a/Xw/SText.h b/Xw/SText.h
new file mode 100644
index 0000000..0572f8d
--- /dev/null
+++ b/Xw/SText.h
@@ -0,0 +1,39 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: SText.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for StaticText class widgets
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/***********************************************************************
+ *
+ * StaticText Widget
+ *
+ ***********************************************************************/
+
+extern WidgetClass XwstatictextWidgetClass;
+/* synonym added for consistent naming conventions */
+extern WidgetClass XwstaticTextWidgetClass;
+
+typedef struct _XwStaticTextClassRec *XwStaticTextWidgetClass;
+typedef struct _XwStaticTextRec *XwStaticTextWidget;
+
diff --git a/Xw/STextP.h b/Xw/STextP.h
new file mode 100644
index 0000000..70fa5e4
--- /dev/null
+++ b/Xw/STextP.h
@@ -0,0 +1,89 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: STextP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for StaticText class
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+
+/********************************************
+ *
+ * No new fields need to be defined
+ * for the StaticText widget class record
+ *
+ ********************************************/
+typedef struct {int foo;} XwStaticTextClassPart;
+
+/****************************************************
+ *
+ * Full class record declaration for StaticText class
+ *
+ ****************************************************/
+typedef struct _XwStaticTextClassRec {
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwStaticTextClassPart statictext_class;
+} XwStaticTextClassRec;
+
+/********************************************
+ *
+ * New fields needed for instance record
+ *
+ ********************************************/
+typedef struct _XwStaticTextPart {
+ /*
+ * "Public" members (Can be set by resource manager).
+ */
+ char *input_string; /* String sent to this widget. */
+ XwAlignment alignment; /* Alignment within the box */
+ int gravity; /* Controls use of extra space in window */
+ Boolean wrap; /* Controls wrapping on spaces */
+ Boolean strip; /* Controls stripping of blanks */
+ int line_space; /* Ratio of font height use as dead space
+ between lines. Can be less than zero
+ but not less than -1.0 */
+ XFontStruct *font; /* Font to write in. */
+ Dimension internal_height; /* Space from text to top and
+ bottom highlights */
+ Dimension internal_width; /* Space from left and right side highlights */
+ /*
+ * "Private" members -- values computed by
+ * XwStaticTextWidgetClass methods.
+ */
+ GC normal_GC; /* GC for text */
+ XRectangle TextRect; /* The bounding box of the text, or clip rectangle
+ of the window; whichever is smaller. */
+ char *output_string; /* input_string after formatting */
+} XwStaticTextPart;
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+typedef struct _XwStaticTextRec {
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwStaticTextPart static_text;
+} XwStaticTextRec;
+
diff --git a/Xw/SourceP.h b/Xw/SourceP.h
new file mode 100644
index 0000000..007613e
--- /dev/null
+++ b/Xw/SourceP.h
@@ -0,0 +1,57 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: SourceP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: private include file for TextEdit widget sources
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#ifndef _XwTextEditSourcePrivate_h
+#define _XwTextEditSourcePrivate_h
+
+#define applySource(method) (*(self->text.source->method))
+
+#define XwEstringSrc "stringsrc"
+#define XwEdiskSrc "disksrc"
+
+typedef struct _StringSourceData {
+ XwEditType editMode;
+ unsigned char *buffer;
+ unsigned char *initial_string;
+ XwTextPosition length, /* current data size of buffer */
+ buffer_size, /* storage size of buffer */
+ max_size; /* user specified buffer limit */
+ int max_size_flag; /* flag to test max_size set */
+} StringSourceData, *StringSourcePtr;
+
+
+#endif
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/Xw/SourceStr.c b/Xw/SourceStr.c
new file mode 100644
index 0000000..71c6bbc
--- /dev/null
+++ b/Xw/SourceStr.c
@@ -0,0 +1,374 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: SourceStr.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code for TextEdit widget string source
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <X11/Xlib.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/TextEdit.h>
+#include <Xw/TextEditP.h>
+#include <Xw/SourceP.h>
+
+/* Private StringSource Definitions */
+
+#define MAGICVALUE -1
+#define DEFAULTBUFFERSIZE 512
+
+
+#define Increment(data, position, direction)\
+{\
+ if (direction == XwsdLeft) {\
+ if (position > 0) \
+ position -= 1;\
+ }\
+ else {\
+ if (position < data->length)\
+ position += 1;\
+ }\
+}
+
+static long magic_value = MAGICVALUE;
+
+static XtResource stringResources[] = {
+ {XtNstring, XtCString, XtRString, sizeof (char *),
+ XtOffset(StringSourcePtr, initial_string), XtRString, NULL},
+ {XtNmaximumSize, XtCMaximumSize, XtRLong, sizeof (long),
+ XtOffset(StringSourcePtr, max_size), XtRLong, (caddr_t)&magic_value},
+ {XtNeditType, XtCEditType, XtREditMode, sizeof(XwEditType),
+ XtOffset(StringSourcePtr, editMode), XtRString, "edit"},
+};
+
+/*--------------------------------------------------------------------------+*/
+static unsigned char Look(data, position, direction)
+/*--------------------------------------------------------------------------+*/
+ StringSourcePtr data;
+ XwTextPosition position;
+ XwScanDirection direction;
+{
+/* Looking left at pos 0 or right at position data->length returns newline */
+ if (direction == XwsdLeft) {
+ if (position == 0)
+ return(0);
+ else
+ return(data->buffer[position-1]);
+ }
+ else {
+ if (position == data->length)
+ return(0);
+ else
+ return(data->buffer[position]);
+ }
+}
+
+/*--------------------------------------------------------------------------+*/
+static int StringReadText (src, pos, text, maxRead)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+ int pos;
+ XwTextBlock *text;
+ int maxRead;
+{
+ int charsLeft;
+ StringSourcePtr data;
+
+ data = (StringSourcePtr) src->data;
+ text->firstPos = pos;
+ text->ptr = data->buffer + pos;
+ charsLeft = data->length - pos;
+ text->length = (maxRead > charsLeft) ? charsLeft : maxRead;
+ return pos + text->length;
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwEditResult StringReplaceText (src, startPos, endPos, text, delta)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+ XwTextPosition startPos, endPos;
+ XwTextBlock *text;
+ int *delta;
+{
+ StringSourcePtr data;
+ int i, length;
+
+ data = (StringSourcePtr) src->data;
+ switch (data->editMode) {
+ case XwtextAppend:
+ if (startPos != endPos || endPos!= data->length)
+ return (XweditPosError);
+ break;
+ case XwtextRead:
+ return (XweditError);
+ case XwtextEdit:
+ break;
+ default:
+ return (XweditError);
+ }
+ length = endPos - startPos;
+ *delta = text->length - length;
+ if ((data->length + *delta) > data->buffer_size) {
+ if (data->max_size_flag)
+ return (XweditError);
+ else {
+ while ((data->length + *delta) > data->buffer_size)
+ data->buffer_size += DEFAULTBUFFERSIZE;
+ data->buffer = (unsigned char *)
+ XtRealloc(data->buffer, data->buffer_size);
+ }
+ };
+
+
+ if (*delta < 0) /* insert shorter than delete, text getting
+ shorter */
+ for (i = startPos; i < data->length + *delta; ++i)
+ data->buffer[i] = data->buffer[i - *delta];
+ else
+ if (*delta > 0) { /* insert longer than delete, text getting
+ longer */
+ for (i = data->length; i > startPos-1; --i)
+ data->buffer[i + *delta] = data->buffer[i];
+ }
+ if (text->length != 0) /* do insert */
+ for (i = 0; i < text->length; ++i)
+ data->buffer[startPos + i] = text->ptr[i];
+ data->length = data->length + *delta;
+ data->buffer[data->length] = 0;
+ return (XweditDone);
+}
+
+/*--------------------------------------------------------------------------+*/
+static StringSetLastPos (src, lastPos)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+ XwTextPosition lastPos;
+{
+ ((StringSourceData *) (src->data))->length = lastPos;
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwTextPosition StringGetLastPos (src)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+{
+ return( ((StringSourceData *) (src->data))->length );
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwTextPosition StringScan (src, pos, sType, dir, count, include)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+ XwTextPosition pos;
+ XwScanType sType;
+ XwScanDirection dir;
+ int count;
+ Boolean include;
+{
+ StringSourcePtr data;
+ XwTextPosition position;
+ int i, whiteSpace;
+ unsigned char c;
+ int ddir = (dir == XwsdRight) ? 1 : -1;
+
+ data = (StringSourcePtr) src->data;
+ position = pos;
+ switch (sType) {
+ case XwstPositions:
+ if (!include && count > 0)
+ count -= 1;
+ for (i = 0; i < count; i++) {
+ Increment(data, position, dir);
+ }
+ break;
+ case XwstWhiteSpace:
+
+ for (i = 0; i < count; i++) {
+ whiteSpace = -1;
+ while (position >= 0 && position <= data->length) {
+ c = Look(data, position, dir);
+ if ((c == ' ') || (c == '\t') || (c == '\n')){
+ if (whiteSpace < 0) whiteSpace = position;
+ } else if (whiteSpace >= 0)
+ break;
+ position += ddir;
+ }
+ }
+ if (!include) {
+ if(whiteSpace < 0 && dir == XwsdRight) whiteSpace = data->length;
+ position = whiteSpace;
+ }
+ break;
+ case XwstEOL:
+ for (i = 0; i < count; i++) {
+ while (position >= 0 && position <= data->length) {
+ if (Look(data, position, dir) == '\n')
+ break;
+ if(((dir == XwsdRight) && (position == data->length)) ||
+ (dir == XwsdLeft) && ((position == 0)))
+ break;
+ Increment(data, position, dir);
+ }
+ if (i + 1 != count)
+ Increment(data, position, dir);
+ }
+ if (include) {
+ /* later!!!check for last char in file # eol */
+ Increment(data, position, dir);
+ }
+ break;
+ case XwstLast:
+ if (dir == XwsdLeft)
+ position = 0;
+ else
+ position = data->length;
+ }
+ if (position < 0) position = 0;
+ if (position > data->length) position = data->length;
+ return(position);
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwEditType StringGetEditType(src)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+{
+ StringSourcePtr data;
+ data = (StringSourcePtr) src->data;
+ return(data->editMode);
+}
+
+/*--------------------------------------------------------------------------+*/
+static Boolean XwStringSourceCheckData(src)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+{ int initial_size = 0;
+ StringSourcePtr data = (StringSourcePtr)src->data;
+
+ data->max_size_flag = (data->max_size != MAGICVALUE);
+
+ if (data->initial_string == NULL) {
+ if (data->max_size_flag)
+ data->buffer_size = data->max_size;
+ else
+ data->buffer_size = DEFAULTBUFFERSIZE;
+ if (!data->buffer) data->length = 0;
+ }
+ else {
+ initial_size = XwStrlen(data->initial_string);
+ if (data->max_size_flag) {
+ if (data->max_size < initial_size) {
+ XtWarning("Initial string size larger than XtNmaximumSize");
+ data->max_size = initial_size;
+ }
+ data->buffer_size = data->max_size;
+ }
+ else {
+ data->buffer_size =
+ (initial_size < DEFAULTBUFFERSIZE) ? DEFAULTBUFFERSIZE :
+ ((initial_size / DEFAULTBUFFERSIZE) + 1) * DEFAULTBUFFERSIZE;
+ };
+ data->length = initial_size;
+ };
+
+ if (data->buffer && initial_size)
+ data->buffer =
+ (unsigned char *) XtRealloc(data->buffer, data->buffer_size);
+ else if (!data->buffer)
+ data->buffer = (unsigned char *) XtMalloc(data->buffer_size);
+
+ if (initial_size) {
+ strcpy(data->buffer, data->initial_string);
+ data->initial_string = NULL;
+ }
+}
+
+/***** Public routines *****/
+
+/*--------------------------------------------------------------------------+*/
+void XwStringSourceDestroy (src)
+/*--------------------------------------------------------------------------+*/
+ XwTextSource *src;
+{
+ XtFree((char *) src->data);
+ XtFree((char *) src);
+}
+
+/*--------------------------------------------------------------------------+*/
+XwTextSource *XwStringSourceCreate (w, args, argCount)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ ArgList args;
+ int argCount;
+{
+ XwTextSource *src;
+ StringSourcePtr data;
+
+
+ src = XtNew(XwTextSource);
+ src->read = StringReadText;
+ src->replace = StringReplaceText;
+ src->setLastPos = StringSetLastPos;
+ src->getLastPos = StringGetLastPos;
+ src->scan = StringScan;
+ src->editType = StringGetEditType;
+ src->resources = stringResources;
+ src->resource_num = XtNumber(stringResources);
+ src->check_data = XwStringSourceCheckData;
+ src->destroy = XwStringSourceDestroy;
+ data = XtNew(StringSourceData);
+ data->editMode = XwtextRead;
+ data->buffer = NULL;
+ data->initial_string = NULL;
+ data->length = 0;
+ data->buffer_size = 0;
+ data->max_size = 0;
+ data->max_size_flag = 0;
+ src->data = (int *)data;
+
+ /* Use the name given to the TextEdit widget this source will go with.
+ This could be a problem if we allow multiple views on one source */
+
+ XtGetSubresources (w, data, XtNstringSrc, "StringSrc",
+ stringResources, XtNumber(stringResources), args, argCount);
+
+ src->data = (int *) (data);
+
+ XwStringSourceCheckData(src);
+
+ return src;
+}
+
diff --git a/Xw/TextEdit.c b/Xw/TextEdit.c
new file mode 100644
index 0000000..f94bcd9
--- /dev/null
+++ b/Xw/TextEdit.c
@@ -0,0 +1,2503 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: TextEdit.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code for TextEdit widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#include <stdio.h>
+#ifdef SYSV
+#include <fcntl.h>
+#include <string.h>
+#else
+#include <strings.h>
+#endif /* SYSV */
+#include <X11/Xos.h>
+
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+
+#include <Xw/TextEdit.h>
+#include <Xw/TextEditP.h>
+#include <X11/Xutil.h> /* This include depends on something above it */
+
+#define BufMax 1000
+#define abs(x) (((x) < 0) ? (-(x)) : (x))
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#define GETLASTPOS(ctx) ((*(ctx->text.source->getLastPos)) (ctx->text.source))
+
+#define BUTTONMASK 0x143d
+
+#define zeroPosition ((XwTextPosition) 0)
+
+/******************************************************************************
+*
+* Resources for TextEdit
+*
+******************************************************************************/
+
+static XtResource resources[] = {
+/* Resources from other classes with new defaults */
+ {XtNheight,
+ XtCHeight,
+ XtRDimension,
+ sizeof(Dimension),
+ XtOffset(XwTextEditWidget, core.height),
+ XtRString,
+ "200"},
+ {XtNwidth,
+ XtCWidth,
+ XtRDimension,
+ sizeof(Dimension),
+ XtOffset(XwTextEditWidget, core.width),
+ XtRString,
+ "200"},
+/* New resources for TextEdit */
+ {XtNdisplayPosition,
+ XtCTextPosition,
+ XtRInt,
+ sizeof (XwTextPosition),
+ XtOffset(XwTextEditWidget, text.lt.top),
+ XtRString, "0"},
+ {XtNinsertPosition,
+ XtCTextPosition,
+ XtRInt,
+ sizeof(XwTextPosition),
+ XtOffset(XwTextEditWidget, text.insertPos),
+ XtRString,
+ "0"},
+ {XtNleftMargin,
+ XtCMargin,
+ XtRDimension,
+ sizeof (Dimension),
+ XtOffset(XwTextEditWidget, text.leftmargin),
+ XtRString,
+ "2"},
+ {XtNrightMargin,
+ XtCMargin,
+ XtRDimension,
+ sizeof (Dimension),
+ XtOffset(XwTextEditWidget, text.rightmargin),
+ XtRString,
+ "2"},
+ {XtNtopMargin,
+ XtCMargin,
+ XtRDimension,
+ sizeof (Dimension),
+ XtOffset(XwTextEditWidget, text.topmargin),
+ XtRString,
+ "2"},
+ {XtNbottomMargin,
+ XtCMargin,
+ XtRDimension,
+ sizeof (Dimension),
+ XtOffset(XwTextEditWidget, text.bottommargin),
+ XtRString,
+ "2"},
+ {XtNsourceType,
+ XtCSourceType,
+ XtRSourceType,
+ sizeof(XwSourceType),
+ XtOffset(XwTextEditWidget, text.srctype),
+ XtRString,
+ "stringsrc"},
+ {XtNtextSource,
+ XtCTextSource,
+ XtRPointer,
+ sizeof (caddr_t),
+ XtOffset(XwTextEditWidget, text.source),
+ XtRPointer,
+ NULL},
+ {XtNselection,
+ XtCSelection,
+ XtRPointer,
+ sizeof(caddr_t),
+ XtOffset(XwTextEditWidget, text.s),
+ XtRPointer,
+ NULL},
+ {XtNmotionVerification,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtCallbackProc),
+ XtOffset(XwTextEditWidget, text.motion_verification),
+ XtRCallback,
+ (caddr_t) NULL},
+ {XtNmodifyVerification,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtCallbackProc),
+ XtOffset(XwTextEditWidget, text.modify_verification),
+ XtRCallback,
+ (caddr_t) NULL},
+ {XtNleaveVerification,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtCallbackProc),
+ XtOffset(XwTextEditWidget, text.leave_verification),
+ XtRCallback,
+ (caddr_t) NULL},
+ {XtNexecute,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtCallbackProc),
+ XtOffset(XwTextEditWidget, text.execute),
+ XtRCallback,
+ (caddr_t) NULL},
+ {XtNwrap,
+ XtCWrap,
+ XtRWrap,
+ sizeof (XwWrap),
+ XtOffset (XwTextEditWidget, text.wrap_mode),
+ XtRString,
+ "softwrap"},
+ {XtNwrapForm,
+ XtCWrapForm,
+ XtRWrapForm,
+ sizeof (XwWrapForm),
+ XtOffset (XwTextEditWidget, text.wrap_form),
+ XtRString,
+ "sourceform"},
+ {XtNwrapBreak,
+ XtCWrapBreak,
+ XtRWrapBreak,
+ sizeof (XwWrapBreak),
+ XtOffset (XwTextEditWidget, text.wrap_break),
+ XtRString,
+ "wrapwhitespace"},
+ {XtNscroll,
+ XtCScroll,
+ XtRScroll,
+ sizeof (XwScroll),
+ XtOffset (XwTextEditWidget, text.scroll_mode),
+ XtRString,
+ "autoscrolloff"},
+ {XtNgrow,
+ XtCGrow,
+ XtRGrow,
+ sizeof (XwGrow),
+ XtOffset (XwTextEditWidget, text.grow_mode),
+ XtRString,
+ "growoff"},
+};
+
+
+/******************************************************************************
+*
+* Forward declarations of functions to put into the class record
+*
+******************************************************************************/
+static void Initialize();
+static void Realize();
+static void TextDestroy();
+static void Resize();
+static void ProcessExposeRegion();
+static Boolean SetValues();
+static unsigned char* _XwTextCopySubString();
+
+/******************************************************************************
+*
+* Forward declarations of action functions to put into the action table
+*
+******************************************************************************/
+static void TraverseUp();
+static void TraverseDown();
+static void TraverseLeft();
+static void TraverseRight();
+static void TraverseNext();
+static void TraversePrev();
+static void TraverseHome();
+static void TraverseNextTop();
+static void Enter();
+static void Leave();
+static void Execute();
+static void RedrawDisplay();
+static void InsertChar();
+static void TextFocusIn();
+static void TextFocusOut();
+static void MoveForwardChar();
+static void MoveBackwardChar();
+static void MoveForwardWord();
+static void MoveBackwardWord();
+static void MoveForwardParagraph();
+static void MoveBackwardParagraph();
+static void MoveToLineStart();
+static void MoveToLineEnd();
+static void MoveNextLine();
+static void MovePreviousLine();
+static void MoveNextPage();
+static void MovePreviousPage();
+static void MoveBeginningOfFile();
+static void MoveEndOfFile();
+static void ScrollOneLineUp();
+static void ScrollOneLineDown();
+static void DeleteForwardChar();
+static void DeleteBackwardChar();
+static void DeleteBackwardNormal();
+static void DeleteForwardWord();
+static void DeleteBackwardWord();
+static void DeleteCurrentSelection();
+static void KillForwardWord();
+static void KillBackwardWord();
+static void KillCurrentSelection();
+static void KillToEndOfLine();
+static void KillToEndOfParagraph();
+static void UnKill();
+static void Stuff();
+static void InsertNewLineAndIndent();
+static void InsertNewLineAndBackup();
+static XwEditResult InsertNewLine();
+static void SelectWord();
+static void SelectAll();
+static void SelectStart();
+static void SelectAdjust();
+static void SelectEnd();
+static void ExtendStart();
+static void ExtendAdjust();
+static void ExtendEnd();
+
+/******************************************************************************
+*
+* TextEdit Actions Table
+*
+******************************************************************************/
+XtActionsRec texteditActionsTable [] = {
+/* motion bindings */
+ {"forward-character", MoveForwardChar},
+ {"backward-character", MoveBackwardChar},
+ {"forward-word", MoveForwardWord},
+ {"backward-word", MoveBackwardWord},
+ {"forward-paragraph", MoveForwardParagraph},
+ {"backward-paragraph", MoveBackwardParagraph},
+ {"beginning-of-line", MoveToLineStart},
+ {"end-of-line", MoveToLineEnd},
+ {"next-line", MoveNextLine},
+ {"previous-line", MovePreviousLine},
+ {"next-page", MoveNextPage},
+ {"previous-page", MovePreviousPage},
+ {"beginning-of-file", MoveBeginningOfFile},
+ {"end-of-file", MoveEndOfFile},
+ {"scroll-one-line-up", ScrollOneLineUp},
+ {"scroll-one-line-down", ScrollOneLineDown},
+/* delete bindings */
+ {"delete-next-character", DeleteForwardChar},
+ {"delete-previous-character", DeleteBackwardNormal},
+ {"delete-next-word", DeleteForwardWord},
+ {"delete-previous-word", DeleteBackwardWord},
+ {"delete-selection", DeleteCurrentSelection},
+/* kill bindings */
+ {"kill-word", KillForwardWord},
+ {"backward-kill-word", KillBackwardWord},
+ {"kill-selection", KillCurrentSelection},
+ {"kill-to-end-of-line", KillToEndOfLine},
+ {"kill-to-end-of-paragraph", KillToEndOfParagraph},
+/* unkill bindings */
+ {"unkill", UnKill},
+ {"stuff", Stuff},
+/* new line stuff */
+ {"newline-and-indent", InsertNewLineAndIndent},
+ {"newline-and-backup", InsertNewLineAndBackup},
+ {"newline", (XtActionProc)InsertNewLine},
+/* Selection stuff */
+ {"select-word", SelectWord},
+ {"select-all", SelectAll},
+ {"select-start", SelectStart},
+ {"select-adjust", SelectAdjust},
+ {"select-end", SelectEnd},
+ {"extend-start", ExtendStart},
+ {"extend-adjust", ExtendAdjust},
+ {"extend-end", ExtendEnd},
+/* Miscellaneous */
+ {"redraw-display", RedrawDisplay},
+ {"insert-char", InsertChar},
+ {"focus-in", TextFocusIn},
+ {"focus-out", TextFocusOut},
+/* traversal direction functions */
+ {"traverse-left", TraverseLeft},
+ {"traverse-right", TraverseRight},
+ {"traverse-next", TraverseNext},
+ {"traverse-prev", TraversePrev},
+ {"traverse-up", TraverseUp},
+ {"traverse-down", TraverseDown},
+ {"traverse-home", TraverseHome},
+ {"traverse-next-top", TraverseNextTop},
+/* highlighting */
+ {"enter", Enter},
+ {"leave", Leave},
+ {"execute", Execute},
+ {NULL,NULL}
+};
+
+/****************************************************************************
+*
+* TextEdit Default Event Translations
+*
+****************************************************************************/
+char defaultTextEditTranslations[] =
+ "Ctrl<Key>F: forward-character()\n\
+ Ctrl<Key>Right: traverse-right()\n\
+ <Key>Right: forward-character()\n\
+ Ctrl<Key>B: backward-character()\n\
+ Ctrl<Key>Left: traverse-left()\n\
+ <Key>Left: backward-character()\n\
+ Meta<Key>F: forward-word()\n\
+ Meta<Key>B: backward-word()\n\
+ Meta<Key>]: forward-paragraph()\n\
+ Ctrl<Key>[: backward-paragraph()\n\
+ Ctrl<Key>A: beginning-of-line()\n\
+ Ctrl<Key>E: end-of-line()\n\
+ Ctrl<Key>N: next-line()\n\
+ Ctrl<Key>Down: traverse-down()\n\
+ <Key>Down: next-line()\n\
+ Ctrl<Key>P: previous-line()\n\
+ Ctrl<Key>Up: traverse-up()\n\
+ <Key>Up: previous-line()\n\
+ Ctrl<Key>V: next-page()\n\
+ Ctrl<Key>Next: traverse-next()\n\
+ <Key>Next: next-page()\n\
+ Meta<Key>V: previous-page()\n\
+ Ctrl<Key>Prior: traverse-prev()\n\
+ <Key>Prior: previous-page()\n\
+ Meta<Key>\\<: beginning-of-file()\n\
+ Meta<Key>\\>: end-of-file()\n\
+ Ctrl<Key>Home: traverse-home()\n\
+ Shift<Key>Home: end-of-file()\n\
+ <Key>Home: beginning-of-file()\n\
+ Ctrl<Key>Z: scroll-one-line-up()\n\
+ Meta<Key>Z: scroll-one-line-down()\n\
+ Ctrl<Key>D: delete-next-character()\n\
+ <Key>Delete: delete-previous-character()\n\
+ <Key>BackSpace: delete-previous-character()\n\
+ Ctrl<Key>H: delete-previous-character()\n\
+ Meta<Key>D: delete-next-word()\n\
+ Meta<Key>H: delete-previous-word()\n\
+ Shift Meta<Key>D: kill-word()\n\
+ Shift Meta<Key>H: backward-kill-word()\n\
+ Ctrl<Key>W: kill-selection()\n\
+ Ctrl<Key>K: kill-to-end-of-line()\n\
+ Meta<Key>K: kill-to-end-of-paragraph()\n\
+ Ctrl<Key>Y: unkill()\n\
+ Meta<Key>Y: stuff()\n\
+ Ctrl<Key>J: newline-and-indent()\n\
+ Ctrl<Key>O: newline-and-backup()\n\
+ Ctrl<Key>M: newline()\n\
+ <Key>Return: newline()\n\
+ <Key>Linefeed: newline-and-indent()\n\
+ Ctrl<Key>L: redraw-display()\n\
+ <FocusIn>: focus-in()\n\
+ <FocusOut>: focus-out()\n\
+ <Btn1Down>: select-start()\n\
+ Button1<PtrMoved>: extend-adjust()\n\
+ <Btn1Up>: extend-end()\n\
+ <Btn2Down>: stuff()\n\
+ <Btn3Down>: extend-start()\n\
+ Button3<PtrMoved>: extend-adjust()\n\
+ <Btn3Up>: extend-end()\n\
+ <Key>Execute: execute()\n\
+ <Key>: insert-char()\n\
+ Shift<Key>: insert-char()\n\
+ <EnterWindow>: enter()\n\
+ <LeaveWindow>: leave()";
+
+
+/* Utility routines for support of TextEdit */
+#include "sub.c"
+
+/******************************************************************************
+*
+* Functions to support selection
+*
+******************************************************************************/
+/*--------------------------------------------------------------------------+*/
+static void _XtTextSetNewSelection(ctx, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition left, right;
+{
+ XwTextPosition pos;
+
+ if (left < ctx->text.s.left) {
+ pos = min(right, ctx->text.s.left);
+ _XtTextNeedsUpdating(ctx, left, pos);
+ }
+ if (left > ctx->text.s.left) {
+ pos = min(left, ctx->text.s.right);
+ _XtTextNeedsUpdating(ctx, ctx->text.s.left, pos);
+ }
+ if (right < ctx->text.s.right) {
+ pos = max(right, ctx->text.s.left);
+ _XtTextNeedsUpdating(ctx, pos, ctx->text.s.right);
+ }
+ if (right > ctx->text.s.right) {
+ pos = max(left, ctx->text.s.right);
+ _XtTextNeedsUpdating(ctx, pos, right);
+ }
+
+ ctx->text.s.left = left;
+ ctx->text.s.right = right;
+}
+
+
+/*
+ * This routine implements multi-click selection in a hardwired manner.
+ * It supports multi-click entity cycling (char, word, line, file) and mouse
+ * motion adjustment of the selected entitie (i.e. select a word then, with
+ * button still down, adjust wich word you really meant by moving the mouse).
+ * [NOTE: This routine is to be replaced by a set of procedures that
+ * will allows clients to implements a wide class of draw through and
+ * multi-click selection user interfaces.]
+*/
+/*--------------------------------------------------------------------------+*/
+static void DoSelection (ctx, position, time, motion)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition position;
+ Time time;
+ Boolean motion;
+{
+ int delta;
+ XwTextPosition newLeft, newRight;
+ XwSelectType newType;
+ XwSelectType *sarray;
+
+ delta = (time < ctx->text.lasttime) ?
+ ctx->text.lasttime - time : time - ctx->text.lasttime;
+ if (motion)
+ newType = ctx->text.s.type;
+ else {/* multi-click event */
+ if ((delta < 500) && ((position >= ctx->text.s.left)
+ && (position <= ctx->text.s.right))) {
+ sarray = ctx->text.sarray;
+ for (sarray = ctx->text.sarray;
+ *sarray != XwselectNull && *sarray != ctx->text.s.type;
+ sarray++) ;
+ if (*sarray != XwselectNull) sarray++;
+ if (*sarray == XwselectNull) sarray = ctx->text.sarray;
+ newType = *sarray;
+ } else { /* single-click event */
+ newType = *(ctx->text.sarray);
+ }
+ ctx->text.lasttime = time;
+ }
+ switch (newType) {
+ case XwselectPosition:
+ newLeft = newRight = position;
+ break;
+ case XwselectChar:
+ newLeft = position;
+ newRight = (*(ctx->text.source->scan))(
+ ctx->text.source, position, position, XwsdRight, 1, FALSE);
+ break;
+ case XwselectWord:
+ newLeft = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstWhiteSpace, XwsdLeft, 1, FALSE);
+ newRight = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstWhiteSpace, XwsdRight, 1, FALSE);
+ break;
+ case XwselectLine:
+ case XwselectParagraph: /* need "para" scan mode to implement pargraph */
+ newLeft = (*(ctx->text.source->scan))(
+ ctx->text.source, position, XwstEOL, XwsdLeft, 1, FALSE);
+ newRight = (*(ctx->text.source->scan))(
+ ctx->text.source, position, XwstEOL, XwsdRight, 1, FALSE);
+ break;
+ case XwselectAll:
+ newLeft = (*(ctx->text.source->scan))(
+ ctx->text.source, position, XwstLast, XwsdLeft, 1, FALSE);
+ newRight = (*(ctx->text.source->scan))(
+ ctx->text.source, position, XwstLast, XwsdRight, 1, FALSE);
+ break;
+ default:
+ break;
+ }
+ if ((newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right)
+ || (newType != ctx->text.s.type)) {
+ _XtTextSetNewSelection(ctx, newLeft, newRight);
+ ctx->text.s.type = newType;
+ if (position - ctx->text.s.left < ctx->text.s.right - position)
+ ctx->text.insertPos = newLeft;
+ else
+ ctx->text.insertPos = newRight;
+ }
+ if (!motion) { /* setup so we can freely mix select extend calls*/
+ ctx->text.origSel.type = ctx->text.s.type;
+ ctx->text.origSel.left = ctx->text.s.left;
+ ctx->text.origSel.right = ctx->text.s.right;
+ if (position >= ctx->text.s.left +
+ ((ctx->text.s.right - ctx->text.s.left) / 2))
+ ctx->text.extendDir = XwsdRight;
+ else
+ ctx->text.extendDir = XwsdLeft;
+ }
+}
+
+/*
+ * This routine implements extension of the currently selected text in
+ * the "current" mode (i.e. char word, line, etc.). It worries about
+ * extending from either end of the selection and handles the case when you
+ * cross through the "center" of the current selection (e.g. switch which
+ * end you are extending!).
+ * [NOTE: This routine will be replaced by a set of procedures that
+ * will allows clients to implements a wide class of draw through and
+ * multi-click selection user interfaces.]
+*/
+/*--------------------------------------------------------------------------+*/
+static void ExtendSelection (ctx, position, motion)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition position;
+ Boolean motion;
+{
+ XwTextPosition newLeft, newRight;
+
+
+ if (!motion) { /* setup for extending selection */
+ ctx->text.origSel.type = ctx->text.s.type;
+ ctx->text.origSel.left = ctx->text.s.left;
+ ctx->text.origSel.right = ctx->text.s.right;
+ if (position >= ctx->text.s.left +
+ ((ctx->text.s.right - ctx->text.s.left) / 2))
+ ctx->text.extendDir = XwsdRight;
+ else
+ ctx->text.extendDir = XwsdLeft;
+ }
+ else /* check for change in extend direction */
+ if ((ctx->text.extendDir == XwsdRight &&
+ position < ctx->text.origSel.left) ||
+ (ctx->text.extendDir == XwsdLeft &&
+ position > ctx->text.origSel.right)) {
+ ctx->text.extendDir =
+ (ctx->text.extendDir == XwsdRight)? XwsdLeft : XwsdRight;
+ _XtTextSetNewSelection(ctx, ctx->text.origSel.left,
+ ctx->text.origSel.right);
+ }
+ newLeft = ctx->text.s.left;
+ newRight = ctx->text.s.right;
+ switch (ctx->text.s.type) {
+ case XwselectPosition:
+ if (ctx->text.extendDir == XwsdRight)
+ newRight = position;
+ else
+ newLeft = position;
+ break;
+ case XwselectWord:
+ if (ctx->text.extendDir == XwsdRight)
+ newRight = position = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstWhiteSpace, XwsdRight, 1, FALSE);
+ else
+ newLeft = position = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstWhiteSpace, XwsdLeft, 1, FALSE);
+ break;
+ case XwselectLine:
+ case XwselectParagraph: /* need "para" scan mode to implement pargraph */
+ if (ctx->text.extendDir == XwsdRight)
+ newRight = position = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstEOL, XwsdRight, 1, TRUE);
+ else
+ newLeft = position = (*(ctx->text.source->scan))
+ (ctx->text.source, position, XwstEOL, XwsdLeft, 1, FALSE);
+ break;
+ case XwselectAll:
+ position = ctx->text.insertPos;
+ break;
+ default:
+ break;
+ }
+ _XtTextSetNewSelection(ctx, newLeft, newRight);
+ ctx->text.insertPos = position;
+}
+
+
+/*
+ * This routine is used to perform various selection functions. The goal is
+ * to be able to specify all the more popular forms of draw-through and
+ * multi-click selection user interfaces from the outside.
+ */
+/*--------------------------------------------------------------------------+*/
+static void AlterSelection (ctx, mode, action)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwSelectionMode mode; /* {XwsmTextSelect, XwsmTextExtend} */
+ XwSelectionAction action; /* {XwactionStart, XwactionAdjust, XwactionEnd} */
+{
+ XwTextPosition position;
+ unsigned char *ptr;
+
+ position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
+ if (action == XwactionStart) {
+ switch (mode) {
+ case XwsmTextSelect:
+ DoSelection (ctx, position, ctx->text.time, FALSE);
+ break;
+ case XwsmTextExtend:
+ ExtendSelection (ctx, position, FALSE);
+ break;
+ }
+ }
+ else {
+ switch (mode) {
+ case XwsmTextSelect:
+ DoSelection (ctx, position, ctx->text.time, TRUE);
+ break;
+ case XwsmTextExtend:
+ ExtendSelection (ctx, position, TRUE);
+ break;
+ }
+ }
+ if (action == XwactionEnd && ctx->text.s.left < ctx->text.s.right) {
+ ptr = _XwTextCopySubString (ctx, ctx->text.s.left, ctx->text.s.right);
+ XStoreBuffer (XtDisplay(ctx), ptr, min (XwStrlen (ptr), MAXCUT), 0);
+ XtFree (ptr);
+ }
+}
+
+/******************************************************************************
+*
+* TextEdit Class Methods
+*
+******************************************************************************/
+
+/*****************************************************************************
+* This method deletes the text from startPos to endPos in a source and
+* then inserts, at startPos, the text that was passed. As a side effect it
+* "invalidates" that portion of the displayed text (if any), so that things
+* will be repainted properly.
+******************************************************************************/
+
+/*--------------------------------------------------------------------------+*/
+static int _XwTextSubString(ctx, left, right, target, size, used)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition left, right;
+ unsigned char *target; /* Memory to copy into */
+ int size, /* Size of memory */
+ *used; /* Memory used by copy */
+{
+ unsigned char *tempResult;
+ int length, n;
+ XwTextBlock text;
+ XwTextPosition end, nend;
+
+ end = (*(ctx->text.source->read))(ctx->text.source, left, &text,
+ right - left);
+ n = length = min(text.length,size);
+ strncpy(target, text.ptr, n);
+ while (n && (end < right) && (length < size)) {
+ nend = (*(ctx->text.source->read))(ctx->text.source, end, &text,
+ right - end);
+ n = text.length;
+ if (length + n > size) n = size - length;
+ tempResult = target + length;
+ strncpy(tempResult, text.ptr, n);
+ length += n;
+ end = nend;
+ }
+ *used = length;
+ return length; /* return the number of positions transfered to target */
+}
+
+/*--------------------------------------------------------------------------+*/
+static unsigned char *_XwTextCopySubString(ctx, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition left, right;
+{
+ unsigned char *result;
+ int length, resultLength;
+ int dummy;
+
+ resultLength = right - left + 10; /* Bogus? %%% */
+ result = (unsigned char *)XtMalloc((unsigned) resultLength);
+
+ length = _XwTextSubString(ctx, left, right, result, resultLength, &dummy);
+
+ result[length] = 0;
+ return result;
+}
+
+/*--------------------------------------------------------------------------+*/
+static unsigned char *_XwTextCopySelection(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ return( _XwTextCopySubString(ctx, ctx->text.s.left, ctx->text.s.right));
+}
+
+/*--------------------------------------------------------------------------+*/
+static void _XwTextSetSelection(w, left, right)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ Position left, right;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+
+ _XtTextPrepareToUpdate(ctx);
+ _XtTextSetNewSelection(ctx, (XwTextPosition)left, (XwTextPosition)right);
+ _XtTextExecuteUpdate(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void _XwTextUnsetSelection(w)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+
+ _XtTextPrepareToUpdate(ctx);
+ _XtTextSetNewSelection(ctx, zeroPosition, zeroPosition);
+ _XtTextExecuteUpdate(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwEditResult _XwTextReplace(w, startPos, endPos, text, verify)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XwTextPosition startPos, endPos;
+ XwTextBlock *text;
+ Boolean verify;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+ XwEditResult result;
+
+ _XtTextPrepareToUpdate(ctx);
+ result = ReplaceText(ctx, startPos, endPos, text, verify);
+ _XtTextExecuteUpdate(ctx);
+ return result;
+}
+
+/*--------------------------------------------------------------------------+*/
+static void _XwTextRedraw (w)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+
+ _XtTextPrepareToUpdate(ctx);
+ ForceBuildLineTable(ctx);
+ DisplayAllText(ctx);
+ _XtTextExecuteUpdate(ctx);
+ if (ctx->primitive.highlighted)
+ _XwHighlightBorder(ctx);
+}
+
+
+/******************************************************************************
+*
+* Utilities
+*
+******************************************************************************/
+/*--------------------------------------------------------------------------+*/
+static XwEditResult _XwSetCursorPos(ctx, newposition)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition newposition;
+{
+ XwTextVerifyCD cbdata;
+
+ cbdata.operation = motionVerify;
+ cbdata.doit = TRUE;
+ cbdata.currInsert = ctx->text.insertPos;
+ cbdata.newInsert = newposition;
+
+ XtCallCallbacks((Widget)ctx, XtNmotionVerification, &cbdata);
+
+ if (!cbdata.doit) return XweditReject;
+
+ ctx->text.insertPos = cbdata.newInsert;
+
+ return XweditDone;
+}
+
+/*--------------------------------------------------------------------------+*/
+static void StartAction(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ _XtTextPrepareToUpdate(ctx);
+ if (event) {
+ ctx->text.time = event->xbutton.time;
+ ctx->text.ev_x = event->xbutton.x;
+ ctx->text.ev_y = event->xbutton.y;
+ }
+}
+
+/*--------------------------------------------------------------------------+*/
+static void EndAction(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ CheckResizeOrOverflow(ctx);
+ _XtTextExecuteUpdate(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteOrKill(ctx, from, to, kill)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition from, to;
+ Boolean kill;
+{
+ XwTextBlock text;
+ unsigned char *ptr;
+ XwEditResult result;
+
+ if (kill && from < to)
+ ptr = _XwTextCopySubString(ctx, from, to);
+
+ text.length = 0;
+
+ if (result = ReplaceText(ctx, from, to, &text, TRUE)) {
+ if (result != XweditReject)
+ XBell(XtDisplay(ctx), 50);
+ if (kill && from < to)
+ XtFree(ptr);
+ return;
+ }
+
+ if (kill && from < to) {
+ XStoreBuffer(XtDisplay(ctx), ptr, XwStrlen(ptr), 1);
+ XtFree(ptr);
+ }
+ _XwSetCursorPos(ctx, from);
+ ctx->text.showposition = TRUE;
+
+ from = ctx->text.insertPos;
+ _XtTextSetNewSelection(ctx, from, from);
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static void StuffFromBuffer(ctx, buffer)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ int buffer;
+{
+ extern char *XFetchBuffer();
+ XwTextBlock text;
+ XwEditResult result;
+ XwTextPosition nextcursorpos;
+
+ text.ptr =
+ (unsigned char*)XFetchBuffer(XtDisplay(ctx), &(text.length), buffer);
+ if (result =
+ ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
+ &text, TRUE)) {
+ if (result != XweditReject)
+ XBell(XtDisplay(ctx), 50);
+ XtFree(text.ptr);
+ return;
+ }
+ nextcursorpos = (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdRight,
+ text.length, TRUE);
+ _XwSetCursorPos(ctx, nextcursorpos);
+ nextcursorpos = ctx->text.insertPos;
+ _XtTextSetNewSelection(ctx, nextcursorpos, nextcursorpos);
+ XtFree(text.ptr);
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwTextPosition NextPosition(ctx, position, kind, direction)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition position;
+ XwScanType kind;
+ XwScanDirection direction;
+{
+ XwTextPosition pos;
+
+ pos = (*(ctx->text.source->scan))(
+ ctx->text.source, position, kind, direction, 1, FALSE);
+ if (pos == ctx->text.insertPos)
+ pos = (*(ctx->text.source->scan))(
+ ctx->text.source, position, kind, direction, 2, FALSE);
+ return pos;
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwEditResult InsertNewLineAndBackupInternal(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ XwTextBlock text;
+ XwEditResult result;
+
+ text.length = 1;
+ text.ptr = (unsigned char*)"\n";
+ text.firstPos = 0;
+ if (result =
+ ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
+ &text, TRUE)) {
+ if (result != XweditReject)
+ XBell( XtDisplay(ctx), 50);
+ return(result);
+ }
+ _XtTextSetNewSelection(ctx, (XwTextPosition) 0, (XwTextPosition) 0);
+ ctx->text.showposition = TRUE;
+ return(result);
+}
+/* Insert a file of the given name into the text. Returns 0 if file found,
+ -1 if not. */
+
+/* Unadvertized function */
+/*--------------------------------------------------------------------------+*/
+int XwTextInsertFile(ctx, str)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ unsigned char *str;
+{
+ int fid;
+ XwTextBlock text;
+ unsigned char buf[1000];
+ XwTextPosition position;
+
+ if (str == NULL || XwStrlen(str) == 0) return -1;
+ fid = open(str, O_RDONLY);
+ if (fid <= 0) return -1;
+ _XtTextPrepareToUpdate(ctx);
+ position = ctx->text.insertPos;
+ while ((text.length = read(fid, buf, 512)) > 0) {
+ text.ptr = buf;
+ ReplaceText(ctx, position, position, &text, TRUE);
+ position = (*(ctx->text.source->scan))(ctx->text.source, position,
+ XwstPositions, XwsdRight, text.length, TRUE);
+ }
+ close(fid);
+ ctx->text.insertPos = position;
+ _XtTextExecuteUpdate(ctx);
+ return 0;
+}
+
+/******************************************************************************
+*
+* Action Table Functions
+*
+******************************************************************************/
+/*--------------------------------------------------------------------------+*/
+static Boolean VerifyLeave(ctx,event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextVerifyCD cbdata;
+
+ StartAction(ctx, event);
+ cbdata.operation = leaveVerify;
+ cbdata.doit = TRUE;
+ cbdata.currInsert = ctx->text.insertPos;
+ cbdata.newInsert = ctx->text.insertPos;
+ cbdata.startPos = ctx->text.insertPos;
+ cbdata.endPos = ctx->text.insertPos;
+ cbdata.text = NULL;
+ cbdata.xevent = event;
+ XtCallCallbacks((Widget)ctx, XtNleaveVerification, &cbdata);
+ ctx->text.insertPos = cbdata.newInsert;
+ EndAction(ctx);
+ return( cbdata.doit );
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseUp(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseUp((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseDown(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseDown((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraversePrev(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraversePrev((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseNext(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseNext((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseLeft(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseLeft((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseRight(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseRight((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseHome(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseHome((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TraverseNextTop(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* Allow the verification routine to control the traversal */
+ if (VerifyLeave(ctx, event))
+ _XwTraverseNextTop((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void Enter(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ _XwPrimitiveEnter((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void Leave(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* If traversal is on, then the leave verification callback is called
+ in the focus out event handler */
+ if (ctx->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
+ VerifyLeave(ctx, event);
+
+ _XwPrimitiveLeave((Widget)ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TextFocusIn (ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ _XwPrimitiveFocusIn((XwPrimitiveWidget)ctx, event);
+ ctx->text.hasfocus = TRUE;
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TextFocusOut(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* If traversal is on, then the leave verification callback is called in
+ the traversal event handler */
+ if (ctx->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
+ VerifyLeave(ctx, event);
+
+ _XwPrimitiveFocusOut((XwPrimitiveWidget)ctx, event);
+ ctx->text.hasfocus = FALSE;
+}
+
+/* Kill and Stuff */
+/*--------------------------------------------------------------------------+*/
+static void UnKill(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ StuffFromBuffer(ctx, 1);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void Stuff(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ StuffFromBuffer(ctx, 0);
+ EndAction(ctx);
+}
+
+/* routines for moving around */
+
+/*--------------------------------------------------------------------------+*/
+static void MoveForwardChar(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdRight, 1,
+ TRUE)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveBackwardChar(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdLeft, 1, TRUE)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveForwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx,
+ NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveBackwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx,
+ NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveBackwardParagraph(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx,
+ NextPosition(ctx, ctx->text.insertPos, XwstEOL, XwsdLeft)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveForwardParagraph(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx,
+ NextPosition(ctx, ctx->text.insertPos, XwstEOL, XwsdRight)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveToLineStart(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ int line;
+ StartAction(ctx, event);
+ _XtTextShowPosition(ctx);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ _XwSetCursorPos(ctx, ctx->text.lt.info[line].position);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveToLineEnd(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ int line;
+ XwTextPosition next, lastpos = GETLASTPOS(ctx);
+ StartAction(ctx, event);
+ _XtTextShowPosition(ctx);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ next = ctx->text.lt.info[line+1].position;
+ if (next > lastpos)
+ next = lastpos;
+ else
+ next = (*(ctx->text.source->scan))
+ (ctx->text.source, next, XwstPositions, XwsdLeft, 1, TRUE);
+ if (next <= ctx->text.lt.info[line].drawPos)
+ next = ctx->text.lt.info[line].drawPos + 1 ;
+ _XwSetCursorPos(ctx, next);
+ EndAction(ctx);
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static void MoveNextLine(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ int width, width2, height, line;
+ XwTextPosition position, maxp, lastpos = GETLASTPOS(ctx);
+ XwTextSink *sink = ctx->text.sink ;
+
+ StartAction(ctx, event);
+ _XtTextShowPosition(ctx); /* Needed if cursor goes off screen ??? */
+ line = LineForPosition(ctx, ctx->text.insertPos);
+
+ if (ctx->text.lt.info[line+1].position != (lastpos + 1)) {
+ if ((line == ctx->text.lt.lines - 1) && (line > 0)) {
+ _XtTextScroll(ctx, 1);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ }
+ if (sink->LineLastPosition == ctx->text.insertPos)
+ width = sink->LineLastWidth;
+ else
+ (*(ctx->text.sink->findDistance))
+ (ctx, ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
+ ctx->text.insertPos, &width, &position, &height);
+ line++;
+ if (ctx->text.lt.info[line].position > lastpos) {
+ position = lastpos;
+ }
+ else {
+ (*(ctx->text.sink->findPosition))(ctx,
+ ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
+ width, FALSE, &position, &width2, &height);
+ maxp = (*(ctx->text.source->scan))(ctx->text.source,
+ ctx->text.lt.info[line+1].position,
+ XwstPositions, XwsdLeft, 1, TRUE);
+ if (position > maxp)
+ position = maxp;
+ }
+ if (_XwSetCursorPos(ctx, position) == XweditDone) {
+ sink->LineLastWidth = width;
+ sink->LineLastPosition = position;
+ }
+ }
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MovePreviousLine(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ int width, width2, height, line;
+ XwTextPosition position, maxp;
+ XwTextSink *sink = ctx->text.sink ;
+
+ StartAction(ctx, event);
+ _XtTextShowPosition(ctx);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ if (line == 0) {
+ _XtTextScroll(ctx, -1);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ }
+ if (line > 0) {
+ if (sink->LineLastPosition == ctx->text.insertPos)
+ width = sink->LineLastWidth;
+ else
+ (*(ctx->text.sink->findDistance))(ctx,
+ ctx->text.lt.info[line].position,
+ ctx->text.lt.info[line].x,
+ ctx->text.insertPos, &width, &position, &height);
+ line--;
+ (*(ctx->text.sink->findPosition))(ctx,
+ ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
+ width, FALSE, &position, &width2, &height);
+ maxp = (*(ctx->text.source->scan))(ctx->text.source,
+ ctx->text.lt.info[line+1].position,
+ XwstPositions, XwsdLeft, 1, TRUE);
+ if (position > maxp)
+ position = maxp;
+ if (_XwSetCursorPos(ctx, position) == XweditDone) {
+ sink->LineLastWidth = width;
+ sink->LineLastPosition = position;
+ }
+ }
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveBeginningOfFile(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstLast, XwsdLeft, 1, TRUE)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveEndOfFile(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstLast, XwsdRight, 1, TRUE)
+ );
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void ScrollOneLineUp(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XtTextScroll(ctx, 1);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void ScrollOneLineDown(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ _XtTextScroll(ctx, -1);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MoveNextPage(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwLineTablePtr lt = &(ctx->text.lt) ;
+ int cur_line;
+ XwTextPosition line_offset, new_pos, lastpos = GETLASTPOS(ctx);
+
+ StartAction(ctx, event);
+ if (lt->info[(lt->lines)].position != (lastpos + 1)) {
+ cur_line = LineForPosition(ctx, ctx->text.insertPos);
+ line_offset = (ctx->text.insertPos - lt->info[cur_line].position);
+ _XtTextScroll(ctx, max(1, lt->lines - 2));
+ if (lt->info[cur_line].position > lastpos)
+ cur_line = LineForPosition(ctx, lastpos);
+ new_pos = (lt->info[cur_line].position + line_offset);
+ new_pos = min(new_pos, lt->info[cur_line].drawPos);
+ _XwSetCursorPos(ctx, new_pos);
+ }
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void MovePreviousPage(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{ XwLineTablePtr lt = &(ctx->text.lt) ;
+ int cur_line = LineForPosition(ctx, ctx->text.insertPos);
+ XwTextPosition line_offset =
+ (ctx->text.insertPos - lt->info[cur_line].position);
+ XwTextPosition new_pos;
+ StartAction(ctx, event);
+ _XtTextScroll(ctx, -max(1, lt->lines - 2));
+ new_pos = (lt->info[cur_line].position + line_offset);
+ _XwSetCursorPos(ctx, min(new_pos, lt->info[cur_line].drawPos));
+ EndAction(ctx);
+}
+
+/* delete routines */
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteForwardChar(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = (*(ctx->text.source->scan))(
+ ctx->text.source, ctx->text.insertPos, XwstPositions,
+ XwsdRight, 1, TRUE);
+ DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteBackwardNormal(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ /* If there's a selection, delete it, otherwise, delete the character */
+
+ if (ctx->text.s.left != ctx->text.s.right)
+ DeleteCurrentSelection(ctx, event);
+ else
+ DeleteBackwardChar(ctx, event);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteBackwardChar(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = (*(ctx->text.source->scan))(
+ ctx->text.source, ctx->text.insertPos, XwstPositions,
+ XwsdLeft, 1, TRUE);
+ DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteForwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight);
+ DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteBackwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft);
+ DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void KillForwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight);
+ DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void KillBackwardWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft);
+ DeleteOrKill(ctx, next, ctx->text.insertPos, TRUE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void KillCurrentSelection(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, TRUE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void DeleteCurrentSelection(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, FALSE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void KillToEndOfLine(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ int line;
+ XwTextPosition last, next, lastpos = GETLASTPOS(ctx);
+ StartAction(ctx, event);
+ _XtTextShowPosition(ctx);
+ line = LineForPosition(ctx, ctx->text.insertPos);
+ last = ctx->text.lt.info[line + 1].position;
+ next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstEOL, XwsdRight, 1, FALSE);
+ if (last > lastpos)
+ last = lastpos;
+ if (last > next && ctx->text.insertPos < next)
+ last = next;
+ DeleteOrKill(ctx, ctx->text.insertPos, last, TRUE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void KillToEndOfParagraph(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+
+ StartAction(ctx, event);
+ next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstEOL, XwsdRight, 1, FALSE);
+ if (next == ctx->text.insertPos)
+ next = (*(ctx->text.source->scan))(ctx->text.source, next, XwstEOL,
+ XwsdRight, 1, TRUE);
+ DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void InsertNewLineAndBackup(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ InsertNewLineAndBackupInternal(ctx);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwEditResult InsertNewLine(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition next;
+ XwEditResult result;
+
+ StartAction(ctx, event);
+ if (InsertNewLineAndBackupInternal(ctx)) {
+ EndAction(ctx);
+ return(XweditError);
+ }
+ next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstPositions, XwsdRight, 1, TRUE);
+ result = _XwSetCursorPos(ctx, next);
+ EndAction(ctx);
+ return(result);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void InsertNewLineAndIndent(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextBlock text;
+ XwTextPosition pos1, pos2;
+ XwEditResult result;
+
+ StartAction(ctx, event);
+ pos1 = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstEOL, XwsdLeft, 1, FALSE);
+ pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos1, XwstEOL,
+ XwsdLeft, 1, TRUE);
+ pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos2, XwstWhiteSpace,
+ XwsdRight, 1, TRUE);
+ text.ptr = _XwTextCopySubString(ctx, pos1, pos2);
+ text.length = XwStrlen(text.ptr);
+ if (InsertNewLine(ctx, event)) return;
+ if (result =
+ ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
+ &text, TRUE)) {
+ if (result != XweditReject)
+ XBell(XtDisplay(ctx), 50);
+ XtFree(text.ptr);
+ EndAction(ctx);
+ return;
+ }
+ _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
+ (ctx->text.source, ctx->text.insertPos, XwstPositions,
+ XwsdRight, text.length, TRUE));
+ XtFree(text.ptr);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void NewSelection(ctx, l, r)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition l, r;
+{
+ unsigned char *ptr;
+ _XtTextSetNewSelection(ctx, l, r);
+ if (l < r) {
+ ptr = _XwTextCopySubString(ctx, l, r);
+ XStoreBuffer(XtDisplay(ctx), ptr, min(XwStrlen(ptr), MAXCUT), 0);
+ XtFree(ptr);
+ }
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SelectWord(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ XwTextPosition l, r;
+ StartAction(ctx, event);
+ l = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstWhiteSpace, XwsdLeft, 1, FALSE);
+ r = (*(ctx->text.source->scan))(ctx->text.source, l, XwstWhiteSpace,
+ XwsdRight, 1, FALSE);
+ NewSelection(ctx, l, r);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SelectAll(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ NewSelection(ctx, (XwTextPosition) 0, GETLASTPOS(ctx));
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SelectStart(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextSelect, XwactionStart);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SelectAdjust(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextSelect, XwactionAdjust);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void SelectEnd(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextSelect, XwactionEnd);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void ExtendStart(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextExtend, XwactionStart);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void ExtendAdjust(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextExtend, XwactionAdjust);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void ExtendEnd(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ AlterSelection(ctx, XwsmTextExtend, XwactionEnd);
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void RedrawDisplay(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ StartAction(ctx, event);
+ ForceBuildLineTable(ctx);
+ DisplayAllText(ctx);
+ ClearWindow(ctx);
+ EndAction(ctx);
+/* This seems like the wrong place for this */
+ if (ctx->primitive.highlighted)
+ _XwHighlightBorder(ctx);
+}
+
+#define STRBUFSIZE 100
+static XComposeStatus compose_status = {NULL, 0};
+
+/*--------------------------------------------------------------------------+*/
+static void InsertChar(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+ unsigned char strbuf[STRBUFSIZE];
+ KeySym keysym;
+ XwEditResult result;
+ XwTextBlock text;
+
+ text.length = XLookupString ((XKeyEvent *)event, strbuf, STRBUFSIZE,
+ &keysym, &compose_status);
+ if (text.length==0) return;
+ StartAction(ctx, event);
+ text.ptr = &strbuf[0];;
+ text.firstPos = 0;
+ if (result =
+ ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
+ &text, TRUE)) {
+ if (result != XweditReject)
+ XBell(XtDisplay(ctx), 50);
+ EndAction(ctx);
+ return;
+ }
+ _XwSetCursorPos(ctx,
+ (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
+ XwstPositions, XwsdRight, text.length, TRUE));
+ _XtTextSetNewSelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
+
+ EndAction(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void Execute(ctx, event)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XEvent *event;
+{
+
+ XtCallCallbacks((Widget)ctx, XtNexecute, NULL);
+
+}
+
+/*************************************************************************
+*
+* Class Record Support Functions
+*
+*************************************************************************/
+
+/******************************************************************************
+*
+* Class Record Functions
+*
+******************************************************************************/
+
+/*--------------------------------------------------------------------------+*/
+static void ClassInitialize()
+/*--------------------------------------------------------------------------+*/
+{
+
+
+} /* ClassInitialize */
+
+
+
+/******************************************************************************
+*
+* External functions (Methods???) on the class
+*
+******************************************************************************/
+
+/*--------------------------------------------------------------------------+*/
+void XwTextClearBuffer(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ _XtTextPrepareToUpdate(w);
+ (*(w->text.source->setLastPos))(w->text.source, (XwTextPosition)0);
+ w->text.insertPos = 0;
+ ForceBuildLineTable(w);
+ DisplayAllText(w);
+ _XtTextExecuteUpdate(w);
+}
+
+/*--------------------------------------------------------------------------+*/
+unsigned char *XwTextCopyBuffer(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+
+ return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_substring)
+ ((XwTextEditWidget)w, 0, GETLASTPOS(w));
+
+}
+
+/*--------------------------------------------------------------------------+*/
+unsigned char *XwTextCopySelection(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_selection)
+ ((XwTextEditWidget)w);
+}
+
+/*--------------------------------------------------------------------------+*/
+int XwTextReadSubString( w, startpos, endpos, target, targetsize, targetused )
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition startpos, endpos;
+ unsigned char *target;
+ int targetsize,
+ *targetused;
+{
+ return( _XwTextSubString(w, startpos, endpos, target, targetsize, targetused) );
+
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextUnsetSelection(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.unset_selection)
+ ((Widget)w);
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextSetSelection(w, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition left, right;
+{
+ (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.set_selection)
+ ((Widget)w, left, right);
+}
+
+/*--------------------------------------------------------------------------+*/
+XwEditResult XwTextReplace(w, startPos, endPos, string)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition startPos, endPos;
+ unsigned char *string;
+{
+ XwTextBlock blk;
+
+ blk.ptr = string;
+ blk.length = XwStrlen(string);
+ blk.firstPos = (XwTextPosition)0;
+
+ return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.replace_text)
+ (w, startPos, endPos, &blk, FALSE);
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextRedraw(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.redraw_text)
+ ((Widget)w);
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextResize(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ _XtTextPrepareToUpdate(w);
+ CheckResizeOrOverflow(w);
+ _XtTextExecuteUpdate(w);
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextUpdate( w, status )
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ Boolean status;
+{
+ w->text.update_flag = status;
+ if (status) {
+ _XtTextExecuteUpdate(w);
+ }
+ else {
+ w->text.numranges = 0;
+ w->text.showposition = FALSE;
+ w->text.oldinsert = w->text.insertPos;
+ if ( XtIsRealized((Widget)w) ) InsertCursor(w, XwisOff);
+ }
+}
+
+
+/*--------------------------------------------------------------------------+*/
+void XwTextInsert(w, string)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ unsigned char *string;
+{
+ XwTextBlock blk;
+
+ blk.ptr = string;
+ blk.length = XwStrlen(string);
+ blk.firstPos = (XwTextPosition) 0;
+
+ _XtTextPrepareToUpdate(w);
+ if (ReplaceText(w, w->text.insertPos,
+ w->text.insertPos, &blk, FALSE) == XweditDone) {
+ w->text.showposition = TRUE;
+ w->text.insertPos = w->text.insertPos + blk.length;
+ }
+ _XtTextExecuteUpdate(w);
+
+}
+
+/*--------------------------------------------------------------------------+*/
+XwTextPosition XwTextGetLastPos (w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ return( GETLASTPOS(w) );
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextGetSelectionPos(w, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition *left, *right;
+{
+
+ *left = w->text.s.left;
+ *right = w->text.s.right;
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextSetInsertPos(w, position)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition position;
+{
+
+ _XtTextPrepareToUpdate(w);
+ w->text.insertPos = position;
+ w->text.showposition = TRUE;
+ _XtTextExecuteUpdate(w);
+}
+
+/*--------------------------------------------------------------------------+*/
+XwTextPosition XwTextGetInsertPos(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+
+ return( w->text.insertPos );
+
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextSetSource(w, source, startpos)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextSourcePtr source;
+ XwTextPosition startpos;
+{
+
+ w->text.source = source;
+ w->text.lt.top = startpos;
+ w->text.s.left = w->text.s.right = 0;
+ w->text.insertPos = startpos;
+
+ ForceBuildLineTable(w);
+ if (XtIsRealized((Widget)w)) {
+ _XtTextPrepareToUpdate(w);
+ DisplayAllText(w);
+ _XtTextExecuteUpdate(w);
+ }
+}
+/* Not advertised. Don't think it is necessary */
+/*--------------------------------------------------------------------------+*/
+unsigned char *XwTextCopySubString(w, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition left, right;
+{
+ return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_substring)
+ ((XwTextEditWidget)w, left, right);
+}
+
+/*--------------------------------------------------------------------------+*/
+void XwTextInvalidate(w, from, to)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+ XwTextPosition from,to;
+{
+ _XtTextPrepareToUpdate(w);
+ _XtTextNeedsUpdating(w, from, to);
+ ForceBuildLineTable(w);
+ _XtTextExecuteUpdate(w);
+}
+
+/*--------------------------------------------------------------------------+*/
+XwTextPosition XwTextTopPosition(w)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget w;
+{
+ return w->text.lt.top;
+}
+
+/*****************************************************************************
+* Class Functions
+*****************************************************************************/
+
+/*--------------------------------------------------------------------------+*/
+static void Initialize(request, new)
+/*--------------------------------------------------------------------------+*/
+ Widget request, new;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget)new;
+ XwTextEditPart *text = &(ctx->text);
+
+ text->lt.lines = 0;
+ text->lt.info = NULL;
+ text->s.left = text->s.right = 0;
+ text->s.type = XwselectPosition;
+ text->sarray[0] = XwselectPosition;
+ text->sarray[1] = XwselectWord;
+ text->sarray[2] = XwselectLine;
+ text->sarray[3] = XwselectParagraph;
+ text->sarray[4] = XwselectAll;
+ text->sarray[5] = XwselectNull;
+ text->lasttime = 0; /* ||| correct? */
+ text->time = 0; /* ||| correct? */
+
+ text->oldinsert = -1 ;
+ text->update_flag = FALSE;
+ text->showposition = TRUE;
+ text->updateFrom = (XwTextPosition *) XtMalloc(sizeof(XwTextPosition));
+ text->updateTo = (XwTextPosition *) XtMalloc(sizeof(XwTextPosition));
+ text->numranges = text->maxranges = 0;
+ text->gc = DefaultGCOfScreen(XtScreen(ctx));
+ text->hasfocus = FALSE;
+ text->scroll_state = text->scroll_mode ;
+ text->grow_state = text->grow_mode ;
+ text->prevW = ctx->core.width ;
+ text->prevH = ctx->core.height ;
+ if (text->grow_mode & XwGrowHorizontal)
+ { text->wrap_mode = XwWrapOff ;
+ } ;
+ if (text->wrap_mode == XwWrapOff)
+ { text->wrap_form = XwSourceForm ;
+ text->wrap_break = XwWrapAny ;
+ } ;
+
+#ifdef GLSDEBUG
+ fprintf (stderr, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %x\n"
+ , " wrap mode", text->wrap_mode
+ , " wrap form", text->wrap_form
+ , " wrap break", text->wrap_break
+ , "scroll mode", text->scroll_mode
+ , " grow mode", text->grow_mode
+ , " options", text->options
+ ) ;
+#endif
+}
+
+/*--------------------------------------------------------------------------+*/
+static void InitializeHook(widget, args, num_args)
+/*--------------------------------------------------------------------------+*/
+ Widget widget;
+ ArgList args;
+ Cardinal *num_args;
+{ XwTextEditWidget ctx = (XwTextEditWidget)widget;
+ register XwTextEditPart *text = &(ctx->text);
+
+ text->sink = XwAsciiSinkCreate(widget, args, *num_args);
+
+ if (text->srctype == XwstringSrc)
+ text->source = XwStringSourceCreate(widget, args, *num_args);
+ else if (text->srctype != XwprogDefinedSrc)
+ {XtWarning("XwSourceType not recognized. Using XwstringSrc.");
+ text->source = XwStringSourceCreate(widget, args, *num_args);
+ };
+
+ ForceBuildLineTable((XwTextEditWidget)widget);
+ if (text->lt.lines > 1)
+ { text->scroll_state &= ~XwAutoScrollHorizontal ;
+ }
+}
+
+/*--------------------------------------------------------------------------+*/
+static void TextDestroy(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ (*(ctx->text.source->destroy))(ctx->text.source);
+ (*(ctx->text.sink->destroy))(ctx->text.sink);
+ XtFree((char *)ctx->text.updateFrom);
+ XtFree((char *)ctx->text.updateTo);
+ XtRemoveAllCallbacks((Widget)ctx, XtNmotionVerification);
+ XtRemoveAllCallbacks((Widget)ctx, XtNmodifyVerification);
+ XtRemoveAllCallbacks((Widget)ctx, XtNleaveVerification);
+}
+
+
+/*--------------------------------------------------------------------------+*/
+static void Resize(w)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+ XwTextEditPart *tp ;
+ Dimension width, height ;
+ Boolean realized = XtIsRealized(w);
+
+ tp = &(ctx->text) ;
+ width = ctx->core.width ;
+ if ((width < tp->prevW) && (tp->grow_mode & XwGrowHorizontal))
+ tp->grow_state |= XwGrowHorizontal ;
+ height = ctx->core.height ;
+ if ((height < tp->prevH) && (tp->grow_mode & XwGrowVertical))
+ tp->grow_state |= XwGrowVertical ;
+
+ if (realized) _XtTextPrepareToUpdate(ctx);
+ ForceBuildLineTable(ctx);
+
+ if (tp->lt.lines > 1)
+ { tp->scroll_state &= ~XwAutoScrollHorizontal ;
+ }
+ else
+ { tp->scroll_state |= tp->scroll_mode & XwAutoScrollHorizontal ;
+ }
+
+ if (realized)
+ {
+ DisplayAllText(ctx);
+ ClearWindow(ctx);
+ }
+
+ if (realized) _XtTextExecuteUpdate(ctx);
+}
+
+/*--------------------------------------------------------------------------+*/
+static Boolean SetValues(current, request, new)
+/*--------------------------------------------------------------------------+*/
+Widget current, request, new;
+{
+ XwTextEditWidget oldtw = (XwTextEditWidget) current;
+ XwTextEditWidget newtw = (XwTextEditWidget) new;
+ Boolean redisplay = FALSE;
+ XwTextEditPart *oldtext = &(oldtw->text);
+ XwTextEditPart *newtext = &(newtw->text);
+ Boolean realized = XtIsRealized(current);
+
+ if (realized) _XtTextPrepareToUpdate(oldtw);
+
+ if (oldtext->source != newtext->source) {
+ ForceBuildLineTable(oldtw);
+ if ((oldtext->s.left == newtext->s.left) &&
+ (oldtext->s.right == newtext->s.right)) {
+ newtext->s.left = (XwTextPosition) 0;
+ newtext->s.right = (XwTextPosition) 0;
+ }
+ redisplay = TRUE;
+ }
+
+ if (oldtext->sink != newtext->sink)
+ redisplay = TRUE;
+
+ if (oldtext->insertPos != newtext->insertPos)
+ oldtext->showposition = TRUE;
+
+ if (oldtext->lt.top != newtext->lt.top)
+ redisplay = TRUE;
+
+ if ((oldtext->leftmargin != newtext->leftmargin) ||
+ (oldtext->topmargin != newtext->topmargin) ||
+ (oldtext->rightmargin != newtext->rightmargin) ||
+ (oldtext->bottommargin != newtext->bottommargin))
+ redisplay = TRUE;
+
+ if ((oldtext->s.left != newtext->s.left) ||
+ (oldtext->s.right != newtext->s.right)) {
+ if (newtext->s.left > newtext->s.right) {
+ XwTextPosition temp = newtext->s.right;
+ newtext->s.right = newtext->s.left;
+ newtext->s.left = temp;
+ redisplay = TRUE;
+ }
+ }
+
+
+ /* ||| This may be the best way to do this, as some optimizations
+ * can occur here that may be harder if we let XtSetValues
+ * call our expose proc.
+ */
+
+ if (redisplay && realized)
+ DisplayAllText(newtw);
+
+ if (realized) _XtTextExecuteUpdate(newtw);
+
+ return ( FALSE );
+}
+
+/*--------------------------------------------------------------------------+*/
+static Boolean SetValuesHook(widget, args, num_args)
+/*--------------------------------------------------------------------------+*/
+ Widget widget;
+ ArgList args;
+ Cardinal *num_args;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget)widget;
+ XwTextSource *source = ctx->text.source;
+ XwTextSink *sink = ctx->text.sink;
+ Boolean realized = XtIsRealized(widget);
+
+ if (realized) _XtTextPrepareToUpdate(ctx);
+
+ /* This is ugly, but need to know if user set initial_string */
+ ((StringSourcePtr)(source->data))->initial_string = NULL;
+
+ XtSetSubvalues(source->data, source->resources,
+ source->resource_num, args, *num_args);
+ XtSetSubvalues(sink->data, sink->resources,
+ sink->resource_num, args, *num_args);
+
+ (*(source->check_data))(source);
+
+ ForceBuildLineTable(ctx);
+ if (realized) {
+ DisplayAllText(ctx);
+ _XtTextExecuteUpdate(ctx);
+ }
+
+ return( FALSE );
+}
+
+/*--------------------------------------------------------------------------+*/
+static void GetValuesHook(widget, args, num_args)
+/*--------------------------------------------------------------------------+*/
+ Widget widget;
+ ArgList args;
+ Cardinal *num_args;
+{
+ XwTextSource *source = ((XwTextEditWidget)widget)->text.source;
+ XwTextSink *sink = ((XwTextEditWidget)widget)->text.sink;
+ int i = 0;
+
+ /* This is ugly, but have to get internal buffer to initial_string storage */
+ while (i < *num_args) {
+ if (strcmp(args[i].name, XtNstring) == 0) {
+ ((StringSourcePtr)(source->data))->initial_string =
+ XwTextCopyBuffer((XwTextEditWidget)widget);
+ break;
+ };
+ i++;
+ };
+
+ XtGetSubvalues(source->data, source->resources, source->resource_num,
+ args, *num_args);
+ XtGetSubvalues(sink->data, sink->resources, sink->resource_num,
+ args, *num_args);
+}
+
+/*--------------------------------------------------------------------------+*/
+static void Realize( w, valueMask, attributes )
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ Mask *valueMask;
+ XSetWindowAttributes *attributes;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget)w;
+
+ *valueMask |= CWBitGravity;
+ attributes->bit_gravity = NorthWestGravity;
+
+ XtCreateWindow( w, InputOutput, (Visual *)CopyFromParent,
+ *valueMask, attributes);
+ if (XtIsRealized(w)) {
+ XDefineCursor( w->core.screen->display, w->core.window,
+ XCreateFontCursor( w->core.screen->display, XC_left_ptr));
+ ctx->text.update_flag = TRUE;
+ }
+ else {
+ XtWarning("Unable to realize TextEdit");
+ }
+ _XwRegisterName(w);
+}
+
+
+/*****************************************************************************
+*
+* Text Edit Class Record
+*
+*****************************************************************************/
+XwTextEditClassRec XwtexteditClassRec = {
+ {
+ /* core fields */
+ /* superclass */ (WidgetClass) &XwprimitiveClassRec,
+ /* class_name */ "XwTextEdit",
+ /* widget_size */ sizeof(XwTextEditRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ (XtInitProc)Initialize,
+ /* initialize_hook */ InitializeHook,
+ /* realize */ Realize,
+ /* actions */ texteditActionsTable,
+ /* num_actions */ XtNumber(texteditActionsTable),
+ /* resources */ resources,
+ /* num_ resource */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure*/ FALSE,
+ /* compress_enterleave*/ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ (XtWidgetProc)TextDestroy,
+ /* resize */ Resize,
+ /* expose */ (XtExposeProc)ProcessExposeRegion,
+ /* set_values */ (XtSetValuesFunc)SetValues,
+ /* set_values_hook */ SetValuesHook,
+ /* set_values_almost*/ XtInheritSetValuesAlmost,
+ /* get_values_hook */ GetValuesHook,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ defaultTextEditTranslations,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ {
+ /* XwPrimitive fields */
+
+ (XtWidgetProc) NULL,
+ (XtWidgetProc) NULL,
+ (XwEventProc) NULL,
+ (XwEventProc) NULL,
+ (XwEventProc) NULL,
+ (XtTranslations) NULL
+ },
+ {
+ /* XwTextEdit fields */
+ /* copy_substring */ _XwTextCopySubString,
+ /* copy_selection */ _XwTextCopySelection,
+ /* unset_selection */ _XwTextUnsetSelection,
+ /* set_selection */ (XwSetSProc)_XwTextSetSelection,
+ /* replace_text */ _XwTextReplace,
+ /* redraw_text */ _XwTextRedraw,
+ }
+};
+
+WidgetClass XwtexteditWidgetClass = (WidgetClass)&XwtexteditClassRec;
+WidgetClass XwtextEditWidgetClass = (WidgetClass)&XwtexteditClassRec;
+
diff --git a/Xw/TextEdit.h b/Xw/TextEdit.h
new file mode 100644
index 0000000..d9d4d2a
--- /dev/null
+++ b/Xw/TextEdit.h
@@ -0,0 +1,263 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: TextEdit.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: TextEdit widget public include file
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#ifndef _XwTextEdit_h
+#define _XwTextEdit_h
+
+#define XwSetArg(arg, n, v) \
+ { Arg *_XwSetArgTmp = &(arg) ;\
+ _XwSetArgTmp->name = (n) ;\
+ _XwSetArgTmp->value = (XtArgVal) (v) ;}
+
+#include <X11/StringDefs.h>
+
+
+
+/*************************************************************************
+*
+* Structures used in TextEdit function calls
+*
+*************************************************************************/
+
+extern WidgetClass XwtexteditWidgetClass;
+/* synonym added for consistent naming conventions */
+extern WidgetClass XwtextEditWidgetClass;
+
+typedef struct _XwTextEditClassRec *XwTextEditWidgetClass;
+typedef struct _XwTextEditRec *XwTextEditWidget;
+
+typedef long XwTextPosition;
+
+typedef enum {XwsdLeft, XwsdRight} XwScanDirection;
+typedef enum
+ {XwstPositions, XwstWhiteSpace, XwstEOL, XwstLast} XwScanType;
+
+typedef struct {
+ int firstPos;
+ int length;
+ unsigned char *ptr;
+ } XwTextBlock, *XwTextBlockPtr;
+
+typedef enum {XwtextRead, XwtextAppend, XwtextEdit} XwEditType;
+typedef enum
+ {XweditDone, XweditError, XweditPosError, XweditReject} XwEditResult;
+
+typedef struct {
+ XtResource *resources;
+ Cardinal resource_num;
+ int (*read)();
+ XwEditResult (*replace)();
+ XwTextPosition (*getLastPos)();
+ int (*setLastPos)();
+ XwTextPosition (*scan)();
+ XwEditType (*editType)();
+ Boolean (*check_data)();
+ void (*destroy)();
+ int *data;
+ } XwTextSource, *XwTextSourcePtr;
+
+/* this wouldn't be here if source and display (still called
+ sink here) were properly separated, classed and subclassed
+ */
+
+typedef short TextFit ;
+#define tfNoFit 0x01
+#define tfIncludeTab 0x02
+#define tfEndText 0x04
+#define tfNewline 0x08
+#define tfWrapWhiteSpace 0x10
+#define tfWrapAny 0x20
+
+typedef struct {
+ XwTextEditWidget parent;
+ XFontStruct *font;
+ int foreground;
+ XtResource *resources;
+ Cardinal resource_num;
+ int (*display)();
+ int (*insertCursor)();
+ int (*clearToBackground)();
+ int (*findPosition)();
+ TextFit (*textFitFn)();
+ int (*findDistance)();
+ int (*resolve)();
+ int (*maxLines)();
+ int (*maxHeight)();
+ Boolean (*check_data)();
+ void (*destroy)();
+ int LineLastWidth ;
+ XwTextPosition LineLastPosition ;
+ int *data;
+ } XwTextSink, *XwTextSinkPtr;
+
+/*************************************************************************
+*
+* Support for Verification Callbacks
+*
+*************************************************************************/
+
+typedef enum {motionVerify, modVerify, leaveVerify} XwVerifyOpType;
+
+typedef struct {
+ XEvent *xevent;
+ XwVerifyOpType operation;
+ Boolean doit;
+ XwTextPosition currInsert, newInsert;
+ XwTextPosition startPos, endPos;
+ XwTextBlock *text;
+} XwTextVerifyCD, *XwTextVerifyPtr;
+
+
+/* Class record constants */
+
+typedef enum {XwstringSrc, XwdiskSrc, XwprogDefinedSrc} XwSourceType;
+
+/* other stuff */
+
+#define wordBreak 0x01
+#define scrollVertical 0x02
+#define scrollHorizontal 0x04
+#define scrollOnOverflow 0x08
+#define resizeWidth 0x10
+#define resizeHeight 0x20
+#define editable 0x40
+
+/****************************************************************************
+*
+* Display control (grow, wrap, scroll, visible cursor)
+*
+****************************************************************************/
+
+typedef enum {XwWrapOff, XwSoftWrap, XwHardWrap} XwWrap ;
+typedef enum {XwSourceForm, XwDisplayForm} XwWrapForm ;
+typedef enum {XwWrapAny, XwWrapWhiteSpace} XwWrapBreak ;
+
+/* Scroll options */
+typedef int XwScroll ;
+
+/* Grow options */
+typedef int XwGrow ;
+
+/*************************************************************************
+*
+* External functions from TextEdit
+*
+*************************************************************************/
+
+extern void XwTextClearBuffer();
+ /* XwTextEditWidget w; */
+
+extern unsigned char *XwTextCopyBuffer();
+ /* XwTextEditWidget w */
+
+extern unsigned char *XwTextCopySelection();
+ /* XwTextEditWidget w */
+
+extern int XwTextReadSubString();
+ /* XwTextEditWidget w;
+ XwTextPosition startpos,
+ endpos;
+ unsigned char *target; Memory to copy into
+ int targetsize, Memory size
+ targetused; Memory used by copy */
+
+extern void XwTextUnsetSelection();
+ /* XwTextEditWidget w */
+
+extern void XwTextSetSelection();
+ /* XwTextEditWidget w;
+ XwTextPosition left, right; */
+
+extern XwEditResult XwTextReplace();
+ /* XwTextEditWidget w;
+ XwTextPosition startPos, endPos;
+ unsigned char *string; */
+
+extern void XwTextRedraw();
+ /* XwTextEditWidget w */
+
+#define HAVE_XWTEXTRESIZE
+extern void XwTextResize();
+ /* XwTextEditWidget w */
+
+extern void XwTextUpdate();
+ /* XwTextEditWidget w;
+ Boolean status */
+
+extern void XwTextInsert();
+ /* XwTextEditWidget w */
+ /* unsigned char *string */
+
+extern XwTextPosition XwTextGetLastPos();
+ /* XwTextEditWidget w; */
+
+extern void XwTextGetSelectionPos();
+ /* XwTextEditWidget w; */
+ /* XwTextPosition *left, *right; */
+
+extern void XwTextSetInsertPos();
+ /* XwTextEditWidget w; */
+ /* XwTextPosition position */
+
+extern XwTextPosition XwTextGetInsertPos();
+ /* XwTextEditWidget widget */
+
+extern void XwTextSetSource();
+ /* XwTextEditWidget w; */
+ /* XwTextSourcePtr source; */
+ /* XwTextPosition startpos */
+
+/*************************************************************************
+*
+* Extern Source and Sink Create/Destroy functions
+*
+*************************************************************************/
+
+extern XwTextSink *XwAsciiSinkCreate();
+ /* Widget w */
+ /* ArgList args */
+ /* Cardinal num_args */
+
+extern XwTextSource *XwStringSourceCreate();
+ /* Widget parent; */
+ /* ArgList args; */
+ /* int argCount; */
+
+extern void XwStringSourceDestroy();
+ /* XwTextSource *src */
+
+#endif
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/Xw/TextEditP.h b/Xw/TextEditP.h
new file mode 100644
index 0000000..9228a61
--- /dev/null
+++ b/Xw/TextEditP.h
@@ -0,0 +1,172 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: TextEditP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: TextEdit widget private include file
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#ifndef _XtTextEditPrivate_h
+#define _XtTextEditPrivate_h
+
+
+/****************************************************************
+ *
+ * TextEdit widget private
+ *
+ ****************************************************************/
+
+#define MAXCUT 30000 /* Maximum number of characters that can be cut. */
+
+#define LF 0x0a
+#define CR 0x0d
+#define TAB 0x09
+#define BS 0x08
+#define SP 0x20
+#define DEL 0x7f
+#define BSLASH '\\'
+
+#define isNewline(c) (c=='\n')
+#define isWhiteSpace(c) ( c==' ' || c=='\t' || c=='\n' || c=='\r' )
+
+#include <Xw/TextEdit.h>
+
+typedef int XwTextLineRange ;
+
+#include "SourceP.h"
+#include "DisplayP.h"
+
+/* NOTE: more of the following information will eventually be moved
+ to the files TESourceP.h and TEDisplayP.h.
+ */
+
+/* Private TextEdit Definitions */
+
+typedef int (*ActionProc)();
+
+typedef XwSelectType SelectionArray[20];
+
+typedef struct {
+ unsigned char *string;
+ int value;
+} XwSetValuePair;
+
+
+/*************************************************************************
+*
+* New fields for the TextEdit widget class record
+*
+************************************************************************/
+typedef struct {
+ unsigned char* (*copy_substring)();
+ unsigned char* (*copy_selection)();
+ XtWidgetProc unset_selection;
+ XwSetSProc set_selection;
+ XwEditResult (*replace_text)();
+ XtWidgetProc redraw_text;
+} XwTextEditClassPart;
+
+/*************************************************************************
+*
+* Full class record declaration for TextEdit class
+*
+************************************************************************/
+typedef struct _XwTextEditClassRec {
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwTextEditClassPart textedit_class;
+} XwTextEditClassRec;
+
+extern XwTextEditClassRec XwtexteditClassRec;
+
+/*************************************************************************
+*
+* New fields for the TextEdit widget instance record
+*
+************************************************************************/
+typedef struct _XwTextEditPart {
+ XwSourceType srctype; /* used by args & rm to set source */
+ XwTextSource *source;
+ XwTextSink *sink;
+ XwLineTable lt;
+ XwTextPosition insertPos;
+ XwTextPosition oldinsert;
+ XwTextSelection s;
+ XwScanDirection extendDir;
+ XwTextSelection origSel; /* the selection being modified */
+ SelectionArray sarray; /* Array to cycle for selections. */
+ Dimension leftmargin; /* Width of left margin. */
+ Dimension rightmargin; /* Width of right margin. */
+ Dimension topmargin; /* Width of top margin. */
+ Dimension bottommargin; /* Width of bottom margin. */
+ int options; /* wordbreak, scroll, etc. */
+ Time lasttime; /* timestamp of last processed action */
+ Time time; /* time of last key or button action */
+ Position ev_x, ev_y; /* x, y coords for key or button action */
+ XwTextPosition *updateFrom; /* Array of start positions for update. */
+ XwTextPosition *updateTo; /* Array of end positions for update. */
+ int numranges; /* How many update ranges there are. */
+ int maxranges; /* How many ranges we have space for */
+ Boolean showposition; /* True if we need to show the position. */
+ GC gc;
+ Boolean hasfocus; /* TRUE if we currently have input focus.*/
+ XtCallbackList motion_verification;
+ XtCallbackList modify_verification;
+ XtCallbackList leave_verification;
+ XwWrap wrap_mode;
+ XwWrapForm wrap_form;
+ XwWrapBreak wrap_break;
+ XwScroll scroll_mode;
+ XwScroll scroll_state;
+ XwGrow grow_mode;
+ XwGrow grow_state; /* tells whether further growth should
+ be attempted */
+ Dimension prevW, prevH; /* prev values of window width, height */
+ Boolean visible_insertion ;
+ Boolean update_flag ; /* turn updates on and off */
+ XtCallbackList execute ; /* Execute callback list */
+} XwTextEditPart;
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+****************************************************************/
+
+typedef struct _XwTextEditRec {
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwTextEditPart text;
+} XwTextEditRec;
+
+
+#endif
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/Xw/Toggle.c b/Xw/Toggle.c
new file mode 100644
index 0000000..fa3cdf6
--- /dev/null
+++ b/Xw/Toggle.c
@@ -0,0 +1,858 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Toggle.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains code for primitive widget class: Toggle
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/*
+ * Include files & Static Routine Definitions
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/ToggleP.h>
+#include <Xw/Toggle.h>
+#include <X11/StringDefs.h>
+#include <X11/keysymdef.h>
+
+#define SPACE_FACTOR 3
+#define T_BW 2
+
+static void Redisplay();
+static Boolean SetValues();
+static void ClassInitialize();
+static void Initialize();
+static void Destroy();
+static void Toggle();
+static void Select();
+static void Unselect();
+static void DrawToggle();
+static void Resize();
+static void DrawDiamondButton();
+static void GetSelectGC();
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: default translation table for class: Toggle
+ * -----------
+ *
+ * Matches events with string descriptors for internal routines.
+ *
+ *************************************<->***********************************/
+
+
+static char defaultTranslations[] =
+ "<EnterWindow>: enter() \n\
+ <LeaveWindow>: leave() \n\
+ <Btn1Down>: toggle() \n\
+ <Key>Select: toggle()";
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: action list for class: Toggle
+ * -----------
+ *
+ * Matches string descriptors with internal routines.
+ *
+ *************************************<->***********************************/
+
+static XtActionsRec actionsList[] =
+{
+ {"toggle", (XtActionProc) Toggle},
+ {"select", (XtActionProc) Select},
+ {"unselect", (XtActionProc) Unselect},
+ {"enter", (XtActionProc) _XwPrimitiveEnter},
+ {"leave", (XtActionProc) _XwPrimitiveLeave},
+};
+
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: resource list for class: Toggle
+ * -----------
+ *
+ * Provides default resource settings for instances of this class.
+ * To get full set of default settings, examine resouce list of super
+ * classes of this class.
+ *
+ *************************************<->***********************************/
+
+static XtResource resources[] =
+{
+ {
+ XtNsquare, XtCSquare, XtRBoolean, sizeof (Boolean),
+ XtOffset (XwToggleWidget, toggle.square),
+ XtRString, "True"
+ },
+
+ {
+ XtNselectColor, XtCForeground, XtRPixel, sizeof (Pixel),
+ XtOffset (XwToggleWidget, toggle.select_color),
+ XtRString, "Black"
+ }
+};
+
+
+
+/*************************************<->*************************************
+ *
+ *
+ * Description: global class record for instances of class: Toggle
+ * -----------
+ *
+ * Defines default field settings for this class record.
+ *
+ *************************************<->***********************************/
+
+XwToggleClassRec XwtoggleClassRec = {
+ {
+/* core_class fields */
+ /* superclass */ (WidgetClass) &XwbuttonClassRec,
+ /* class_name */ "Toggle",
+ /* widget_size */ sizeof(XwToggleRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ _XwRealize,
+ /* actions */ actionsList,
+ /* num_actions */ XtNumber(actionsList),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterlv */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ }
+};
+WidgetClass XwtoggleWidgetClass = (WidgetClass)&XwtoggleClassRec;
+
+/*************************************<->*************************************
+ *
+ * ComputeSpace (w, redisplay)
+ *
+ * Description:
+ * -----------
+ * Compute allowable space to display label and/or toggle.
+ * If this function is used in redisplay (i.e. redisplay
+ * flag is true), compute space for label as well as toggle.
+ * Compute for toggle only if redisplay flag is FALSE.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * redisplay = flag indicating routine is called from Redisplay()
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XClearArea()
+ * _XwHighlightBorder()
+ * _XwUnhighlightBorder()
+ *************************************<->***********************************/
+static void ComputeSpace(w, redisplay)
+ Widget w;
+ Boolean redisplay;
+{
+ XwToggleWidget cbox = (XwToggleWidget)w;
+ Boolean clipHeight, clipWidth;
+ int x, available_width, available_height;
+
+ /* COMPUTE SPACE FOR DRAWING TOGGLE */
+
+ if (redisplay)
+ {
+ available_width = Max(0, (int)cbox->core.width - 2*
+ ((int)cbox->button.internal_width +
+ cbox->primitive.highlight_thickness));
+
+ /* SEE IF WE NEED TO CLIP THIS LABEL ON RIGHT */
+
+ if (((int)cbox->button.label_width +
+ (int)cbox->button.label_height +
+ (int)cbox->button.label_height/SPACE_FACTOR) > available_width)
+ clipWidth = True;
+ else
+ clipWidth = False;
+
+ }
+ else
+ {
+ available_width = Max(0,((int)cbox->core.width - 2*
+ ((int)cbox->button.internal_width +
+ cbox->primitive.highlight_thickness) -
+ (int)cbox->button.label_width -
+ (int)cbox->button.label_height/SPACE_FACTOR));
+
+ /* SEE IF WE NEED TO CLIP THIS LABEL ON RIGHT */
+
+ if ((int)cbox->button.label_height > available_width)
+ clipWidth = True;
+ else
+ clipWidth = False;
+ }
+
+ available_height = Max(0, (int)cbox->core.height - 2*
+ ((int)cbox->button.internal_height +
+ cbox->primitive.highlight_thickness));
+
+
+ /* SEE IF WE NEED TO CLIP THIS LABEL ON TOP AND/OR BOTTOM */
+
+ if ((int)cbox->button.label_height > available_height)
+ clipHeight = True;
+ else
+ clipHeight = False;
+
+ if (clipWidth)
+ {
+ x = (int)cbox->core.width - cbox->primitive.highlight_thickness -
+ (int)cbox->button.internal_width;
+
+ if ((cbox->button.label_location != XwRIGHT) && redisplay)
+ x -= Min((int)cbox->button.label_height,
+ Max(0, (int)cbox->core.height -
+ 2*(cbox->primitive.highlight_thickness +
+ (int)cbox->button.internal_height)));
+
+
+ XClearArea (XtDisplay(w), XtWindow(w), x, 0,
+ ((int)cbox->core.width - x), cbox->core.height, FALSE);
+ }
+
+ if (clipHeight)
+ {
+ XClearArea (XtDisplay(w), XtWindow(w), 0,0, cbox->core.width,
+ (cbox->primitive.highlight_thickness +
+ cbox->button.internal_height), FALSE);
+ XClearArea (XtDisplay(w), XtWindow(w), 0,
+ ((int)cbox->core.height -
+ cbox->primitive.highlight_thickness -
+ (int)cbox->button.internal_height), cbox->core.width,
+ (cbox->primitive.highlight_thickness +
+ cbox->button.internal_height), FALSE);
+ }
+
+ if (cbox->primitive.highlighted)
+ _XwHighlightBorder(w);
+ else if (cbox->primitive.display_highlighted)
+ _XwUnhighlightBorder(w);
+
+ /* REDRAW THE TOGGLE ON LABEL LOCATION LEFT CONDITIONS AND RECURSIVELY
+ CALL THIS FUNCTION. THIS ENSURES VISIBILITY OF THE TOGGLE */
+ if ((cbox->button.label_location != XwRIGHT) && redisplay)
+ {
+ DrawToggle(w, FALSE);
+ ComputeSpace(w, FALSE);
+ }
+
+} /* ComputeSpace */
+
+
+/*************************************<->*************************************
+ *
+ * Toggle (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * When this Toggle is selected, toggle the activation state
+ * (i.e., draw it as active if it was not active and draw it as
+ * inactive if it was active). Generate the correct callbacks
+ * in response.
+ *
+ * NOTE: this code assumes that instances do not receive selection
+ * events when insensitive.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * DrawToggle() [Toggle.c]
+ * ComputeSpace() [Toggle.c]
+ * XtCallCallbacks()
+ *************************************<->***********************************/
+
+static void Toggle(w,event)
+ Widget w;
+ XEvent *event;
+{
+ XwToggleWidget cbox = (XwToggleWidget)w;
+
+ cbox->button.set = (cbox->button.set == TRUE) ? FALSE : TRUE;
+ DrawToggle(w, FALSE);
+ ComputeSpace(w, FALSE);
+ XFlush(XtDisplay(w));
+ if (cbox->button.set == TRUE)
+ XtCallCallbacks (w, XtNselect, NULL);
+ else
+ XtCallCallbacks (w, XtNrelease, NULL);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Select (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * Mark Toggle as selected, (i.e., draw it as active)
+ * Generate the correct callbacks.
+ *
+ * NOTE: this code assumes that instances do not receive selection
+ * events when insensitive.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * DrawToggle() [Toggle.c]
+ * ComputeSpace() [Toggle.c]
+ * XtCallCallbacks()
+ *************************************<->***********************************/
+
+static void Select(w,event)
+ Widget w;
+ XEvent *event;
+{
+ XwToggleWidget cbox = (XwToggleWidget)w;
+
+ cbox->button.set = TRUE;
+ DrawToggle(w, FALSE);
+ ComputeSpace(w,FALSE);
+ XFlush(XtDisplay(w));
+ XtCallCallbacks (w, XtNselect, NULL);
+}
+
+
+/*************************************<->*************************************
+ *
+ * Unselect (w, event) PRIVATE
+ *
+ * Description:
+ * -----------
+ * When this Toggle is unselected draw it as inactive.
+ * Generate the correct callbacks.
+ *
+ * NOTE: this code assumes that instances do not receive selection
+ * events when insensitive.
+ *
+ * Inputs:
+ * ------
+ * w = widget instance that was selected.
+ * event = event record
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * DrawToggle() [Toggle.c]
+ * ComputeSpace() [Toggle.c]
+ * XtCallCallbacks()
+ *************************************<->***********************************/
+
+static void Unselect(w,event)
+ Widget w;
+ XEvent *event;
+{
+ XwToggleWidget cbox = (XwToggleWidget)w;
+
+ cbox->button.set = FALSE;
+ DrawToggle(w, FALSE);
+ ComputeSpace(w,FALSE);
+ XFlush(XtDisplay(w));
+ XtCallCallbacks (w, XtNrelease, NULL);
+}
+
+
+
+
+/************************************************************************
+ *
+ * GetSelectGC
+ * Get the graphics context to be used to fill the interior of
+ * a square or diamond when selected.
+ *
+ ************************************************************************/
+
+static void GetSelectGC (tw)
+XwToggleWidget tw;
+
+{
+ XGCValues values;
+
+ values.foreground = tw -> toggle.select_color;
+ values.background = tw -> core.background_pixel;
+ values.fill_style = FillSolid;
+
+ tw -> toggle.select_GC =
+ XtGetGC ((Widget)tw, GCForeground | GCBackground | GCFillStyle, &values);
+
+}
+
+
+
+
+/*************************************<->*************************************
+ *
+ * Resize
+ *
+ * Description:
+ * -----------
+ * A resize event has been generated. Recompute location of button
+ * elements.
+ *
+ * Inputs:
+ * ------
+ * w = widget to be resized.
+ *
+ *************************************<->***********************************/
+
+static void Resize(w)
+ Widget w;
+{
+ register XwButtonWidget aButton = (XwButtonWidget) w;
+ int direction = aButton->button.label_location;
+
+ switch (direction)
+ {
+ case XwRIGHT:
+ aButton->button.label_x = aButton->button.internal_width +
+ aButton->primitive.highlight_thickness +
+ aButton->button.label_height +
+ aButton->button.label_height/SPACE_FACTOR;
+ break;
+
+ default:
+ aButton->button.label_x = aButton->button.internal_width +
+ aButton->primitive.highlight_thickness;
+ }
+
+ aButton->button.label_y =
+ (((int)aButton->core.height - (int)aButton->button.label_height) >> 1)
+ + aButton->button.font->max_bounds.ascent;
+}
+
+/*************************************<->*************************************
+ *
+ * Initialize
+ *
+ * Description:
+ * -----------
+ * If the core height and width fields are set to 0, treat that as a flag
+ * and compute the optimum size for this button. Then using what ever
+ * the core fields are set to, compute the text placement fields.
+ * Make sure that the label location field is properly set for the
+ * Resize call.
+ *************************************<->***********************************/
+static void Initialize (request, new)
+ Widget request, new;
+{
+ XwToggleWidget cbox = (XwToggleWidget) new;
+
+ if ((cbox->button.label_location != XwLEFT) &&
+ (cbox->button.label_location != XwRIGHT))
+ {
+ cbox->button.label_location = XwLEFT;
+ XtWarning ("XwToggle Initialize: invalid label location setting.");
+ }
+
+ if (request->core.width == 0) cbox->core.width +=
+ cbox->button.label_width +
+ 2 * cbox->button.internal_width + /* white space */
+ cbox->button.label_height + /* size of box */
+ cbox->button.label_height/SPACE_FACTOR + /* space */
+ 2 * cbox->primitive.highlight_thickness;
+
+ if (request->core.height == 0) cbox->core.height +=
+ cbox->button.label_height + 2 * cbox->button.internal_height
+ + 2 * cbox->primitive.highlight_thickness;
+
+/* dana change */
+ if (!cbox->toggle.square) cbox->core.height += 2;
+
+ GetSelectGC (new);
+ Resize (new);
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * Destroy
+ * Free toggle's graphic context.
+ *
+ ************************************************************************/
+
+static void Destroy (tw)
+XwToggleWidget tw;
+
+{
+ XtDestroyGC (tw -> toggle.select_GC);
+}
+
+
+
+
+
+/*************************************<->*************************************
+ *
+ * DrawToggle(w)
+ *
+ * Description:
+ * -----------
+ * Depending on the state of this widget, draw the Toggle.
+ *
+ *
+ * Inputs:
+ * ------
+ * w = widget to be (re)displayed.
+ *
+ *************************************<->***********************************/
+
+static void DrawToggle(w, all)
+ XwToggleWidget w;
+ Boolean all; /* redo all, or just center? */
+{
+ int x, y, edge;
+
+ /***************************************************************
+ * Determine whether label should appear to the left or
+ * the right of the box and set label X coordinate accordingly.
+ ****************************************************************/
+
+ edge = Min((int)w->button.label_height,
+ Max(0, (int)w->core.height - 2*(w->primitive.highlight_thickness
+ + (int)w->button.internal_height)));
+
+ if (w->button.label_location == XwRIGHT)
+ x= w->button.internal_width + w->primitive.highlight_thickness;
+ else
+ x= Max(0, (int)w->core.width - (int)w->button.internal_width
+ - w->primitive.highlight_thickness - edge); /* size of box */
+
+ y= Max(0, ((int)w->core.height - edge) / 2);
+
+ if (w->toggle.square)
+ {
+ _XwDrawBox (XtDisplay (w), XtWindow (w),
+ w -> button.normal_GC, T_BW,
+ x, y, edge, edge);
+ if (edge > 6) XFillRectangle (XtDisplay ((Widget) w),
+ XtWindow ((Widget) w),
+ ((w->button.set) ? w -> toggle.select_GC :
+ w -> button.inverse_GC),
+ x+3, y+3, edge-6, edge-6);
+ }
+ else
+ DrawDiamondButton ((XwButtonWidget) w, x-1, y-1, edge+2,
+ w -> button.normal_GC,
+ ((w->button.set) ?
+ w -> toggle.select_GC :
+ w -> button.inverse_GC));
+}
+
+
+
+
+/*************************************<->*************************************
+ *
+ * ClassInitialize
+ *
+ * Description:
+ * -----------
+ * Set fields in primitive class part of our class record so that
+ * the traversal code can invoke our button select procedures.
+ *
+ *************************************<->***********************************/
+static void ClassInitialize()
+{
+ XwtoggleClassRec.primitive_class.select_proc = (XwEventProc) Select;
+ XwtoggleClassRec.primitive_class.release_proc = (XwEventProc) Unselect;
+ XwtoggleClassRec.primitive_class.toggle_proc = (XwEventProc) Toggle;
+}
+
+
+/*************************************<->*************************************
+ *
+ * Redisplay (w, event)
+ *
+ * Description:
+ * -----------
+ * Cause the widget, identified by w, to be redisplayed.
+ *
+ *
+ * Inputs:
+ * ------
+ * w = widget to be redisplayed;
+ * event = event structure identifying need for redisplay on this
+ * widget.
+ *
+ * Outputs:
+ * -------
+ *
+ * Procedures Called
+ * -----------------
+ * XDrawString()
+ * DrawToggle() [Toggle.c]
+ * ComputeSpace() [Toggle.c]
+ *************************************<->***********************************/
+
+static void Redisplay(w, event)
+ Widget w;
+ XEvent *event;
+{
+ register XwToggleWidget cbox = (XwToggleWidget) w;
+
+ if (cbox->button.label_len > 0)
+ XDrawString( XtDisplay(w), XtWindow(w), cbox->button.normal_GC,
+ cbox->button.label_x, cbox->button.label_y,
+ cbox->button.label, cbox->button.label_len);
+ DrawToggle(cbox, TRUE);
+ ComputeSpace(w, TRUE);
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * SetValues(current, request, new)
+ *
+ * Description:
+ * -----------
+ * This is the set values procedure for the Toggle class. It is
+ * called last (the set values rtnes for its superclasses are called
+ * first).
+ *
+ *
+ * Inputs:
+ * ------
+ * current = original widget;
+ * request = copy of current (?);
+ * new = copy of request which reflects changes made to it by
+ * set values procedures of its superclasses;
+ *
+ *
+ *************************************<->***********************************/
+
+static Boolean SetValues(current, request, new)
+ Widget current, request, new;
+{
+ XwToggleWidget curcbox = (XwToggleWidget) current;
+ XwToggleWidget newcbox = (XwToggleWidget) new;
+ Boolean flag = FALSE; /* our return value */
+
+
+ /**********************************************************************
+ * Calculate the window size: The assumption here is that if
+ * the width and height are the same in the new and current instance
+ * record that those fields were not changed with set values. Therefore
+ * its okay to recompute the necessary width and height. However, if
+ * the new and current do have different width/heights then leave them
+ * alone because that's what the user wants.
+ *********************************************************************/
+
+ if ((curcbox->core.width == newcbox->core.width) &&
+ (_XwRecomputeSize(current, new)))
+ {
+ newcbox->core.width =
+ newcbox->button.label_width +2*newcbox->button.internal_width
+ + newcbox->button.label_height +
+ newcbox->button.label_height/SPACE_FACTOR +
+ 2 * newcbox->primitive.highlight_thickness;
+ flag = TRUE;
+ }
+
+ if ((curcbox->core.height == newcbox->core.height) &&
+ (_XwRecomputeSize(current, new)))
+ {
+ newcbox->core.height =
+ newcbox->button.label_height + 2*newcbox->button.internal_height +
+ 2 * newcbox->primitive.highlight_thickness;
+ flag = TRUE;
+ }
+
+
+ if (curcbox -> toggle.select_color != newcbox -> toggle.select_color)
+ {
+ XtDestroyGC (newcbox -> toggle.select_GC);
+ GetSelectGC (newcbox);
+ flag = True;
+ }
+
+
+ if (curcbox -> toggle.square != newcbox -> toggle.square)
+ {
+ flag = True;
+ }
+
+
+ Resize(new); /* fix label x and label y positioning */
+ return(flag);
+}
+
+
+
+
+
+/************************************************************************
+ *
+ * DrawDiamondButton()
+ * The dimond drawing routine. Used in place of primitives
+ * draw routine when toggle's square flag is False.
+ *
+ ************************************************************************/
+
+
+static void DrawDiamondButton (bw, x, y, size, borderGC, centerGC)
+XwButtonWidget bw;
+int x, y, size;
+GC borderGC, centerGC;
+
+
+{
+ XSegment seg[8];
+ XPoint pt[5];
+ int midX, midY;
+
+ if (size % 2 == 0)
+ size--;
+
+ midX = x + (size + 1) / 2;
+ midY = y + (size + 1) / 2;
+
+
+ /* The top segments */
+
+ seg[0].x1 = x; /* 1 */
+ seg[0].y1 = midY - 1;
+ seg[0].x2 = midX - 1; /* 2 */
+ seg[0].y2 = y;
+
+ seg[1].x1 = x + 1; /* 3 */
+ seg[1].y1 = midY - 1;
+ seg[1].x2 = midX - 1; /* 4 */
+ seg[1].y2 = y + 1;
+
+ seg[2].x1 = midX - 1; /* 5 */
+ seg[2].y1 = y;
+ seg[2].x2 = x + size - 1; /* 6 */
+ seg[2].y2 = midY - 1;
+
+ seg[3].x1 = midX - 1; /* 7 */
+ seg[3].y1 = y + 1;
+ seg[3].x2 = x + size - 2; /* 8 */
+ seg[3].y2 = midY - 1;
+
+
+ /* The bottom segments */
+
+ seg[4].x1 = x; /* 9 */
+ seg[4].y1 = midY - 1;
+ seg[4].x2 = midX - 1; /* 10 */
+ seg[4].y2 = y + size - 1;
+
+ seg[5].x1 = x + 1; /* 11 */
+ seg[5].y1 = midY - 1;
+ seg[5].x2 = midX - 1; /* 12 */
+ seg[5].y2 = y + size - 2;
+
+ seg[6].x1 = midX - 1; /* 13 */
+ seg[6].y1 = y + size - 1;
+ seg[6].x2 = x + size - 1; /* 14 */
+ seg[6].y2 = midY - 1;
+
+ seg[7].x1 = midX - 1; /* 15 */
+ seg[7].y1 = y + size - 2;
+ seg[7].x2 = x + size - 2; /* 16 */
+ seg[7].y2 = midY - 1;
+
+ XDrawSegments (XtDisplay ((Widget) bw), XtWindow ((Widget) bw),
+ borderGC, &seg[2], 2);
+
+ XDrawSegments (XtDisplay ((Widget) bw), XtWindow ((Widget) bw),
+ borderGC, &seg[4], 4);
+
+ XDrawSegments (XtDisplay ((Widget) bw), XtWindow ((Widget) bw),
+ borderGC, &seg[0], 2);
+
+
+ pt[0].x = x + 3;
+ pt[0].y = midY - 1;
+ pt[1].x = midX - 1;
+ pt[1].y = y + 3;
+ pt[2].x = x + size - 4;
+ pt[2].y = midY - 1;
+ pt[3].x = midX - 2;
+ pt[3].y = y + size - 4;
+
+ XFillPolygon (XtDisplay ((Widget) bw), XtWindow ((Widget) bw),
+ centerGC, pt, 4, Convex, CoordModeOrigin);
+}
diff --git a/Xw/Toggle.h b/Xw/Toggle.h
new file mode 100644
index 0000000..1e36928
--- /dev/null
+++ b/Xw/Toggle.h
@@ -0,0 +1,44 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Toggle.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for applications using the
+ ** toggle widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Toggle Widget
+ *
+ ***********************************************************************/
+
+extern WidgetClass XwtoggleWidgetClass;
+
+typedef struct _XwToggleClassRec *XwToggleWidgetClass;
+typedef struct _XwToggleRec *XwToggleWidget;
+
+
+
+
+
+
diff --git a/Xw/ToggleP.h b/Xw/ToggleP.h
new file mode 100644
index 0000000..9adedcd
--- /dev/null
+++ b/Xw/ToggleP.h
@@ -0,0 +1,82 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: ToggleP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for Toggle class, used by
+ ** widgets which are subclasses of the toggle widget
+ ** or which need to get direct access to the instance
+ ** and class fields of the toggle widget.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+/********************************************
+ *
+ * No new fields need to be defined
+ * for the Toggle widget class record
+ *
+ ********************************************/
+
+typedef struct {int foo;} XwToggleClassPart;
+
+
+/****************************************************
+ *
+ * Full class record declaration for Toggle class
+ *
+ ****************************************************/
+typedef struct _XwToggleClassRec {
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwButtonClassPart button_class;
+ XwToggleClassPart toggle_class;
+} XwToggleClassRec;
+
+
+extern XwToggleClassRec XwtoggleClassRec;
+
+
+/********************************************
+ *
+ * No new fields needed for instance record
+ *
+ ********************************************/
+
+typedef struct _XwTogglePart
+{
+ Boolean square;
+ Pixel select_color;
+ GC select_GC;
+} XwTogglePart;
+
+
+
+/****************************************************************
+ *
+ * Full instance record declaration
+ *
+ ****************************************************************/
+
+typedef struct _XwToggleRec {
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwButtonPart button;
+ XwTogglePart toggle;
+} XwToggleRec;
diff --git a/Xw/Traversal.c b/Xw/Traversal.c
new file mode 100644
index 0000000..53b5852
--- /dev/null
+++ b/Xw/Traversal.c
@@ -0,0 +1,1187 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Traversal.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code to support a generalized traversal handler for
+ ** subclasses of XwManager.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xutil.h>
+#include <X11/StringDefs.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <stdlib.h> /* abs */
+
+
+static int Overlap();
+static void MoveNext();
+static void MovePrev();
+static void MoveTraversal();
+static void Start();
+static void Home();
+static void TraverseToChild ();
+static void ClearKbdFocus();
+static Widget RightCheck();
+static Widget LeftCheck();
+static Widget UpCheck();
+static Widget DownCheck();
+static Widget ValidChoice();
+static Boolean _XwManagerIsTraversable();
+
+
+/* Structures used to maintain the traversal checklist */
+
+typedef enum {
+ XwVERIFY_ONLY,
+ XwADD_TO_CHOSEN_LIST,
+ XwADD_TO_ACTIVE_LIST,
+ XwCLEAR_ACTIVE_LIST
+} XwValidChoiceActions;
+
+typedef enum {
+ XwNONE,
+ XwCHOSEN,
+ XwACTIVE
+} XwEntryType;
+
+typedef struct {
+ Widget widget;
+ XwEntryType type;
+} _XwCheckListEntry;
+
+
+/*
+ * Globals used to maintain a list of those widgets already checked
+ * during a traversal request.
+ */
+
+_XwCheckListEntry * _XwCheckList = NULL;
+int _XwCheckListSize = 0;
+int _XwCheckListIndex = 0;
+
+/*
+
+A manager's traversal handler will be invoked with:
+
+ Upper Left Point: (x1, y1)
+ Lower Right Point: (x2, y2)
+ Direction: XwTRAVERSE_CURRENT
+ XwTRAVERSE_LEFT
+ XwTRAVERSE_RIGHT
+ XwTRAVERSE_UP
+ XwTRAVERSE_DOWN
+ XwTRAVERSE_NEXT
+ XwTRAVERSE_PREV
+ XwTRAVERSE_HOME
+ XwTRAVERSE_NEXT_TOP
+
+
+
+
+A manager has an active child which may be NULL. Widgets under
+consideration to receive the keyboard focus are called candidate widgets.
+In order to be a candidate, a widget must be traversable. This means
+that it must be:
+
+ 1) a subclass of primitive, and
+ sensitive (it and its ancestor)
+ visible
+ managed
+ have its "mapped_when_managed" flag set to TRUE, and
+ traversal_type=XwHIGHLIGHT_TRAVERSAL
+
+ 2) a composite with a traversable primitive
+
+
+
+
+Step 1: See if the manager contains any children which are traversable.
+ If not, set the "active_child" to NULL and
+ if the parent of this manager is a subclass of manager AND
+ that parent has traversal on, then invoke its traversal
+ handling procedure directly, otherwise return focus to
+ the root.
+
+ <<<<NOTE TEST WHETHER THIS IS THE CORRECT THING TO DO, WE
+ MAY NEED 2 DIFFERENT ACTIONS DEPENDING ON THE FOCUS MODEL
+ IN EFFECT.>>>>
+
+ If we do have someone who can accept the focus, then continue.
+
+
+Step 2: The caller of this procedure supplies POINT1, POINT2 and the
+ DIRECTION. Pass control to the specified direction handler.
+
+*/
+
+
+
+/**********************************/
+/* Globals for Traversal Routines */
+/**********************************/
+static int widget_type;
+static XwManagerWidget parent;
+static Boolean parent_is_manager;
+
+void mgr_traversal (mgr, ul, lr, direction)
+
+ XwManagerWidget mgr;
+ XPoint ul, lr;
+ int direction;
+
+{
+ XPoint newUl, newLr;
+
+ parent = (XwManagerWidget)mgr->core.parent;
+ parent_is_manager = XtIsSubclass((Widget)parent,XwmanagerWidgetClass);
+
+ if (direction == XwTRAVERSE_NEXT_TOP)
+ {
+ if (parent_is_manager)
+ {
+ newUl.x = newUl.y = newLr.x = newLr.y = 0;
+
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, newUl, newLr, direction);
+ }
+ else
+ {
+ XtCallCallbacks((Widget)mgr, XtNnextTop, NULL);
+ }
+ return;
+ }
+
+
+ if ((_XwFindTraversablePrim (mgr) == FALSE) ||
+ (!_XwManagerIsTraversable(mgr)))
+ {
+ if (mgr->manager.active_child != NULL)
+ mgr->manager.active_child = (Widget)NULL;
+
+
+ if (parent_is_manager && parent->manager.traversal_on)
+ {
+ newUl.x = ul.x + mgr->core.x;
+ newUl.y = ul.y + mgr->core.y;
+ newLr.x = lr.x + mgr->core.x;
+ newLr.y = lr.y + mgr->core.y;
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, newUl, newLr, direction);
+ }
+ else
+ ClearKbdFocus((Widget) mgr);
+ return;
+ }
+
+ /************************************
+ *
+ * THERE IS A CHILD TO TRAVERSE TO,
+ * DETERMINE DIRECTION & DO TRAVERSAL
+ *
+ ************************************/
+ switch(direction)
+ {
+ case XwTRAVERSE_NEXT:
+ MoveNext((XwManagerWidget)mgr,ul, lr, direction); return;
+ case XwTRAVERSE_PREV:
+ MovePrev((XwManagerWidget)mgr,ul, lr, direction); return;
+ case XwTRAVERSE_DOWN:
+ case XwTRAVERSE_UP:
+ case XwTRAVERSE_RIGHT:
+ case XwTRAVERSE_LEFT:
+ MoveTraversal((XwManagerWidget)mgr,ul, lr, direction); return;
+ case XwTRAVERSE_CURRENT:
+ Start((XwManagerWidget)mgr, ul, lr ,direction); return;
+ case XwTRAVERSE_HOME:
+ Home((XwManagerWidget)mgr, ul, lr ,direction); return;
+ }
+}
+
+/*
+
+DIRECTION = RIGHT (All other directions are just variations of this)
+=================
+
+Step 1) Find the widget to the right of the active child.
+
+If widget A is the current active child and its upper left and lower right
+points are defined by (x1,y1) and (x2,y2) respectively; and widget B is
+a candidate widget whose upper left and lower right points are defined by
+(x1',y1') and (x2',y2'). Then widget B is to the right of widget A
+
+ IFF ((x1 < x1') OR (if (x1 = x1') then (x2' > x2))
+ AND (y1 <= y2') AND (y2 >= y1')
+
+If there is more than 1 candidate then choose the candidate with the
+smallest value for:
+
+ (x1' - x1)
+
+If 2 or more candidates have the same value for (x1'-x1) then choose the
+candidate with the smallest value for:
+
+ |(x2' - x2)|
+
+If 2 or more candidates have the same value for |(x2'-x2)| then choose
+the candidate with the largest overlap of widget A along its y dimension:
+
+
+ if (y2' >= y2)
+ then
+ if (y1' <= y1)
+ then
+ overlap = height of active child
+ else
+ overlap = y2 - y1'
+ else
+ if (y1' <= y1)
+ then
+ overlap = y2' - y1
+ else
+ overlap = height of candidate
+
+If 2 or more candidates have the same overlap then choose the widget with
+the smallest value for y1'.
+
+If 2 or more candidates have the same value for y1' then choose the widget with
+the smallest value for y2'.
+
+It should not be possible for 2 candidates to get this far since it would
+mean that one exactly overlaps the other, which should mean that the
+visibility flag of the obscured widget should be FALSE (thus making it
+un-traversable), however, if we do get this far, arbitrarily choose the
+first candidate.
+
+
+Step 2) If no widget is to the right of the active child then:
+
+ if widget A's grandparent is a subclass of XwManager
+ then
+ -set manager's active child field to NULL
+ -invoke grandparent's traversal handler with:
+
+ Upper Left Point: x1=x1+parent's x coordinate
+ y1=y1+parent's y coordinate
+
+
+ Lower Right Point: x2=x2+parent's x coordinate
+ y2=y2+parent's y coordinate
+
+ Direction = XwTRAVERSE_RIGHT
+
+
+
+ if widget A's grandparent is NOT a subclass of XwManager
+ then
+ -set manager's active child field to NULL
+ -invoke parent's traversal handler with:
+
+ Upper Left Point: x1=0, y1=y1;
+
+ Lower Right Point: x2=0, y2=y2;
+
+ Direction = XwTRAVERSE_RIGHT
+
+
+Step 3) If a candidate has been chosen, then set it as the active child of
+ its parent and:
+
+ if it is a subclass of XwPrimitive
+ then
+ -give it keyboard focus using XSetInputFocus function.
+
+
+ else (its a manager subclass)
+ -invoke its traversal handler with:
+
+ Upper Left Point: x1=x1 - x1'; y1=y1 - y1'
+
+ Lower Right Point: x2=x2 - x2'; y2=y2 - y2'
+
+ Direction = XwTRAVERSE_RIGHT
+
+*/
+
+static void MoveTraversal (mw, ul, lr, direction)
+
+ XwManagerWidget mw;
+ XPoint ul, lr;
+ int direction;
+{
+ Widget candidate, chosen;
+ int chosen_widget_type;
+ int i=(-1);
+ XPoint cand_ul, cand_lr;
+
+ chosen = NULL;
+
+ while (++i < mw->composite.num_children)
+ {
+ candidate = mw->composite.children[i];
+ if ((candidate != mw->manager.active_child) &&
+ XwTestTraversability(candidate, &widget_type))
+ {
+ cand_ul.x = candidate->core.x;
+ cand_ul.y = candidate->core.y;
+ cand_lr.x = candidate->core.x + candidate->core.width +
+ (candidate->core.border_width << 1) - 1;
+ cand_lr.y = candidate->core.y + candidate->core.height +
+ (candidate->core.border_width << 1) - 1;
+
+ switch (direction)
+ {
+ case XwTRAVERSE_RIGHT:
+ chosen=RightCheck (chosen, ul, lr, candidate, cand_ul, cand_lr);
+ break;
+
+ case XwTRAVERSE_LEFT:
+ chosen = LeftCheck (chosen, ul, lr, candidate, cand_ul, cand_lr);
+ break;
+
+ case XwTRAVERSE_UP:
+ chosen = UpCheck (chosen, ul, lr, candidate, cand_ul, cand_lr);
+ break;
+
+ case XwTRAVERSE_DOWN:
+ chosen = DownCheck (chosen, ul, lr, candidate, cand_ul, cand_lr);
+ break;
+
+ }
+ }
+
+ if (chosen == candidate) chosen_widget_type = widget_type;
+ }
+
+ if (chosen == NULL) /* no widget in specified direction! */
+ {
+ /*
+ * Since our parent is a manager, see if there is another sibling
+ * of ours which can be traversed to.
+ */
+ mw->manager.active_child = NULL;
+ if (parent_is_manager) /* really grandparent of active child */
+ {
+ /* Add ourselves to the active list */
+ ValidChoice (mw, mw, XwADD_TO_ACTIVE_LIST);
+
+ ul.x += mw->core.x;
+ ul.y += mw->core.y;
+ lr.x += mw->core.x;
+ lr.y += mw->core.y;
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, ul, lr, direction);
+ }
+ else
+ {
+ /* Wrap to opposite edge */
+
+ /* Clear the active traversal list */
+ ValidChoice (NULL, NULL, XwCLEAR_ACTIVE_LIST);
+
+ switch (direction)
+ {
+ case XwTRAVERSE_RIGHT:
+ {
+ ul.x = -10000;
+ lr.x = -10000;
+ break;
+ }
+
+ case XwTRAVERSE_LEFT:
+ {
+ ul.x = mw->core.width + (mw->core.border_width << 1);
+ lr.x = mw->core.width + (mw->core.border_width << 1);
+ break;
+ }
+
+ case XwTRAVERSE_UP:
+ {
+ ul.y = mw->core.height + (mw->core.border_width << 1);
+ lr.y = mw->core.height + (mw->core.border_width << 1);
+ break;
+ }
+
+ case XwTRAVERSE_DOWN:
+ {
+ ul.y = -10000;
+ lr.y = -10000;
+ break;
+ }
+ }
+
+ (*(((XwManagerWidgetClass)(mw->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)mw, ul, lr, direction);
+ }
+ }
+ else
+ {
+ ValidChoice(chosen, chosen, XwADD_TO_CHOSEN_LIST);
+ TraverseToChild(mw, chosen, ul, lr, direction);
+ }
+}
+
+
+
+static void Start (mw, ul, lr, direction)
+ XwManagerWidget mw;
+ XPoint ul, lr;
+ int direction;
+{
+ Widget candidate, chosen;
+ int i=0;
+
+ chosen = NULL;
+
+ /* To prevent endless recursion, see if the child has already been checked */
+ if ((mw->manager.active_child != NULL) &&
+ (ValidChoice(NULL, mw->manager.active_child, XwVERIFY_ONLY)))
+ {
+ if (XwTestTraversability(mw->manager.active_child, &widget_type))
+ {
+ ValidChoice(chosen, chosen, XwADD_TO_CHOSEN_LIST);
+ TraverseToChild (mw, mw->manager.active_child, ul, lr, direction);
+ }
+ }
+ else
+ {
+ while (i < mw->composite.num_children)
+ {
+ candidate = mw->composite.children[i];
+ if (XwTestTraversability(candidate, &widget_type))
+ {
+ if (chosen==NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+
+ {
+ if ((candidate->core.x+candidate->core.y) <
+ (chosen->core.x+chosen->core.y))
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+
+ }
+ }
+ i++;
+ }
+
+ ValidChoice(chosen, chosen, XwADD_TO_CHOSEN_LIST);
+ TraverseToChild(mw, chosen, ul, lr, direction);
+
+ }
+}
+
+
+
+/* We are guaranteed that there is a child to traverse to! */
+
+static void MoveNext (mw, ul, lr, direction)
+ XwManagerWidget mw;
+ XPoint ul, lr;
+ int direction;
+{
+ int i=0;
+
+ parent = (XwManagerWidget)mw->core.parent;
+ parent_is_manager = XtIsSubclass((Widget)parent,XwmanagerWidgetClass);
+
+ if (mw->manager.active_child != NULL)
+ {
+ ul.x = (mw->manager.active_child)->core.x;
+ ul.y = (mw->manager.active_child)->core.y;
+ lr.x = ul.x + (mw->manager.active_child)->core.width +
+ ((mw->manager.active_child)->core.border_width << 1) - 1;
+ lr.y = ul.y + (mw->manager.active_child)->core.height +
+ ((mw->manager.active_child)->core.border_width << 1) - 1;
+
+ /* FIND INDEX OF CURRENTLY ACTIVE CHILD */
+ while ((mw->composite.children[i] != mw->manager.active_child) &&
+ (i < mw->composite.num_children))i++;
+ }
+ else
+ /* START LOOKING AT START OF LIST + 1 (TO ALLOW FOR 1ST DECREMENT)
+ * NOTE: THIS ALSO TAKES CARE OF THE DEGENERATE CASE WHEN THERE
+ * ARE NO CHILDREN. IN THIS CASE THE PARENT "MUST" BE A SUBCLASS
+ * OF XWMANAGER OR WE WOULD NEVER HAVE GOTTEN HERE.
+ */
+ i = -1;
+
+ /*
+ * IF WE'VE COME TO THE END OF THE WIDGET LIST AND THE PARENT
+ * IS ALSO A SUBCLASS OF XWMANAGER, THEN INVOKE THE PARENT'S
+ * TRAVERSAL HANDLER, OTHERWISE, WRAP THE COUNTER TO START LOOKING
+ * AT THE LIST AGAIN.
+ */
+ if (++i >= mw->composite.num_children)
+ {
+ if (parent_is_manager)
+ {
+ mw->manager.active_child = NULL;
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, ul, lr, direction);
+ return;
+ }
+ else
+ i=0;
+ }
+
+ /* FIND NEXT TRAVERSABLE WIDGET --THERE MUST BE ONE! */
+ while (! XwTestTraversability(mw->composite.children[i], &widget_type))
+ if (++i >= mw->composite.num_children) i=0;
+
+ TraverseToChild(mw, mw->composite.children[i], ul, lr, direction);
+}
+
+
+
+
+/* We are guaranteed that there is a child to traverse to! */
+
+static void MovePrev (mw, ul, lr, direction)
+ XwManagerWidget mw;
+ XPoint ul, lr;
+ int direction;
+{
+ int i;
+
+ parent = (XwManagerWidget)mw->core.parent;
+ parent_is_manager = XtIsSubclass((Widget)parent,XwmanagerWidgetClass);
+
+ if (mw->manager.active_child != NULL)
+ {
+ ul.x = (mw->manager.active_child)->core.x;
+ ul.y = (mw->manager.active_child)->core.y;
+ lr.x = ul.x + (mw->manager.active_child)->core.width +
+ ((mw->manager.active_child)->core.border_width << 1) - 1;
+ lr.y = ul.y + (mw->manager.active_child)->core.height +
+ ((mw->manager.active_child)->core.border_width << 1) - 1;
+
+ /* FIND INDEX OF CURRENTLY ACTIVE CHILD */
+ i=mw->composite.num_children -1;
+ while ((mw->composite.children[i] != mw->manager.active_child) &&
+ (i > 0))i--;
+ }
+ else
+ /* START LOOKING AT END OF LIST + 1 (TO ALLOW FOR 1ST DECREMENT)
+ * NOTE: THIS ALSO TAKES CARE OF THE DEGENERATE CASE WHEN THERE
+ * ARE NO CHILDREN. IN THIS CASE THE PARENT "MUST" BE A SUBCLASS
+ * OF XWMANAGER OR WE WOULD NEVER HAVE GOTTEN HERE.
+ */
+ i = mw->composite.num_children;
+
+
+ /*
+ * IF WE'VE COME TO THE END OF THE WIDGET LIST AND THE PARENT
+ * IS ALSO A SUBCLASS OF XWMANAGER, THEN INVOKE THE PARENT'S
+ * TRAVERSAL HANDLER, OTHERWISE, WRAP THE COUNTER TO START LOOKING
+ * AT THE LIST AGAIN.
+ */
+ if (--i < 0)
+ {
+ if (parent_is_manager)
+ {
+ mw->manager.active_child = NULL;
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, ul, lr, direction);
+ return;
+ }
+ else
+ i = (mw->composite.num_children)-1;
+ }
+
+
+ /* FIND NEXT TRAVERSABLE WIDGET --THERE MUST BE ONE! */
+ while (! XwTestTraversability(mw->composite.children[i], &widget_type))
+ if (--i < 0) i = (mw->composite.num_children)-1;
+
+ TraverseToChild (mw, mw->composite.children[i], ul, lr, direction);
+}
+
+
+
+
+
+
+static int Overlap (pt1, pt2, w)
+ XPoint pt1, pt2;
+ Widget w;
+{
+ XPoint pt1_prime, pt2_prime;
+
+ pt1_prime.x = w->core.x;
+ pt1_prime.y = w->core.y;
+ pt2_prime.x = w->core.x + w->core.width + (w->core.border_width << 1) - 1;
+ pt2_prime.y = w->core.y + w->core.height + (w->core.border_width << 1) - 1;
+
+ if (pt2_prime.y >= pt2.y)
+ {
+ if (pt1_prime.y <= pt1.y)
+ return(pt2.y - pt1.y);
+ else
+ return(pt2.y - pt1_prime.y);
+ }
+ else
+ {
+ if (pt1_prime.y <= pt1.y)
+ return(pt2_prime.y - pt1.y);
+ else
+ return(w->core.height);
+ }
+}
+
+
+/* CALCULATE OVERLAP IN X DIRECTION */
+static int xOverlap (pt1, pt2, w)
+ XPoint pt1, pt2;
+ Widget w;
+{
+ XPoint pt1_prime, pt2_prime;
+
+ pt1_prime.x = w->core.x;
+ pt1_prime.y = w->core.y;
+ pt2_prime.x = w->core.x + w->core.width + (w->core.border_width << 1) - 1;
+ pt2_prime.y = w->core.y + w->core.height + (w->core.border_width << 1) - 1;
+
+ if (pt2_prime.x >= pt2.x)
+ {
+ if (pt1_prime.x <= pt1.x)
+ return(pt2.x - pt1.x);
+ else
+ return(pt2.x - pt1_prime.x);
+ }
+ else
+ {
+ if (pt1_prime.x <= pt1.x)
+ return(pt2_prime.x - pt1.x);
+ else
+ return(w->core.width);
+ }
+}
+
+
+/*
+ * HOME: If I get called there is NO guarantee that there is something
+ * which is traversable. This is due to the way that X generates
+ * its visiblity events; the manager is notified before its children.
+ * Thus, the manager may still think it has traversable children,
+ * when in fact it doesn't. That is why we must have a special
+ * check to see that a child really was chosen.
+ */
+
+static void Home (mw, ul, lr, direction)
+ XwManagerWidget mw;
+ XPoint ul, lr;
+ int direction;
+{
+ Widget candidate, chosen;
+ int chosen_widget_type;
+ int i=(-1);
+
+ chosen = NULL;
+
+ /*
+ search thru list of children to find child which is closest to
+ origin and which is traversable.
+ */
+ while (++i < mw->composite.num_children)
+ {
+ candidate = mw->composite.children[i];
+ if (XwTestTraversability(candidate, &widget_type))
+ {
+ if (chosen==NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if ((candidate->core.x+candidate->core.y) <
+ (chosen->core.x+chosen->core.y))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ }
+ }
+ if (chosen == candidate) chosen_widget_type = widget_type;
+ }
+
+ /*
+ * If the closest to home widget is NOT the current active child then
+ * make it the active child. Otherwise, try and go up a level.
+ */
+
+ if (mw->manager.active_child != chosen)
+ {
+ mw->manager.active_child=chosen;
+ ValidChoice(chosen, chosen, XwADD_TO_CHOSEN_LIST);
+
+ if (chosen_widget_type == XwPRIMITIVE)
+
+ TraverseToChild(mw, chosen, ul, lr, direction);
+
+ else
+ (*(((XwManagerWidgetClass)(chosen->core.widget_class)) ->
+ manager_class.traversal_handler))
+ (chosen, ul, lr, direction);
+
+ }
+ else /* WE ARE ALREADY HOMED IN THIS MANAGER, GO UP */
+ {
+ if (parent_is_manager) /* really grandparent of active child */
+ {
+ mw->manager.active_child = NULL;
+ (*(((XwManagerWidgetClass)(parent->core.widget_class)) ->
+ manager_class.traversal_handler))
+ ((Widget)parent, ul, lr, direction);
+ }
+
+ /* If our parent is not a manager, then we are already
+ as HOME as we are going to get, so do nothing. */
+ }
+}
+
+
+
+static void TraverseToChild (mw, chosen, ul, lr, direction)
+ XwManagerWidget mw;
+ Widget chosen;
+ XPoint ul, lr;
+ int direction;
+
+{
+ Widget topmost_manager= (Widget) mw;
+
+ mw->manager.active_child = chosen;
+ if (XtIsSubclass(chosen, XwprimitiveWidgetClass))
+ {
+ while ((topmost_manager->core.parent != NULL) &&
+ XtIsSubclass((Widget)(topmost_manager->core.parent),
+ XwmanagerWidgetClass))
+ topmost_manager = topmost_manager->core.parent;
+
+ XtSetKeyboardFocus(topmost_manager, chosen);
+ }
+ else
+ {
+ ul.x -= chosen->core.x;
+ ul.y -= chosen->core.y;
+ lr.x -= chosen->core.x;
+ lr.y -= chosen->core.y;
+ (*(((XwManagerWidgetClass)(chosen->core.widget_class)) ->
+ manager_class.traversal_handler))
+ (chosen, ul, lr, direction);
+ }
+
+}
+
+
+
+/*************************************<->*************************************
+ *
+ * XwMoveFocus(w)
+ *
+ * Description:
+ * -----------
+ * Useful when an application has created multiple top level
+ * hierarchies of widgets, is using keyboard traversal and
+ * wishes to move between them.
+ *
+ *
+ * Inputs: w = widget which is the new top level widget.
+ * ------
+ *
+ *************************************<->***********************************/
+
+
+void XwMoveFocus(w)
+
+ Widget w;
+
+{
+ /* MOVE MOUSE INTO NEW WINDOW HIERARCHY */
+ XWarpPointer(XtDisplay(w), None, XtWindow(w),0,0,0,0,1,1);
+
+ /* SET FOCUS HERE, SHOULD WORK FOR ALL FOCUS MODES */
+ XSetInputFocus (XtDisplay(w), XtWindow(w), RevertToParent,
+ CurrentTime);
+
+
+}
+
+static Widget RightCheck (chosen, ul, lr, candidate, cand_ul, cand_lr)
+
+ Widget chosen, candidate;
+ XPoint ul, lr, cand_ul, cand_lr;
+
+{
+ if (((ul.x < cand_ul.x) || ((ul.x == cand_ul.x) && (lr.x < cand_lr.x))) &&
+ (ul.y <= cand_lr.y) && (lr.y >= cand_ul.y))
+ {
+ if (chosen == NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (chosen->core.x > cand_ul.x)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (cand_ul.x == chosen->core.x)
+ {
+ if (abs(cand_lr.x - lr.x) <
+ abs((chosen->core.x+chosen->core.width +
+ (chosen->core.border_width << 1))-lr.x))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (abs(cand_lr.x - lr.x) ==
+ abs((chosen->core.x+chosen->core.width+
+ (chosen->core.border_width << 1))-lr.x))
+
+ if (Overlap(ul, lr, candidate) > Overlap(ul, lr, chosen))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (Overlap(ul,lr,candidate) == Overlap(ul,lr,chosen))
+ if (cand_ul.y < chosen->core.y)
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.y == chosen->core.y)
+ if (cand_lr.y < chosen->core.y +
+ chosen->core.height +
+ (chosen->core.border_width << 1))
+ chosen = ValidChoice(chosen,
+ candidate,
+ XwVERIFY_ONLY);
+ }
+ }
+ }
+ }
+ }
+ return (chosen);
+}
+
+
+static Widget LeftCheck (chosen, ul, lr, candidate, cand_ul, cand_lr)
+
+ Widget chosen, candidate;
+ XPoint ul, lr, cand_ul, cand_lr;
+
+{
+ if (((cand_ul.x < ul.x) || ((cand_ul.x == ul.x) && (cand_lr.x < lr.x))) &&
+ (ul.y <= cand_lr.y) && (lr.y >= cand_ul.y))
+ {
+ if (chosen == NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.x > chosen->core.x)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (cand_ul.x == chosen->core.x)
+ {
+ if (abs(cand_lr.x - lr.x) < abs(chosen->core.x+
+ chosen->core.width+(chosen->core.border_width<<1)-lr.x))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (abs(cand_lr.x - lr.x) == abs(chosen->core.x+
+ chosen->core.width+(chosen->core.border_width<<1)-lr.x))
+ if (Overlap(ul, lr, candidate) > Overlap(ul, lr, chosen))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (Overlap(ul,lr,candidate) == Overlap(ul,lr,chosen))
+ if (cand_ul.y > chosen->core.y)
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.y == chosen->core.y)
+ if (cand_lr.y >
+ chosen->core.y + chosen->core.height +
+ (chosen->core.border_width << 1))
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ }
+ }
+ }
+ }
+ }
+ return (chosen);
+}
+
+
+static Widget UpCheck (chosen, ul, lr, candidate, cand_ul, cand_lr)
+
+ Widget chosen, candidate;
+ XPoint ul, lr, cand_ul, cand_lr;
+
+{
+ if (((cand_ul.y < ul.y) || ((cand_ul.y == ul.y) && (cand_lr.y < lr.y))) &&
+ (ul.x <= cand_lr.x) && (lr.x >= cand_ul.x))
+ {
+ if (chosen == NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.y > chosen->core.y)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (cand_ul.y == chosen->core.y)
+ {
+ if (abs(cand_lr.y - lr.y) < abs(chosen->core.y+
+ chosen->core.height+(chosen->core.border_width<<1)-lr.y))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (abs(cand_lr.y - lr.y) == abs(chosen->core.y+
+ chosen->core.height+(chosen->core.border_width<<1)-lr.y))
+ if (xOverlap(ul, lr, candidate) > xOverlap(ul, lr, chosen))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (xOverlap(ul, lr, candidate) ==
+ xOverlap(ul, lr, chosen))
+ if (cand_ul.x > chosen->core.x)
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.x == chosen->core.x)
+ if (cand_lr.x >
+ chosen->core.x + chosen->core.width +
+ (chosen->core.border_width << 1))
+ chosen = ValidChoice(chosen,candidate,
+ XwVERIFY_ONLY);
+ }
+ }
+ }
+ }
+ }
+ return (chosen);
+}
+
+
+static Widget DownCheck (chosen, ul, lr, candidate, cand_ul, cand_lr)
+
+ Widget chosen, candidate;
+ XPoint ul, lr, cand_ul, cand_lr;
+
+{
+ if (((ul.y < cand_ul.y) || ((ul.y == cand_ul.y) && (lr.y < cand_lr.y))) &&
+ (ul.x <= cand_lr.x) && (lr.x >= cand_ul.x))
+ {
+ if (chosen == NULL)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (chosen->core.y > cand_ul.y)
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (cand_ul.y == chosen->core.y)
+ {
+ if (abs(cand_lr.y - lr.y) <
+ abs((chosen->core.y+chosen->core.height+
+ (chosen->core.border_width << 1))-lr.y))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ if (abs(cand_lr.y - lr.y) ==
+ abs((chosen->core.y+chosen->core.height+
+ (chosen->core.border_width << 1))-lr.y))
+
+ if (xOverlap(ul, lr, candidate) > xOverlap(ul, lr, chosen))
+ chosen = ValidChoice(chosen, candidate, XwVERIFY_ONLY);
+ else
+ {
+ if (xOverlap(ul, lr, candidate) ==
+ xOverlap(ul, lr, chosen))
+ if (cand_ul.x < chosen->core.x)
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ else
+ {
+ if (cand_ul.x == chosen->core.x)
+ if (cand_lr.x <
+ chosen->core.x + chosen->core.width +
+ (chosen->core.border_width << 1))
+ chosen = ValidChoice(chosen, candidate,
+ XwVERIFY_ONLY);
+ }
+ }
+ }
+ }
+
+ }
+ return (chosen);
+}
+
+/*
+ * To prevent the traversal mechanism from getting into an infinite
+ * recursion, we need to keep a list of those widgets already checked
+ * during a given traversal request. If a candidate has already been
+ * checked once, we don't want to give it a second chance. This is
+ * normally a problem only when a traversal request causes the search
+ * to wrap to the opposite edge.
+ *
+ * There are two types of entries maintained on the list: active entries
+ * and chosen entries. An entry is a chosen entry if its parent has
+ * determined that the entry can possible accept the traversal request,
+ * and has thus chosen it to in turn check its children to see if they
+ * can accept the traversal. An entry is an active entry if it is part
+ * of the current traversal path, but it does not have any children which
+ * can currently accept the traversal request; a widget is added to this
+ * list only if it is not already on the chosen list, AND it is passing
+ * the traversal request up to its parent.
+ *
+ * The active list prevents any of the widgets in the current traversal
+ * path from being rechecked by their parent, once they have already
+ * decided they can't accept the traversal request, until the upper most
+ * manager decides to wrap at an edge and start looking again; at this
+ * point, all active entries are cleared from the list, so that they can
+ * have a chance to regain the traversal if no other widget can.
+ *
+ * If an entry is marked as being on the
+ * active list, and then a request comes to place it on the chosen list,
+ * then the move will occur. If, however, a widget is on the chosen list,
+ * and it asks to move to the active list, this will be denied, since we
+ * don't want this widget to have the chance of being chosen again. An
+ * entry on the active list has not yet been chosen, it mearly was part of
+ * the original active child list.
+ */
+
+static Widget ValidChoice (chosen, candidate, action)
+
+ Widget chosen, candidate;
+ XwValidChoiceActions action;
+
+{
+ int i;
+
+ /* If candidate is already on the list, then don't reprocess it */
+ if (action == XwVERIFY_ONLY)
+ {
+ /* Don't consider it unless it has some traversable primitives */
+ if (XtIsSubclass(candidate, XwmanagerWidgetClass) &&
+ _XwFindTraversablePrim(candidate) == False)
+ return (chosen);
+
+ for (i = 0; i < _XwCheckListIndex; i++)
+ {
+ if ((_XwCheckList[i].widget == candidate) &&
+ (_XwCheckList[i].type != XwNONE))
+ return (chosen);
+ }
+ }
+
+ if ((action == XwADD_TO_CHOSEN_LIST) || (action == XwADD_TO_ACTIVE_LIST))
+ {
+ /* See if already on the list; then just update type field */
+ for (i = 0; i < _XwCheckListIndex; i++)
+ {
+ if (_XwCheckList[i].widget == candidate)
+ {
+ if (_XwCheckList[i].type != XwCHOSEN)
+ {
+ _XwCheckList[_XwCheckListIndex].type =
+ (action == XwADD_TO_CHOSEN_LIST) ? XwCHOSEN : XwACTIVE;
+ }
+ return (candidate);
+ }
+ }
+
+ /* See if the list needs to grow */
+ if (_XwCheckListIndex >= _XwCheckListSize)
+ {
+ _XwCheckListSize += 20;
+ _XwCheckList = (_XwCheckListEntry *)XtRealloc((char *)_XwCheckList,
+ (sizeof(_XwCheckListEntry) * _XwCheckListSize));
+ }
+
+ /* Add to the checklist */
+ _XwCheckList[_XwCheckListIndex].widget = candidate;
+ _XwCheckList[_XwCheckListIndex].type = (action == XwADD_TO_CHOSEN_LIST) ?
+ XwCHOSEN : XwACTIVE;
+ _XwCheckListIndex++;
+ }
+
+ /* Clear all entries which were not on the chosen list */
+ if (action == XwCLEAR_ACTIVE_LIST)
+ {
+ for (i = 0; i < _XwCheckListIndex; i++)
+ {
+ if (_XwCheckList[i].type == XwACTIVE)
+ _XwCheckList[i].type = XwNONE;
+ }
+ }
+
+ return (candidate);
+}
+
+void _XwInitCheckList()
+
+{
+ /* Initialize the traversal checklist */
+ if (_XwCheckList == NULL)
+ {
+ _XwCheckList=(_XwCheckListEntry *)XtMalloc(sizeof(_XwCheckListEntry)*20);
+ _XwCheckListSize = 20;
+ }
+
+ /* Always reset the checklist to the beginning */
+ _XwCheckListIndex = 0;
+}
+
+
+/*
+ * This function verifies that all of the ancestors of a manager
+ * have traversal enabled.
+ */
+
+static Boolean _XwManagerIsTraversable (w)
+
+ XwManagerWidget w;
+
+{
+ while (w && XtIsSubclass((Widget)w, XwmanagerWidgetClass))
+ {
+ if ((w->manager.traversal_on == FALSE) || (w->core.visible == False))
+ return (False);
+
+ w = (XwManagerWidget)w->core.parent;
+ }
+
+ return (True);
+}
+
+
+static void ClearKbdFocus (topmost_manager)
+
+ Widget topmost_manager;
+
+{
+ while ((topmost_manager->core.parent != NULL) &&
+ XtIsSubclass((Widget)(topmost_manager->core.parent),
+ XwmanagerWidgetClass))
+ topmost_manager = topmost_manager->core.parent;
+
+ XtSetKeyboardFocus(topmost_manager, NULL);
+}
diff --git a/Xw/WorkSpace.c b/Xw/WorkSpace.c
new file mode 100644
index 0000000..e01d493
--- /dev/null
+++ b/Xw/WorkSpace.c
@@ -0,0 +1,325 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: WorkSpace.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Contains code for workSpace widget class.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <X11/StringDefs.h>
+#include <X11/keysymdef.h>
+#include <X11/IntrinsicP.h>
+#include <X11/Intrinsic.h>
+#include <Xw/Xw.h>
+#include <Xw/XwP.h>
+#include <Xw/WorkSpace.h>
+#include <Xw/WorkSpaceP.h>
+
+
+/* Event procedures referenced in the actions list */
+
+static void KeyDown();
+static void KeyUp();
+static void Select();
+static void Release();
+
+
+/* Default translation table and action list */
+
+static char defaultTranslations[] =
+ "<KeyDown>: keydown()\n\
+ <KeyUp>: keyup()\n\
+ <BtnDown>: select()\n\
+ <BtnUp>: release()\n\
+ <EnterWindow>: enter()\n\
+ <LeaveWindow>: leave()";
+
+
+static XtActionsRec actionsList[] =
+{
+ { "keydown", (XtActionProc) KeyDown },
+ { "keyup", (XtActionProc) KeyUp },
+ { "select", (XtActionProc) Select },
+ { "release", (XtActionProc) Release },
+ { "enter", (XtActionProc) _XwPrimitiveEnter },
+ { "leave", (XtActionProc) _XwPrimitiveLeave },
+ };
+
+
+/* Resource list for WorkSpace */
+
+static XtResource resources[] =
+{
+ {
+ XtNexpose, XtCCallback, XtRCallback, sizeof (caddr_t),
+ XtOffset (XwWorkSpaceWidget, workSpace.expose),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNresize, XtCCallback, XtRCallback, sizeof (caddr_t),
+ XtOffset (XwWorkSpaceWidget, workSpace.resize),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNkeyDown, XtCCallback, XtRCallback, sizeof (caddr_t),
+ XtOffset (XwWorkSpaceWidget, workSpace.key_down),
+ XtRPointer, (caddr_t) NULL
+ },
+
+ {
+ XtNkeyUp, XtCCallback, XtRCallback, sizeof (caddr_t),
+ XtOffset (XwWorkSpaceWidget, workSpace.key_up),
+ XtRPointer, (caddr_t) NULL
+ }
+};
+
+
+/* Static routine definitions */
+
+static void Initialize();
+static void Redisplay();
+static void Resize();
+static void Destroy();
+static Boolean SetValues();
+
+
+/* The WorkSpace class record definition */
+
+XwWorkSpaceClassRec XwworkSpaceClassRec =
+{
+ {
+ (WidgetClass) &XwprimitiveClassRec, /* superclass */
+ "XwWorkSpace", /* class_name */
+ sizeof(XwWorkSpaceRec), /* widget_size */
+ NULL, /* class_initialize */
+ NULL, /* class_part_initialize */
+ FALSE, /* class_inited */
+ (XtInitProc) Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ _XwRealize, /* realize */
+ actionsList, /* actions */
+ XtNumber(actionsList), /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ TRUE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ (XtWidgetProc) Destroy, /* destroy */
+ (XtWidgetProc) Resize, /* resize */
+ (XtExposeProc) Redisplay, /* expose */
+ (XtSetValuesFunc) SetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback private */
+ defaultTranslations, /* tm_table */
+ NULL, /* query_geometry */
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+
+ {
+ NULL, /* Primitive border_highlight */
+ NULL, /* Primitive border_unhighlight */
+ NULL, /* Primitive select_proc */
+ NULL, /* Primitive release_proc */
+ NULL, /* Primitive toggle_proc */
+ }
+};
+
+WidgetClass XwworkSpaceWidgetClass = (WidgetClass) &XwworkSpaceClassRec;
+
+
+
+
+/************************************************************************
+ *
+ * Initialize
+ * The main widget instance initialization routine.
+ *
+ ************************************************************************/
+
+static void Initialize (request, new)
+XwWorkSpaceWidget request, new;
+
+{
+ if (request -> core.width == 0)
+ new -> core.width += 20;
+ if (request -> core.height == 0)
+ new -> core.height += 20;
+}
+
+
+
+
+/************************************************************************
+ *
+ * Redisplay
+ * Draw the traversal/enter border, and
+ * invoke the application exposure callbacks.
+ *
+ ************************************************************************/
+
+static void Redisplay (hw, event, region)
+XwWorkSpaceWidget hw;
+XEvent * event;
+Region region;
+
+{
+ if (hw -> primitive.highlighted)
+ _XwHighlightBorder (hw);
+ else if (hw -> primitive.display_highlighted)
+ _XwUnhighlightBorder (hw);
+
+ XtCallCallbacks ((Widget)hw, XtNexpose, region);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Resize
+ * Invoke the application resize callbacks.
+ *
+ ************************************************************************/
+
+static void Resize (hw)
+XwWorkSpaceWidget hw;
+
+{
+ XtCallCallbacks ((Widget)hw, XtNresize, NULL);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Destroy
+ * Remove the callback lists.
+ *
+ ************************************************************************/
+
+static void Destroy (hw)
+XwWorkSpaceWidget hw;
+
+{
+ XtRemoveAllCallbacks ((Widget)hw, XtNexpose);
+ XtRemoveAllCallbacks ((Widget)hw, XtNresize);
+ XtRemoveAllCallbacks ((Widget)hw, XtNkeyDown);
+}
+
+
+
+
+/************************************************************************
+ *
+ * SetValues
+ *
+ ************************************************************************/
+
+static Boolean SetValues (current, request, new)
+XwWorkSpaceWidget current, request, new;
+
+{
+ return (False);
+}
+
+
+
+
+/************************************************************************
+ *
+ * KeyDown
+ * This function processes key presses occuring on the workSpace.
+ *
+ ************************************************************************/
+
+static void KeyDown (hw, event)
+XwWorkSpaceWidget hw;
+XButtonPressedEvent * event;
+
+{
+ XtCallCallbacks ((Widget)hw, XtNkeyDown, event);
+}
+
+
+/************************************************************************
+ *
+ * KeyUp
+ * This function processes key releases occuring on the workSpace.
+ *
+ ************************************************************************/
+
+static void KeyUp (hw, event)
+XwWorkSpaceWidget hw;
+XButtonPressedEvent * event;
+
+{
+ XtCallCallbacks ((Widget)hw, XtNkeyUp, event);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Select
+ * This function processes selections occuring on the workSpace.
+ *
+ ************************************************************************/
+
+static void Select (hw, event)
+XwWorkSpaceWidget hw;
+XButtonPressedEvent * event;
+
+{
+ XtCallCallbacks ((Widget)hw, XtNselect, event);
+}
+
+
+
+
+/************************************************************************
+ *
+ * Release
+ * This function processes releases occuring on the workSpace.
+ *
+ ************************************************************************/
+
+static void Release (hw, event)
+XwWorkSpaceWidget hw;
+XEvent * event;
+
+{
+ XtCallCallbacks ((Widget)hw, XtNrelease, event);
+}
diff --git a/Xw/WorkSpace.h b/Xw/WorkSpace.h
new file mode 100644
index 0000000..afc0142
--- /dev/null
+++ b/Xw/WorkSpace.h
@@ -0,0 +1,34 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: WorkSpace.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Public include file for WorkSpace class widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/* WorkSpace Widget */
+
+extern WidgetClass XwworkSpaceWidgetClass;
+
+typedef struct _XwWorkSpaceClassRec * XwWorkSpaceWidgetClass;
+typedef struct _XwWorkSpaceRec * XwWorkSpaceWidget;
+
diff --git a/Xw/WorkSpaceP.h b/Xw/WorkSpaceP.h
new file mode 100644
index 0000000..91be92b
--- /dev/null
+++ b/Xw/WorkSpaceP.h
@@ -0,0 +1,67 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: WorkSpaceP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Private include file for the WorkSpace class
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/* WorkSpace class structure */
+
+typedef struct _XwWorkSpaceClassPart
+{
+ int foo; /* No new fields needed */
+} XwWorkSpaceClassPart;
+
+
+/* Full class record declaration for WorkSpace class */
+
+typedef struct _XwWorkSpaceClassRec
+{
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwWorkSpaceClassPart workSpace_class;
+} XwWorkSpaceClassRec;
+
+extern XwWorkSpaceClassRec XwworkSpaceClassRec;
+
+
+/* The WorkSpace instance record */
+
+typedef struct _XwWorkSpacePart
+{
+ XtCallbackList resize;
+ XtCallbackList expose;
+ XtCallbackList key_down;
+ XtCallbackList key_up;
+} XwWorkSpacePart;
+
+
+/* Full instance record declaration */
+
+typedef struct _XwWorkSpaceRec
+{
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwWorkSpacePart workSpace;
+} XwWorkSpaceRec;
+
diff --git a/Xw/Xw.h b/Xw/Xw.h
new file mode 100644
index 0000000..a8fed14
--- /dev/null
+++ b/Xw/Xw.h
@@ -0,0 +1,470 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: Xw.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: This include file contains public defines and structures
+ ** needed by all XToolkit applications using the X Widget Set.
+ ** Included in the file are the definitions for all common
+ ** resource types, defines for resource or arg list values,
+ ** and the class and instance record definitions for all meta
+ ** classes.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+#ifndef _XtXw_h
+#define _XtXw_h
+
+/************************************************************************
+ *
+ * Good 'ole Max and Min from the defunct <X11/Misc.h>
+ *
+ ************************************************************************/
+#define Max(x, y) (((x) > (y)) ? (x) : (y))
+#define Min(x, y) (((x) > (y)) ? (y) : (x))
+
+/************************************************************************
+ *
+ * Resource manager definitions
+ *
+ ************************************************************************/
+
+#define XtRLong "Long"
+
+#define XtNtraversalOn "traversalOn"
+#define XtCTraversalOn "TraversalOn"
+
+#define XtNtraversalType "traversalType"
+#define XtCTraversalType "TraversalType"
+#define XtRTraversalType "TraversalType"
+
+#define XtNhighlightStyle "highlightStyle"
+#define XtCHighlightStyle "HighlightStyle"
+#define XtNhighlightTile "highlightTile"
+#define XtCHighlightTile "HighlightTile"
+#define XtRHighlightStyle "HighlightStyle"
+#define XtNhighlightThickness "highlightThickness"
+#define XtCHighlightThickness "HighlightThickness"
+#define XtNhighlightColor "highlightColor"
+
+#define XtNbackgroundTile "backgroundTile"
+#define XtCBackgroundTile "BackgroundTile"
+
+#define XtNcursor "cursor"
+
+#define XtNrecomputeSize "recomputeSize"
+#define XtCRecomputeSize "RecomputeSize"
+
+#define XtNlayout "layout"
+#define XtCLayout "Layout"
+#define XtRLayout "Layout"
+
+#define XtRTileType "tileType"
+
+/* #define XtRTranslationTable "TranslationTable" */
+#define XtNlabelLocation "labelLocation"
+#define XtCLabelLocation "LabelLocation"
+#define XtRLabelLocation "LabelLocation"
+#define XtNsensitiveTile "sensitiveTile"
+#define XtCSensitiveTile "SensitiveTile"
+
+#define XtNcolumns "columns"
+#define XtCColumns "Columns"
+#define XtNmode "mode"
+#define XtCMode "Mode"
+#define XtRRCMode "Mode"
+#define XtNset "set"
+#define XtCSet "Set"
+
+#define XtNselect "select"
+#define XtNrelease "release"
+#define XtNnextTop "nextTop"
+
+#define XtNtitleShowing "titleShowing"
+#define XtCTitleShowing "TitleShowing"
+#define XtNmgrTitleOverride "mgrTitleOverride"
+#define XtCTitleOverride "TitleOverride"
+#define XtNtitleType "titleType"
+#define XtCTitleType "TitleType"
+#define XtRTitleType "TitleType"
+#define XtNtitleString "titleString"
+#define XtCTitleString "TitleString"
+#define XtNtitleImage "titleImage"
+#define XtCTitleImage "TitleImage"
+#define XtNfontColor "fontColor"
+#define XtNmnemonic "mnemonic"
+#define XtCMnemonic "Mnemonic"
+#define XtNunderlineTitle "underlineTitle"
+#define XtCUnderlineTitle "UnderlineTitle"
+#define XtNmgrUnderlineOverride "mgrUnderlineOverride"
+#define XtCUnderlineOverride "UnderlineOverride"
+#define XtNunderlinePosition "underlinePosition"
+#define XtCUnderlinePosition "UnderlinePosition"
+#define XtNattachTo "attachTo"
+#define XtCAttachTo "AttachTo"
+#define XtNkbdAccelerator "kbdAccelerator"
+#define XtCKbdAccelerator "KbdAccelerator"
+
+#define XtNassociateChildren "associateChildren"
+#define XtCAssociateChildren "AssociateChildren"
+#define XtNmenuPost "menuPost"
+#define XtCMenuPost "MenuPost"
+#define XtNmenuSelect "menuSelect"
+#define XtCMenuSelect "MenuSelect"
+#define XtNpostAccelerator "postAccelerator"
+#define XtCPostAccelerator "PostAccelerator"
+#define XtNmenuUnpost "menuUnpost"
+#define XtCMenuUnpost "MenuUnpost"
+#define XtNkbdSelect "kbdSelect"
+#define XtCKbdSelect "KbdSelect"
+
+
+/****************************************************************
+ *
+ * TextEdit widget
+ *
+ ****************************************************************/
+
+#define XtNdisplayPosition "displayPosition"
+/* #define XtNinsertPosition "insertPosition" */
+#define XtNleftMargin "leftMargin"
+#define XtNrightMargin "rightMargin"
+#define XtNtopMargin "topMargin"
+#define XtNbottomMargin "bottomMargin"
+/* #define XtNselectionArray "selectionArray"
+#define XtNtextSource "textSource"
+#define XtNselection "selection" */
+#define XtNmaximumSize "maximumSize"
+#define XtCMaximumSize "MaximumSize"
+
+/* #define XtNeditType "editType"
+#define XtNfile "file"
+#define XtNstring "string"
+#define XtNlength "length"
+#define XtNfont "font" */
+#define XtNdiskSrc "disksrc"
+#define XtNstringSrc "stringsrc"
+#define XtNexecute "execute"
+
+#define XtNsourceType "sourceType"
+#define XtCSourceType "SourceType"
+#define XtRSourceType "SourceType"
+
+#define XtNmotionVerification "motionVerification"
+#define XtNmodifyVerification "modifyVerification"
+#define XtNleaveVerification "leaveVerification"
+
+#define XtNwrap "wrap"
+#define XtCWrap "Wrap"
+#define XtRWrap "Wrap"
+
+#define XtNwrapForm "wrapForm"
+#define XtCWrapForm "WrapForm"
+#define XtRWrapForm XtCWrapForm
+
+#define XtNwrapBreak "wrapBreak"
+#define XtCWrapBreak "WrapBreak"
+#define XtRWrapBreak XtCWrapBreak
+
+#define XtNscroll "scroll"
+#define XtCScroll "Scroll"
+#define XtRScroll XtCScroll
+
+#define XtNgrow "grow"
+#define XtCGrow "Grow"
+#define XtRGrow XtCGrow
+
+#define XwAutoScrollOff 0
+#define XwAutoScrollHorizontal 1
+#define XwAutoScrollVertical 2
+#define XwAutoScrollBoth 3 /* must be bitwise OR of horiz. and vert. */
+
+#define XwGrowOff 0
+#define XwGrowHorizontal 1
+#define XwGrowVertical 2
+#define XwGrowBoth 3 /* must be bitwise OR of horiz. and vert. */
+
+/* Valid Label Location Settings for Button */
+
+#define XwRIGHT 0
+#define XwLEFT 1
+#define XwCENTER 2
+
+/* Valid Title Type Values For MenuPane */
+
+#define XwSTRING 0
+#define XwIMAGE 1
+#define XwRECT 2
+
+
+/* New resource manager types */
+
+#define XrmRImage "Image"
+#define XtRImage XrmRImage
+#define XtNalignment "alignment"
+#define XtCAlignment "Alignment"
+#define XtRAlignment "Alignment"
+#define XtNlineSpace "lineSpace"
+#define XtCLineSpace "LineSpace"
+
+#define XtNgravity "gravity"
+#define XtCGravity "Gravity"
+#ifndef XtRGravity
+#define XtRGravity "Gravity"
+#endif
+
+typedef enum {
+ XwALIGN_NONE,
+ XwALIGN_LEFT,
+ XwALIGN_CENTER,
+ XwALIGN_RIGHT
+} XwAlignment;
+
+typedef enum {
+ XwUNKNOWN,
+ XwPULLDOWN,
+ XwTITLE,
+ XwWORK_SPACE
+} XwWidgetType;
+
+/* Form resource definitions */
+
+#define XwHORIZONTAL 0
+#define XwVERTICAL 1
+
+#define XtNxRefName "xRefName"
+#define XtCXRefName "XRefName"
+#define XtNxRefWidget "xRefWidget"
+#define XtCXRefWidget "XRefWidget"
+#define XtNxOffset "xOffset"
+#define XtCXOffset "XOffset"
+#define XtNxAddWidth "xAddWidth"
+#define XtCXAddWidth "XAddWidth"
+#define XtNxVaryOffset "xVaryOffset"
+#define XtCXVaryOffset "XVaryOffset"
+#define XtNxResizable "xResizable"
+#define XtCXResizable "XResizable"
+#define XtNxAttachRight "xAttachRight"
+#define XtCXAttachRight "XAttachRight"
+#define XtNxAttachOffset "xAttachOffset"
+#define XtCXAttachOffset "XAttachOffset"
+
+#define XtNyRefName "yRefName"
+#define XtCYRefName "YRefName"
+#define XtNyRefWidget "yRefWidget"
+#define XtCYRefWidget "YRefWidget"
+#define XtNyOffset "yOffset"
+#define XtCYOffset "YOffset"
+#define XtNyAddHeight "yAddHeight"
+#define XtCYAddHeight "YAddHeight"
+#define XtNyVaryOffset "yVaryOffset"
+#define XtCYVaryOffset "YVaryOffset"
+#define XtNyResizable "yResizable"
+#define XtCYResizable "YResizable"
+#define XtNyAttachBottom "yAttachBottom"
+#define XtCYAttachBottom "YAttachBottom"
+#define XtNyAttachOffset "yAttachOffset"
+#define XtCYAttachOffset "YAttachOffset"
+
+/* MenuBtn esource manager definitions */
+
+#define XtNlabelType "labelType"
+#define XtCLabelType "LabelType"
+#define XtRLabelType "LabelType"
+#define XtNlabelImage "labelImage"
+#define XtCLabelImage "LabelImage"
+#define XtNrectColor "rectColor"
+#define XtCRectColor "RectColor"
+#define XtNrectStipple "rectStipple"
+#define XtCRectStipple "RectStipple"
+#define XtNcascadeImage "cascadeImage"
+#define XtCCascadeImage "CascadeImage"
+#define XtNmarkImage "markImage"
+#define XtCMarkImage "MarkImage"
+#define XtNsetMark "setMark"
+#define XtCSetMark "SetMark"
+#define XtNnoPad "noPad"
+#define XtCNoPad "NoPad"
+#define XtNcascadeOn "cascadeOn"
+#define XtCCascadeOn "CascadeOn"
+#define XtNinvertOnEnter "invertOnEnter"
+#define XtCInvertOnEnter "InvertOnEnter"
+#define XtNmgrOverrideMnemonic "mgrOverrideMnemonic"
+#define XtCMgrOverrideMnemonic "MgrOverrideMnemonic"
+#define XtNcascadeSelect "cascadeSelect"
+#define XtNcascadeUnselect "cascadeUnselect"
+#define XtNmenuMgrId "menuMgrId"
+#define XtCMenuMgrId "MenuMgrId"
+#define XtNhint "hint"
+#define XtCHint "Hint"
+#define XtNhintProc "hintProc"
+#define XtCHintProc "HintProc"
+
+/* Resources for PushButton */
+
+#define XtNinvertOnSelect "invertOnSelect"
+#define XtCInvertOnSelect "InvertOnSelect"
+#define XtNtoggle "toggle"
+#define XtCToggle "Toggle"
+
+/* Resources for Toggle */
+
+#define XtNsquare "square"
+#define XtCSquare "Square"
+#define XtNselectColor "selectColor"
+
+/* WorkSpace resources */
+
+#define XtNexpose "expose"
+#ifndef XtNresize
+#define XtNresize "resize"
+#endif
+#define XtNkeyDown "keyDown"
+#define XtNkeyUp "keyUp"
+
+
+/***********************************************************************
+ *
+ * Cascading MenuPane Widget Resources
+ *
+ ***********************************************************************/
+
+#define XtRTitlePositionType "TitlePositionType"
+#define XtNtitlePosition "titlePosition"
+#define XtCTitlePosition "TitlePosition"
+
+/***********************************************************************
+ *
+ * Popup Menu Manager Widget Resources
+ *
+ ***********************************************************************/
+
+#define XtNstickyMenus "stickyMenus"
+#define XtCStickyMenus "StickyMenus"
+
+/***********************************************************************
+ *
+ * Pulldown Menu Manager Widget Resources
+ *
+ ***********************************************************************/
+
+
+#define XtNallowCascades "allowCascades"
+#define XtCAllowCascades "AllowCascades"
+#define XtNpulldownBarId "pulldownBarId"
+#define XtCPulldownBarId "PulldownBarId"
+
+
+/***********************************************************************
+ *
+ * Cascading MenuPane Widget Attribute Definitions
+ *
+ ***********************************************************************/
+
+#define XwTOP 0x01
+#define XwBOTTOM 0x02
+#define XwBOTH XwTOP|XwBOTTOM
+
+/***********************************************************************
+ *
+ * Static Text resource string definitions
+ *
+ ***********************************************************************/
+#define XtNstrip "strip"
+#define XtCStrip "Strip"
+
+/************************************************************************
+ *
+ * Class record constants for Primitive Widget Meta Class
+ *
+ ************************************************************************/
+
+extern WidgetClass XwprimitiveWidgetClass;
+
+typedef struct _XwPrimitiveClassRec * XwPrimitiveWidgetClass;
+typedef struct _XwPrimitiveRec * XwPrimitiveWidget;
+
+
+/* Tile types used for area filling and patterned text placement */
+
+#define XwFOREGROUND 0
+#define XwBACKGROUND 1
+
+/* Traversal type definitions */
+
+#define XwHIGHLIGHT_OFF 0
+#define XwHIGHLIGHT_ENTER 1
+#define XwHIGHLIGHT_TRAVERSAL 2
+
+
+/* Border highlighting type defines */
+
+#define XwPATTERN_BORDER 1
+#define XwWIDGET_DEFINED 2
+
+
+/* Manager Layout Info */
+
+#define XwIGNORE 0
+#define XwMINIMIZE 1
+#define XwMAXIMIZE 2
+#define XwSWINDOW 3 /* Special Setting for Scrolled Window */
+
+#define XtNwidgetType "widgetType"
+#define XtCWidgetType "WidgetType"
+#define XtRWidgetType "WidgetType"
+
+/************************************************************************
+ *
+ * Class record constants for Meta Class Widgets
+ *
+ ************************************************************************/
+
+extern WidgetClass XwmanagerWidgetClass;
+
+typedef struct _XwManagerClassRec * XwManagerWidgetClass;
+typedef struct _XwManagerRec * XwManagerWidget;
+
+
+
+extern WidgetClass XwbuttonWidgetClass;
+
+typedef struct _XwButtonClassRec * XwButtonWidgetClass;
+typedef struct _XwButtonRec * XwButtonWidget;
+
+
+extern WidgetClass XwmenupaneWidgetClass;
+
+typedef struct _XwMenuPaneClassRec *XwMenuPaneWidgetClass;
+typedef struct _XwMenuPaneRec *XwMenuPaneWidget;
+
+
+extern WidgetClass XwmenumgrWidgetClass;
+
+typedef struct _XwMenuMgrClassRec *XwMenuMgrWidgetClass;
+typedef struct _XwMenuMgrRec *XwMenuMgrWidget;
+
+
+
+#endif
+/* DON'T ADD STUFF AFTER THIS #endif */
+
+
diff --git a/Xw/XwP.h b/Xw/XwP.h
new file mode 100644
index 0000000..a3ce6c9
--- /dev/null
+++ b/Xw/XwP.h
@@ -0,0 +1,605 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: XwP.h
+ **
+ ** Project: X Widgets
+ **
+ ** Description: This include file contains the class and instance record
+ ** definitions for all meta classes. It also contains externs
+ ** for internally shared functions and defines for internally
+ ** shared values.
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1988 by the Massachusetts Institute of Technology
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
+ ** pertaining to distribution of the software without specific, written
+ ** prior permission.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+
+
+/***********************************************************************
+ *
+ * Miscellaneous Private Defines
+ *
+ ***********************************************************************/
+
+#define XwStrlen(s) ((s) ? strlen(s) : 0)
+#define XwBLOCK 10
+#define XwMANAGER 1
+#define XwPRIMITIVE 2
+
+
+/************************************************************************
+ *
+ * The Primitive Widget Class and instance records.
+ *
+ ************************************************************************/
+
+typedef void (*XwEventProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ XEvent* /* event */
+#endif
+);
+
+typedef struct _XwPrimitiveClassPart
+{
+ XtWidgetProc border_highlight;
+ XtWidgetProc border_unhighlight;
+ XwEventProc select_proc;
+ XwEventProc release_proc;
+ XwEventProc toggle_proc;
+ XtTranslations translations;
+} XwPrimitiveClassPart;
+
+typedef struct _XwPrimitiveClassRec
+{
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+} XwPrimitiveClassRec;
+
+extern XwPrimitiveClassRec XwprimitiveClassRec;
+
+#define XtInheritBorderHighlight ((XtWidgetProc) _XtInherit)
+#define XtInheritBorderUnhighlight ((XtWidgetProc) _XtInherit)
+#define XtInheritSelectProc ((XwEventProc) _XtInherit)
+#define XtInheritReleaseProc ((XwEventProc) _XtInherit)
+#define XtInheritToggleProc ((XwEventProc) _XtInherit)
+
+extern void _XwHighlightBorder();
+extern void _XwUnhighlightBorder();
+
+extern void _XwPrimitiveEnter();
+extern void _XwPrimitiveLeave();
+extern void _XwPrimitiveFocusIn();
+extern void _XwPrimitiveFocusOut();
+extern void _XwPrimitiveVisibility();
+extern void _XwPrimitiveUnmap();
+
+extern void _XwTraverseLeft();
+extern void _XwTraverseRight();
+extern void _XwTraverseUp();
+extern void _XwTraverseDown();
+extern void _XwTraverseNext();
+extern void _XwTraversePrev();
+extern void _XwTraverseHome();
+extern void _XwTraverseNextTop();
+
+
+typedef struct _XwPrimitivePart
+{
+ Pixel foreground;
+ int background_tile;
+
+ Cursor cursor;
+
+ int traversal_type;
+ Boolean I_have_traversal;
+
+ int highlight_thickness;
+ int highlight_style;
+ Pixel highlight_color;
+ int highlight_tile;
+
+
+ Boolean recompute_size;
+
+ GC highlight_GC;
+
+ Boolean display_sensitive;
+ Boolean highlighted;
+ Boolean display_highlighted;
+
+ XtCallbackList select;
+ XtCallbackList release;
+ XtCallbackList toggle;
+} XwPrimitivePart;
+
+typedef struct _XwPrimitiveRec
+{
+ CorePart core;
+ XwPrimitivePart primitive;
+} XwPrimitiveRec;
+
+
+
+/************************************************************************
+ *
+ * The Manager Widget Class and instance records.
+ *
+ ************************************************************************/
+
+typedef void (*XwTraversalProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ XPoint, /* ul */
+ XPoint, /* lr */
+ int /* dir */
+#endif
+);
+
+typedef struct _XwManagerClassPart
+{
+ XwTraversalProc traversal_handler;
+ XtTranslations translations;
+} XwManagerClassPart;
+
+typedef struct _XwManagerClassRec
+{
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+} XwManagerClassRec;
+
+extern XwManagerClassRec XwmanagerClassRec;
+
+typedef struct _XwManagerPart
+{
+ Pixel foreground;
+ int background_tile;
+
+ Boolean traversal_on;
+
+ int highlight_thickness;
+
+ GC highlight_GC;
+
+ Widget active_child;
+ WidgetList managed_children;
+ Cardinal num_slots;
+ Cardinal num_managed_children;
+ int layout;
+ XtCallbackList next_top;
+} XwManagerPart;
+
+typedef struct _XwManagerRec
+{
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+} XwManagerRec;
+
+
+#define XtInheritTraversalProc ((XwTraversalProc) _XtInherit)
+
+/**************************************
+ *
+ * Exported Routines from Manager.c
+ *
+ **************************************/
+extern void _XwManagerEnter(); /* start traversal */
+extern void _XwManagerLeave(); /* end traversal */
+extern void _XwManagerFocusIn(); /* focus management */
+extern void _XwManagerVisibility(); /* more focus management */
+extern void _XwManagerUnmap(); /* even more focus management */
+extern Boolean _XwFindTraversablePrim(); /* traversal checking routine */
+extern void _XwReManageChildren(); /* rebuild Managed Children List */
+extern void _XwManagerInsertChild(); /* special insert child routine */
+extern Cardinal _XwInsertOrder(); /* compute position from arglist */
+
+
+/************************************************************************
+ *
+ * Externs and defines for traversal handling functions incorporated
+ * into all primitive widgets.
+ *
+ ************************************************************************/
+
+extern void mgr_traversal();
+extern void _XwDrawBox();
+extern void XwSetFocusPath();
+extern void XwMoveFocus();
+extern void XwProcessTraversal();
+extern void XwSetInputFocus();
+extern void _XwInitCheckList();
+
+
+/* Traversal direction defines */
+
+#define XwTRAVERSE_CURRENT 0
+#define XwTRAVERSE_LEFT 1
+#define XwTRAVERSE_RIGHT 2
+#define XwTRAVERSE_UP 3
+#define XwTRAVERSE_DOWN 4
+#define XwTRAVERSE_NEXT 5
+#define XwTRAVERSE_PREV 6
+#define XwTRAVERSE_HOME 7
+#define XwTRAVERSE_NEXT_TOP 8
+
+
+/**************************************
+ *
+ * Exported Routines from Button.c
+ *
+ **************************************/
+extern void _XwSetTextWidthAndHeight();
+extern void _XwGetNormalGC();
+extern void _XwGetSensitiveGC();
+extern void _XwGetInverseGC();
+extern void _XwInitializeButton();
+extern void _XwRealize();
+extern void _XwResizeButton();
+extern void _XwRegisterName();
+extern Boolean _XwRecomputeSize();
+extern Boolean XwTestTraversability();
+
+/************************************************************************
+ *
+ * New fields for the Button widget class record
+ * and the full class record.
+ *
+ ************************************************************************/
+
+typedef struct _XwButtonClassPart
+{
+ int mumble;
+} XwButtonClassPart;
+
+typedef struct _XwButtonClassRec
+{
+ CoreClassPart core_class;
+ XwPrimitiveClassPart primitive_class;
+ XwButtonClassPart button_class;
+} XwButtonClassRec;
+
+extern XwButtonClassRec XwbuttonClassRec;
+
+
+/************************************************************************
+ *
+ * New fields for the Button instance record and
+ * the full instance record.
+ *
+ ************************************************************************/
+
+typedef struct _XwButtonPart
+{
+ XFontStruct * font;
+ char * label;
+ int label_location;
+ Dimension internal_height;
+ Dimension internal_width;
+ int sensitive_tile;
+ GC normal_GC;
+ GC inverse_GC;
+ Position label_x;
+ Position label_y;
+ Dimension label_width;
+ Dimension label_height;
+ unsigned int label_len;
+ Boolean set;
+ Boolean display_set;
+} XwButtonPart;
+
+typedef struct _XwButtonRec
+{
+ CorePart core;
+ XwPrimitivePart primitive;
+ XwButtonPart button;
+} XwButtonRec;
+
+
+/***********************************************************************
+ *
+ * Inherited functions exported by MenuBtn
+ *
+ ***********************************************************************/
+
+#define XtInheritIdealWidthProc ((XwWidthProc) _XtInherit)
+#define XtInheritUnhighlightProc ((XtWidgetProc) _XtInherit)
+#define XtInheritHighlightProc ((XtWidgetProc) _XtInherit)
+#define XtInheritEnterParentProc ((XtWidgetProc) _XtInherit)
+
+/* Corrected by Steve Langasek (was incompatible with the revised Wprintf()) */
+
+typedef void (*XwStrProc)(
+#if NeedFunctionPrototypes
+ char *format, ... /* hint */
+#endif
+);
+
+/***********************************************************************
+ *
+ * New Fields for the MenuPane widget class record, and
+ * the full class record.
+ *
+ ***********************************************************************/
+
+typedef void (*XwWBoolProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ Boolean /* flag */
+#endif
+);
+
+typedef struct {
+ XwWBoolProc setTraversalFlag;
+} XwMenuPaneClassPart;
+
+/* Full class record declaration */
+typedef struct _XwMenuPaneClassRec {
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwMenuPaneClassPart menu_pane_class;
+} XwMenuPaneClassRec;
+
+extern XwMenuPaneClassRec XwmenupaneClassRec;
+extern Boolean _XwAllAttachesAreSensitive();
+
+#define XtInheritMenuPaneConstraintInit ((XtInitProc) _XtInherit)
+#define XtInheritSetTraversalFlagProc ((XwWBoolProc) _XtInherit)
+
+/***********************************************************************
+ *
+ * New Fields for the MenuPane widget instance record, and
+ * the full class record.
+ *
+ ***********************************************************************/
+
+typedef struct {
+ /* Internal fields */
+ GC titleGC;
+ Widget attachId;
+
+ /* User settable fields */
+ XFontStruct * title_font;
+ String title_string;
+ Boolean title_showing;
+ String attach_to;
+ XImage * titleImage;
+ Boolean title_override;
+ int title_type;
+ String mnemonic;
+ XtCallbackList select;
+} XwMenuPanePart;
+
+
+typedef struct _XwMenuPaneRec {
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwMenuPanePart menu_pane;
+} XwMenuPaneRec;
+
+
+/* New Procedures for _XtInherit, with proper function prototypes */
+
+typedef void (*XwWidthProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ Dimension* /* width */
+#endif
+);
+
+typedef void (*XwWintProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ int /* type */
+#endif
+);
+
+typedef void (*XwWWProc)(
+#if NeedFunctionPrototypes
+ Widget, /* manager */
+ Widget /* pane */
+#endif
+);
+
+typedef void (*XwSelectProc)(
+#if NeedFunctionPrototypes
+ Widget, /* manager */
+ Widget, /* button */
+ String, /* accelerator */
+ unsigned int, /* accelEventType */
+ unsigned int, /* accelDetail */
+ unsigned int /* accelModifiers */
+#endif
+);
+
+typedef void (*XwWWSProc)(
+#if NeedFunctionPrototypes
+ Widget, /* manager */
+ Widget, /* button */
+ String /* accelerator */
+#endif
+);
+
+typedef void (*XwPostProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ Widget, /* widget */
+ Widget, /* widget */
+ Position, /* x */
+ Position /* y */
+#endif
+);
+
+typedef void (*XwSetSProc)(
+#if NeedFunctionPrototypes
+ Widget, /* widget */
+ Position, /* left */
+ Position /* right */
+#endif
+);
+
+/***********************************************************************
+ *
+ * Global functions exported by MapEvent.c
+ *
+ ***********************************************************************/
+
+typedef Boolean (*XwBooleanProc)();
+
+extern Boolean _XwMatchBtnEvent();
+extern Boolean _XwMapBtnEvent();
+extern Boolean _XwMapKeyEvent();
+extern Boolean _XwMatchKeyEvent();
+extern Boolean _XwValidModifier();
+extern String _XwMapToHex();
+extern unsigned long _XwMapFromHex();
+
+extern void _XwSetMappedManagedChildrenList();
+
+#define XtInheritAttachPane ((XwWWSProc) _XtInherit)
+#define XtInheritDetachPane ((XwWWSProc) _XtInherit)
+#define XtInheritAddPane ((XwWWProc) _XtInherit)
+#define XtInheritSetSelectAccelerator ((XwSelectProc) _XtInherit)
+#define XtInheritClearSelectAccelerator ((XwWWProc) _XtInherit)
+#define XtInheritSetPostMnemonic ((XwWWSProc) _XtInherit)
+#define XtInheritClearPostMnemonic ((XwWWProc) _XtInherit)
+#define XtInheritAddButton ((XwWWProc) _XtInherit)
+#define XtInheritSetSelectMnemonic ((XwWWSProc) _XtInherit)
+#define XtInheritClearSelectMnemonic ((XwWWProc) _XtInherit)
+#define XtInheritProcessSelect ((XwBooleanProc) _XtInherit)
+#define XtInheritValidEvent ((XwBooleanProc) _XtInherit)
+#define XtInheritDoICascade ((XwBooleanProc) _XtInherit)
+#define XtInheritSetTitleAttributes ((XwWWProc) _XtInherit)
+#define XtInheritPaneManagedChildren ((XwWWProc) _XtInherit)
+#define XtInheritBtnSensitivityChanged ((XwWWProc) _XtInherit)
+#define XtInheritPaneSensitivityChanged ((XwWWProc) _XtInherit)
+
+/***********************************************************************
+ *
+ * New Fields for the MenuMgr widget class record, and
+ * the full class record.
+ *
+ ***********************************************************************/
+
+typedef struct {
+ XwWWSProc attachPane;
+ XwWWSProc detachPane;
+ XwWWProc addPane;
+ XwSelectProc setSelectAccelerator;
+ XwWWProc clearSelectAccelerator;
+ XwWWSProc setPostMnemonic;
+ XwWWProc clearPostMnemonic;
+ XwWWProc addButton;
+ XwBooleanProc processSelect;
+ XwBooleanProc validEvent;
+ XwBooleanProc doICascade;
+ XwWWSProc setSelectMnemonic;
+ XwWWProc clearSelectMnemonic;
+ XwWWProc setTitleAttributes;
+ XwWWProc paneManagedChildren;
+ XwEventProc traverseLeft;
+ XwEventProc traverseRight;
+ XwEventProc traverseNext;
+ XwEventProc traversePrev;
+ XwEventProc traverseHome;
+ XwEventProc traverseUp;
+ XwEventProc traverseDown;
+ XwEventProc traverseNextTop;
+ XwWWProc btnSensitivityChanged;
+ XwWWProc paneSensitivityChanged;
+} XwMenuMgrClassPart;
+
+/* Full class record declaration */
+typedef struct _XwMenuMgrClassRec {
+ CoreClassPart core_class;
+ CompositeClassPart composite_class;
+ ConstraintClassPart constraint_class;
+ XwManagerClassPart manager_class;
+ XwMenuMgrClassPart menu_mgr_class;
+} XwMenuMgrClassRec;
+
+extern XwMenuMgrClassRec XwmenumgrClassRec;
+
+/***********************************************************************
+ *
+ * New Fields for the MenuMgr widget instance record, and
+ * the full class record.
+ *
+ ***********************************************************************/
+
+/* Structure used by menu mgr to store keyboard accelerators */
+typedef struct {
+ String accelString;
+ unsigned int accelEventType;
+ KeyCode accelKey;
+ unsigned int accelModifiers;
+ Widget menuBtn;
+} XwKeyAccel;
+
+/* Structure used by menu mgr to store pending attach requests */
+typedef struct {
+ String menuBtnName;
+ Widget menupaneId;
+} XwAttachList;
+
+typedef struct {
+ /* Internal fields */
+ unsigned int postEventType;
+ unsigned int postButton;
+ unsigned int postModifiers;
+ unsigned int selectEventType;
+ unsigned int selectButton;
+ unsigned int selectModifiers;
+ XwKeyAccel * menuBtnAccelTable;
+ int numAccels;
+ int sizeAccelTable;
+ XwAttachList * pendingAttachList;
+ int numAttachReqs;
+ int sizeAttachList;
+ Boolean menuActive;
+ unsigned int unpostEventType;
+ KeyCode unpostKey;
+ unsigned int unpostModifiers;
+ unsigned int kbdSelectEventType;
+ KeyCode kbdSelectKey;
+ unsigned int kbdSelectModifiers;
+
+ /* User settable fields */
+ Boolean associateChildren;
+ String postString;
+ String selectString;
+ String unpostString;
+ String kbdSelectString;
+} XwMenuMgrPart;
+
+
+typedef struct _XwMenuMgrRec {
+ CorePart core;
+ CompositePart composite;
+ ConstraintPart constraint;
+ XwManagerPart manager;
+ XwMenuMgrPart menu_mgr;
+} XwMenuMgrRec;
+
+
+
diff --git a/Xw/sub.c b/Xw/sub.c
new file mode 100644
index 0000000..e515acf
--- /dev/null
+++ b/Xw/sub.c
@@ -0,0 +1,969 @@
+/*************************************<+>*************************************
+ *****************************************************************************
+ **
+ ** File: sub.c
+ **
+ ** Project: X Widgets
+ **
+ ** Description: Code for TextEdit widget
+ **
+ *****************************************************************************
+ **
+ ** Copyright (c) 1988 by Hewlett-Packard Company
+ ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
+ ** Massachusetts, and the Massachusetts Institute of Technology,
+ ** Cambridge, Massachusetts
+ **
+ ** Permission to use, copy, modify, and distribute this software
+ ** and its documentation for any purpose and without fee is hereby
+ ** granted, provided that the above copyright notice appear in all
+ ** copies and that both that copyright notice and this permission
+ ** notice appear in supporting documentation, and that the names of
+ ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
+ ** publicity pertaining to distribution of the software without
+ ** written prior permission.
+ **
+ ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ ** SOFTWARE.
+ **
+ *****************************************************************************
+ *************************************<+>*************************************/
+/*****************************************************************************
+*
+* Procedures declared in this file
+*
+******************************************************************************
+*/
+static void InsertCursor () ;
+static void _XtTextNeedsUpdating() ;
+static XwTextPosition PositionForXY () ;
+static int LineForPosition () ;
+static int LineAndXYForPosition () ;
+static void BuildLineTable () ;
+static XwTextLineRange UpdateLineTable () ;
+static void ForceBuildLineTable() ;
+static void _XtTextScroll() ;
+static XwEditResult ReplaceText () ;
+static void DisplayText() ;
+static void ClearWindow () ;
+static void ClearText () ;
+static void DisplayAllText () ;
+static void CheckResizeOrOverflow() ;
+static void ProcessExposeRegion() ;
+static void _XtTextPrepareToUpdate() ;
+static void FlushUpdate() ;
+static void _XtTextShowPosition() ;
+static void _XtTextExecuteUpdate() ;
+
+/*
+ * Procedure to manage insert cursor visibility for editable text. It uses
+ * the value of ctx->insertPos and an implicit argument. In the event that
+ * position is immediately preceded by an eol graphic, then the insert cursor
+ * is displayed at the beginning of the next line.
+ */
+/*--------------------------------------------------------------------------+*/
+static void InsertCursor (ctx, state)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwInsertState state;
+{
+ Position x, y;
+ int dy, line, visible;
+ XwTextBlock text;
+
+ if (ctx->text.lt.lines < 1) return;
+ visible = LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y);
+ if (line < ctx->text.lt.lines)
+ dy = (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1;
+ else
+ dy = (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1;
+
+ /** If the insert position is just after eol then put it on next line **/
+ if (x > ctx->text.leftmargin &&
+ ctx->text.insertPos > 0 &&
+ ctx->text.insertPos >= GETLASTPOS(ctx)) {
+ /* reading the source is bogus and this code should use scan */
+ (*(ctx->text.source->read)) (ctx->text.source,
+ ctx->text.insertPos - 1, &text, 1);
+ if (text.ptr[0] == '\n') {
+ x = ctx->text.leftmargin;
+ y += dy;
+ }
+ }
+ y += dy;
+ if (visible)
+ (*(ctx->text.sink->insertCursor))(ctx, x, y, state);
+}
+
+
+/*
+ * Procedure to register a span of text that is no longer valid on the display
+ * It is used to avoid a number of small, and potentially overlapping, screen
+ * updates. [note: this is really a private procedure but is used in
+ * multiple modules].
+ */
+/*--------------------------------------------------------------------------+*/
+static void _XtTextNeedsUpdating(ctx, left, right)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition left, right;
+{
+ int i;
+ if (left < right) {
+ for (i = 0; i < ctx->text.numranges; i++) {
+ if (left <= ctx->text.updateTo[i]
+ && right >= ctx->text.updateFrom[i])
+ { ctx->text.updateFrom[i] = min(left, ctx->text.updateFrom[i]);
+ ctx->text.updateTo[i] = max(right, ctx->text.updateTo[i]);
+ return;
+ }
+ }
+ ctx->text.numranges++;
+ if (ctx->text.numranges > ctx->text.maxranges) {
+ ctx->text.maxranges = ctx->text.numranges;
+ i = ctx->text.maxranges * sizeof(XwTextPosition);
+ ctx->text.updateFrom = (XwTextPosition *)
+ XtRealloc((char *)ctx->text.updateFrom, (unsigned) i
+ * sizeof(XwTextPosition));
+ ctx->text.updateTo = (XwTextPosition *)
+ XtRealloc((char *)ctx->text.updateTo, (unsigned) i
+ * sizeof(XwTextPosition));
+ }
+ ctx->text.updateFrom[ctx->text.numranges - 1] = left;
+ ctx->text.updateTo[ctx->text.numranges - 1] = right;
+ }
+}
+
+
+/*
+ * This routine maps an x and y position in a window that is displaying text
+ * into the corresponding position in the source.
+ */
+/*--------------------------------------------------------------------------+*/
+static XwTextPosition PositionForXY (ctx, x, y)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ Position x,y;
+{
+ /* it is illegal to call this routine unless there is a valid line table! */
+ int width, fromx, line;
+ XwTextPosition position, resultstart, resultend;
+ XwTextPosition lastpos = GETLASTPOS(ctx);
+
+ /*** figure out what line it is on ***/
+ for (line = 0; line < ctx->text.lt.lines - 1; line++) {
+ if (y <= ctx->text.lt.info[line + 1].y)
+ break;
+ }
+ position = ctx->text.lt.info[line].position;
+ if (position >= lastpos)
+ return lastpos;
+ fromx = ctx->text.lt.info[line].x; /* starting x in line */
+ width = x - fromx; /* num of pix from starting of line */
+ (*(ctx->text.sink->resolve)) (ctx, position, fromx, width,
+ &resultstart, &resultend);
+ if (resultstart >= ctx->text.lt.info[line + 1].position)
+ resultstart = (*(ctx->text.source->scan))(ctx->text.source,
+ ctx->text.lt.info[line + 1].position, XwstPositions, XwsdLeft,
+ 1, TRUE);
+ return resultstart;
+}
+
+/*
+ * This routine maps a source position in to the corresponding line number
+ * of the text that is displayed in the window.
+ */
+/*--------------------------------------------------------------------------+*/
+static int LineForPosition (ctx, position)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition position;
+ /* it is illegal to call this routine unless there is a valid line table!*/
+{
+ int line;
+
+ if (position <= ctx->text.lt.info[0].position)
+ return 0;
+ for (line = 0; line < ctx->text.lt.lines; line++)
+ if (position < ctx->text.lt.info[line + 1].position)
+ break;
+ return line;
+}
+
+/*
+ * This routine maps a source position into the corresponding line number
+ * and the x, y coordinates of the text that is displayed in the window.
+ */
+/*--------------------------------------------------------------------------+*/
+static int LineAndXYForPosition (ctx, pos, line, x, y)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition pos;
+ int *line;
+ Position *x, *y;
+ /* it is illegal to call this routine unless there is a valid line table!*/
+{
+ XwTextPosition linePos, endPos;
+ int visible, realW, realH;
+
+ *line = 0;
+ *x = ctx->text.leftmargin;
+ *y = ctx->text.topmargin;
+ visible = IsPositionVisible(ctx, pos);
+ if (visible) {
+ *line = LineForPosition(ctx, pos);
+ *y = ctx->text.lt.info[*line].y;
+ *x = ctx->text.lt.info[*line].x;
+ linePos = ctx->text.lt.info[*line].position;
+ (*(ctx->text.sink->findDistance))(ctx, linePos,
+ *x, pos, &realW, &endPos, &realH);
+ *x = *x + realW;
+ }
+ return visible;
+}
+
+/*
+ * This routine builds a line table. It does this by starting at the
+ * specified position and measuring text to determine the staring position
+ * of each line to be displayed. It also determines and saves in the
+ * linetable all the required metrics for displaying a given line (e.g.
+ * x offset, y offset, line length, etc.).
+ */
+/*--------------------------------------------------------------------------+*/
+static void BuildLineTable (self, position)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget self;
+ XwTextPosition position;
+{
+ XwTextPosition line, lines;
+ Boolean rebuild;
+ XwLineTableEntryPtr lp ;
+
+ rebuild = (Boolean) (position != self->text.lt.top);
+ lines= applyDisplay(maxLines)(self) ;
+
+/****************
+ *
+ * RBM
+ *
+ * Don't allow a 0-line widget - let clipping occur
+ *
+ * NOTE: THE MAXINT CLIPPING IS AN UGLY HACK THAT NEEDS TO BE FIXED
+ * WITH A CAST!!
+ ****************/
+ if ((lines < 1) || (lines > 32767)) lines = 1;
+
+ if (self->text.lt.info != NULL && lines != self->text.lt.lines) {
+ XtFree((char *) self->text.lt.info);
+ self->text.lt.info = NULL;
+ }
+ if (self->text.lt.info == NULL)
+ { self->text.lt.info = (XwLineTableEntry *)
+ XtCalloc(lines + 1, (unsigned)sizeof(XwLineTableEntry));
+ self->text.lt.lines = lines ;
+ for (line = 0, lp = &(self->text.lt.info[0]) ;
+ line < lines; line++, lp++)
+ { lp->position = lp->drawPos = 0 ;
+ lp->x = lp->y = 0 ;
+ }
+ rebuild = TRUE;
+ }
+
+ self->text.lt.top = position ;
+ if (rebuild) UpdateLineTable ( self
+ , position
+ , 0
+ , self->core.width
+ - self->text.leftmargin
+ - self->text.rightmargin
+ , 0
+ , FALSE
+ ) ;
+}
+
+/*--------------------------------------------------------------------------+*/
+static XwTextLineRange UpdateLineTable
+ (self, pos0, posF, width, line0, updateMode)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget self ;
+ XwTextPosition pos0, posF ;
+ Dimension width ;
+ XwTextPosition line0 ;
+ int updateMode ;
+{
+ XwLineTableEntryPtr currLine ;
+ XwLineTablePtr lt ;
+ XwTextPosition line, nLines ;
+ Dimension x0, y ;
+ int reqW, reqH ;
+ TextFit (*textFitFn)();
+ int wrapEnabled, breakOnWhiteSpace ;
+ XwTextPosition fitPos, drawPos, nextPos ;
+
+ textFitFn = self->text.sink->textFitFn ;
+ lt = &(self->text.lt) ;
+ nLines = lt->lines ;
+ x0 = self->text.leftmargin ;
+ y = updateMode ? lt->info[line0].y : self->text.topmargin ;
+ reqH = 0 ;
+ wrapEnabled = (int) self->text.wrap_mode ;
+ breakOnWhiteSpace =
+ wrapEnabled && (self->text.wrap_break == XwWrapWhiteSpace) ;
+
+ for (line = line0; line <= nLines; line++)
+ { currLine = &(lt->info[line]) ;
+ currLine->x = x0;
+ currLine->y = y;
+ currLine->position = pos0;
+ if (pos0 <= GETLASTPOS(self))
+ { currLine->fit = (*textFitFn) ( self
+ , pos0
+ , x0
+ , width
+ , wrapEnabled
+ , breakOnWhiteSpace
+ , &fitPos
+ , &drawPos
+ , &nextPos
+ , &reqW
+ , &reqH
+ ) ;
+ currLine->drawPos = drawPos ;
+
+ currLine->endX = x0 + reqW ;
+ pos0 = nextPos;
+ /* In update mode we must go through the last line which had a
+ character replaced in it before terminating on a mere position
+ match. Starting position (of replacement) would be sufficient
+ only if we know the font is fixed width. (Good place to
+ optimize someday, huh?)
+ */
+ if (updateMode && (nextPos > posF)
+ && (nextPos == lt->info[line+1].position))
+ { break ;
+ }
+ }
+ else
+ { currLine->endX = x0;
+ currLine->fit = tfEndText ;
+ }
+ y += reqH;
+ } ;
+
+ return ( (line < nLines) ? line : nLines - 1 ) ;
+}
+
+
+/*
+ * This routine is used to re-display the entire window, independent of
+ * its current state.
+ */
+/*--------------------------------------------------------------------------+*/
+static void ForceBuildLineTable(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ XwTextPosition position;
+
+ position = ctx->text.lt.top;
+ ctx->text.lt.top++; /* ugly, but it works */
+ BuildLineTable(ctx, position);
+}
+
+/*
+ * The routine will scroll the displayed text by lines. If the arg is
+ * positive, move up; otherwise, move down. [note: this is really a private
+ * procedure but is used in multiple modules].
+ */
+/*--------------------------------------------------------------------------+*/
+static void _XtTextScroll(ctx, n)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ int n;
+{
+ register XwTextEditPart *text = (XwTextEditPart *) &(ctx->text);
+ register XwLineTablePtr lt = &(text->lt);
+ XwTextPosition top, target, lastpos = GETLASTPOS(ctx);
+ Dimension textwidth =
+ ctx->core.width - (text->leftmargin + text->rightmargin);
+ Dimension ypos;
+ if (n >= 0) {
+ top = min(lt->info[n].position, lastpos);
+ BuildLineTable(ctx, top);
+ if (top >= lastpos)
+ DisplayAllText(ctx);
+ else {
+ XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx),
+ text->gc,
+ text->leftmargin, /* 0, */
+ lt->info[n].y,
+ textwidth, /* 9999, */
+ ctx->core.height - lt->info[n].y - text->bottommargin,
+ text->leftmargin, /* 0, */
+ lt->info[0].y);
+ ypos = lt->info[0].y + ctx->core.height - lt->info[n].y;
+ (*(text->sink->clearToBackground))
+ (ctx,
+ text->leftmargin, /* 0, */
+ ypos, /* lt->info[0].y + ctx->core.height - lt->info[n].y, */
+ textwidth, /* 9999, */
+ ctx->core.height - (ypos + text->bottommargin) /* 9999 */
+ );
+ if (n < lt->lines) n++;
+ _XtTextNeedsUpdating(ctx,
+ lt->info[lt->lines - n].position, lastpos);
+ }
+ } else {
+ Dimension tempHeight;
+ n = -n;
+ target = lt->top;
+ top = (*(text->source->scan))(text->source, target, XwstEOL,
+ XwsdLeft, n+1, FALSE);
+ tempHeight = lt->info[lt->lines-n].y - text->topmargin;
+ BuildLineTable(ctx, top);
+ if (lt->info[n].position == target) {
+ XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx),
+ text->gc,
+ text->leftmargin, /* 0, */
+ lt->info[0].y,
+ textwidth, /* 9999, */
+ tempHeight,
+ text->leftmargin, /* 0, */
+ lt->info[n].y);
+ _XtTextNeedsUpdating(ctx,
+ lt->info[0].position, lt->info[n].position);
+ } else if (lt->top != target) DisplayAllText(ctx);
+ }
+}
+
+
+/*
+ * This internal routine deletes the text from pos1 to pos2 in a source and
+ * then inserts, at pos1, the text that was passed. As a side effect it
+ * "invalidates" that portion of the displayed text (if any).
+ */
+/*--------------------------------------------------------------------------+*/
+static XwEditResult ReplaceText (ctx, pos1, pos2, text, verify)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition pos1, pos2;
+ XwTextBlock *text;
+ Boolean verify;
+
+ /* it is illegal to call this routine unless there is a valid line table!*/
+{
+ int i, line1, line2, visible, delta;
+ XwEditResult error;
+ Position x, y;
+ XwTextPosition startPos, endPos, updateFrom, lastpos;
+ XwTextVerifyCD cbdata;
+ XwTextBlock newtxtblk;
+
+ newtxtblk.ptr = (unsigned char*) XtMalloc(text->length);
+ newtxtblk.firstPos = text->firstPos;
+ newtxtblk.length = text->length;
+ strncpy(newtxtblk.ptr, text->ptr, text->length);
+ cbdata.operation = modVerify;
+ cbdata.doit = TRUE;
+ cbdata.currInsert = ctx->text.insertPos;
+ cbdata.newInsert = ctx->text.insertPos;
+ cbdata.startPos = pos1;
+ cbdata.endPos = pos2;
+ cbdata.text = &newtxtblk;
+
+ if (verify)
+ { XtCallCallbacks((Widget)ctx, XtNmodifyVerification, &cbdata);
+
+ if (!cbdata.doit) {
+ text->length = 0; /* Necessary inorder to return to initial state */
+ return XweditReject;
+ }
+
+ /* Extract any new data changed by the verification callback */
+ /* newtxtblk is used in the actual replace call later */
+ pos1 = cbdata.startPos;
+ pos2 = cbdata.endPos;
+ ctx->text.insertPos = cbdata.newInsert;
+ }
+
+ /* the insertPos may not always be set to the right spot in XwtextAppend */
+ if ((pos1 == ctx->text.insertPos) &&
+ ((*(ctx->text.source->editType))(ctx->text.source) == XwtextAppend)) {
+ ctx->text.insertPos = GETLASTPOS(ctx);
+ pos2 = pos2 - pos1 + ctx->text.insertPos;
+ pos1 = ctx->text.insertPos;
+ }
+ updateFrom = (*(ctx->text.source->scan))
+ (ctx->text.source, pos1, XwstWhiteSpace, XwsdLeft, 1, TRUE);
+ updateFrom = (*(ctx->text.source->scan))
+ (ctx->text.source, updateFrom, XwstPositions, XwsdLeft, 1, TRUE);
+ startPos = max(updateFrom, ctx->text.lt.top);
+ visible = LineAndXYForPosition(ctx, startPos, &line1, &x, &y);
+ error = (*(ctx->text.source->replace))
+ (ctx->text.source, pos1, pos2, &newtxtblk, &delta);
+ XtFree(newtxtblk.ptr);
+ if (error) return error;
+ lastpos = GETLASTPOS(ctx);
+ if (ctx->text.lt.top >= lastpos) {
+ BuildLineTable(ctx, lastpos);
+ /* ClearWindow(ctx); */
+ ClearText(ctx);
+ return error;
+ }
+ if (delta < lastpos) {
+ for (i = 0; i < ctx->text.numranges; i++) {
+ if (ctx->text.updateFrom[i] > pos1)
+ ctx->text.updateFrom[i] += delta;
+ if (ctx->text.updateTo[i] >= pos1)
+ ctx->text.updateTo[i] += delta;
+ }
+ }
+
+ line2 = LineForPosition(ctx, pos1);
+ /*
+ * fixup all current line table entries to reflect edit.
+ * BUG: it is illegal to do arithmetic on positions. This code should
+ * either use scan or the source needs to provide a function for doing
+ * position arithmetic.
+ */
+ for (i = line2 + 1; i <= ctx->text.lt.lines; i++)
+ ctx->text.lt.info[i].position += delta;
+
+ endPos = pos1;
+ /*
+ * Now process the line table and fixup in case edits caused
+ * changes in line breaks. If we are breaking on word boundaries,
+ * this code checks for moving words to and from lines.
+ */
+ if (visible) {
+ XwTextLineRange lastChangedLine ;
+ if (line1) line1-- ; /* force check for word moving to prev line */
+ lastChangedLine =
+ UpdateLineTable (ctx
+ , ctx->text.lt.info[line1].position
+ , pos2 + delta
+ , ctx->core.width - ctx->text.leftmargin
+ - ctx->text.rightmargin
+ , line1
+ , TRUE
+ ) ;
+ endPos = ctx->text.lt.info[lastChangedLine+1].position ;
+ }
+ lastpos = GETLASTPOS(ctx);
+ if (delta >= lastpos)
+ endPos = lastpos;
+ if (delta >= lastpos || pos2 >= ctx->text.lt.top)
+ _XtTextNeedsUpdating(ctx, updateFrom, endPos);
+ return error;
+}
+
+
+/*
+ * This routine will display text between two arbitrary source positions.
+ * In the event that this span contains highlighted text for the selection,
+ * only that portion will be displayed highlighted.
+ */
+/*--------------------------------------------------------------------------+*/
+static void DisplayText(ctx, pos1, pos2)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+ XwTextPosition pos1, pos2;
+ /* it is illegal to call this routine unless there is a valid line table!*/
+{
+ Position x, y, xlimit, tempx;
+ Dimension height;
+ int line, i, visible;
+ XwTextPosition startPos, endPos, lastpos = GETLASTPOS(ctx);
+
+ if (pos1 < ctx->text.lt.top)
+ pos1 = ctx->text.lt.top;
+ if (pos2 > lastpos)
+ pos2 = lastpos;
+ if (pos1 >= pos2) return;
+ visible = LineAndXYForPosition(ctx, pos1, &line, &x, &y);
+ if (!visible)
+ return;
+ startPos = pos1;
+ xlimit = ctx->core.width - ctx->text.rightmargin + 1 ;
+ height = ctx->text.lt.info[1].y - ctx->text.lt.info[0].y;
+ for (i = line; i < ctx->text.lt.lines; i++) {
+ endPos = ctx->text.lt.info[i].drawPos + 1;
+ if (endPos > pos2)
+ endPos = pos2;
+ if (endPos > startPos) {
+ /* We know this should not be necessary!!!!
+ if (x == ctx->text.leftmargin)
+ (*(ctx->text.sink->clearToBackground))(ctx,
+ 0, y, ctx->text.leftmargin, height);
+ */
+ if (startPos >= ctx->text.s.right || endPos <= ctx->text.s.left) {
+ (*(ctx->text.sink->display))(ctx, x, y,
+ startPos, endPos, FALSE);
+ } else if (startPos >= ctx->text.s.left
+ && endPos <= ctx->text.s.right)
+ { (*(ctx->text.sink->display))(ctx, x, y,
+ startPos, endPos, TRUE);
+ } else {
+ DisplayText(ctx, startPos, ctx->text.s.left);
+ DisplayText(ctx, max(startPos, ctx->text.s.left),
+ min(endPos, ctx->text.s.right));
+ DisplayText(ctx, ctx->text.s.right, endPos);
+ }
+ }
+ startPos = ctx->text.lt.info[i + 1].position;
+ height = ctx->text.lt.info[i + 1].y - ctx->text.lt.info[i].y;
+ tempx = ctx->text.lt.info[i].endX;
+ (*(ctx->text.sink->clearToBackground))(ctx,
+ tempx, y, xlimit - tempx, height);
+ x = ctx->text.leftmargin;
+ y = ctx->text.lt.info[i + 1].y;
+ if ((endPos == pos2) && (endPos != lastpos))
+ break;
+ }
+}
+
+/*
+ * Clear the window to background color.
+ */
+/*--------------------------------------------------------------------------+*/
+static void ClearWindow (ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ (*(ctx->text.sink->clearToBackground))(ctx, 0, 0, ctx->core.width,
+ ctx->core.height);
+}
+
+/*
+ * Clear the portion of the window that the text in drawn in, or that is
+ * don't clear the margins
+ */
+/*--------------------------------------------------------------------------+*/
+static void ClearText (ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ register XwTextEditPart *text = (XwTextEditPart *) &(ctx->text);
+ (*(text->sink->clearToBackground))
+ (ctx, 0, 0, ctx->core.width, ctx->core.height);
+}
+
+/*
+ * Internal redisplay entire window.
+ */
+/*--------------------------------------------------------------------------+*/
+static void DisplayAllText (w)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+
+ if (!XtIsRealized((Widget)ctx)) return;
+
+ ClearText(ctx);
+ /* ClearWindow(ctx); */
+ /* BuildLineTable(ctx, ctx->text.lt.top); */
+ _XtTextNeedsUpdating(ctx, zeroPosition, GETLASTPOS(ctx));
+
+}
+
+/*
+ * This routine checks to see if the window should be resized (grown or
+ * shrunk) or scrolled then text to be painted overflows to the right or
+ * the bottom of the window. It is used by the keyboard input routine.
+ */
+/*--------------------------------------------------------------------------+*/
+static void CheckResizeOrOverflow(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ XwTextLineRange i, nLines ;
+ Dimension width;
+ XtWidgetGeometry rbox;
+ XtGeometryResult reply;
+ XwLineTableEntryPtr lp ;
+ XwLineTablePtr lt ;
+ XwTextEditPart *tp ;
+
+ tp = &(ctx->text) ;
+ lt = &(tp->lt) ;
+ nLines = lt->lines ;
+
+ if (tp->grow_state & XwGrowHorizontal)
+ { UpdateLineTable ( ctx, lt->top, 0, INFINITE_WIDTH, 0, FALSE) ;
+ width = 0 ;
+ for (i=0, lp = &(lt->info[0]) ; i < nLines ; i++, lp++)
+ { if (width < lp->endX) width = lp->endX ;
+ } ;
+ width += ctx->text.rightmargin;
+ if (width > ctx->core.width)
+ { rbox.request_mode = CWWidth;
+ rbox.width = width;
+ reply = XtMakeGeometryRequest((Widget)ctx, &rbox, &rbox);
+ if (reply == XtGeometryAlmost)
+ reply = XtMakeGeometryRequest((Widget)ctx, &rbox, NULL);
+ /* NOTE: following test is expected to be a fall-through from
+ previous. Should not be an else if. */
+ if (reply == XtGeometryYes)
+ ctx->core.width = rbox.width;
+ else /* if request not satisfied, disallow future attempts */
+ { tp->grow_state &= ~XwGrowHorizontal ;
+ UpdateLineTable ( ctx, lt->top, 0, ctx->core.width
+ - ctx->text.leftmargin - ctx->text.rightmargin,
+ 0, FALSE);
+ }
+ }
+ } ;
+
+ if ((tp->grow_state & XwGrowVertical)
+ && ( ! (lt->info[nLines].fit & tfEndText)
+ || (lt->info[nLines].drawPos > lt->info[nLines].position))
+ )
+ { rbox.request_mode = CWHeight;
+ rbox.height = (*(ctx->text.sink->maxHeight))
+ (ctx, nLines + 1) + tp->topmargin + tp->bottommargin ;
+ reply = XtMakeGeometryRequest((Widget)ctx, &rbox, &rbox);
+ if (reply == XtGeometryAlmost)
+ reply = XtMakeGeometryRequest((Widget)ctx, &rbox, NULL);
+ if (reply == XtGeometryYes)
+ ctx->core.height = rbox.height;
+ else /* if request not satisfied, disallow future attempts */
+ { tp->grow_state &= ~XwGrowVertical ;
+ }
+ } ;
+}
+
+/*
+ * This routine processes all "expose region" XEvents. In general, its job
+ * is to the best job at minimal re-paint of the text, displayed in the
+ * window, that it can.
+ */
+/*--------------------------------------------------------------------------+*/
+static void ProcessExposeRegion(w, event)
+/*--------------------------------------------------------------------------+*/
+ Widget w;
+ XEvent *event;
+{
+ XwTextEditWidget ctx = (XwTextEditWidget) w;
+ XwTextPosition pos1, pos2, resultend;
+ int line;
+ int x = event->xexpose.x;
+ int y = event->xexpose.y;
+ int width = event->xexpose.width;
+ int height = event->xexpose.height;
+ XwLineTableEntryPtr info;
+
+ _XtTextPrepareToUpdate(ctx);
+ if (x < ctx->text.leftmargin) /* stomp on caret tracks */
+ (*(ctx->text.sink->clearToBackground))(ctx, x, y, width, height);
+ /* figure out starting line that was exposed */
+ line = LineForPosition(ctx, PositionForXY(ctx, x, y));
+ while (line < ctx->text.lt.lines && ctx->text.lt.info[line + 1].y < y)
+ line++;
+ while (line < ctx->text.lt.lines) {
+ info = &(ctx->text.lt.info[line]);
+ if (info->y >= y + height)
+ break;
+ (*(ctx->text.sink->resolve))(ctx,
+ info->position, info->x,
+ x - info->x, &pos1, &resultend);
+ (*(ctx->text.sink->resolve))(ctx,
+ info->position, info->x,
+ x + width - info->x, &pos2,
+ &resultend);
+ pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos2,
+ XwstPositions, XwsdRight, 1, TRUE);
+ _XtTextNeedsUpdating(ctx, pos1, pos2);
+ line++;
+ }
+ _XtTextExecuteUpdate(ctx);
+
+}
+
+/*
+ * This routine does all setup required to syncronize batched screen updates
+ */
+/*--------------------------------------------------------------------------+*/
+static void _XtTextPrepareToUpdate(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+
+ if ((ctx->text.oldinsert < 0) && ctx->text.update_flag) {
+ InsertCursor(ctx, XwisOff);
+ ctx->text.numranges = 0;
+ ctx->text.showposition = FALSE;
+ ctx->text.oldinsert = ctx->text.insertPos;
+ }
+}
+
+
+/*
+ * This is a private utility routine used by _XtTextExecuteUpdate. It
+ * processes all the outstanding update requests and merges update
+ * ranges where possible.
+ */
+/*--------------------------------------------------------------------------+*/
+static void FlushUpdate(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ int i, w;
+ XwTextPosition updateFrom, updateTo;
+ while (ctx->text.numranges > 0) {
+ updateFrom = ctx->text.updateFrom[0];
+ w = 0;
+ for (i=1 ; i<ctx->text.numranges ; i++) {
+ if (ctx->text.updateFrom[i] < updateFrom) {
+ updateFrom = ctx->text.updateFrom[i];
+ w = i;
+ }
+ }
+ updateTo = ctx->text.updateTo[w];
+ ctx->text.numranges--;
+ ctx->text.updateFrom[w] = ctx->text.updateFrom[ctx->text.numranges];
+ ctx->text.updateTo[w] = ctx->text.updateTo[ctx->text.numranges];
+ for (i=ctx->text.numranges-1 ; i>=0 ; i--) {
+ while (ctx->text.updateFrom[i] <= updateTo
+ && i < ctx->text.numranges)
+ {
+ updateTo = ctx->text.updateTo[i];
+ ctx->text.numranges--;
+ ctx->text.updateFrom[i] =
+ ctx->text.updateFrom[ctx->text.numranges];
+ ctx->text.updateTo[i] =
+ ctx->text.updateTo[ctx->text.numranges];
+ }
+ }
+ DisplayText(ctx, updateFrom, updateTo);
+ }
+}
+
+
+/*
+ * This is a private utility routine used by _XtTextExecuteUpdate. This routine
+ * worries about edits causing new data or the insertion point becoming
+ * invisible (off the screen). Currently it always makes it visible by
+ * scrolling. It probably needs generalization to allow more options.
+ */
+/*--------------------------------------------------------------------------+*/
+static void _XtTextShowPosition(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ XwTextPosition top, first, second, insertPos ;
+ XwTextPosition lastpos = GETLASTPOS(ctx);
+ XwTextEditPart *text = &(ctx->text) ;
+ XwLineTablePtr lt = &(text->lt) ;
+ short hScroll ;
+
+ /* NOTE: Following code relies on current assumption that
+ horizontal scrolling will be enabled only when there is
+ only one display line.
+ */
+
+ insertPos = text->insertPos ;
+ if ( insertPos < lt->top
+ || insertPos >= lt->info[lt->lines].position
+ || (hScroll = ((text->scroll_state & XwAutoScrollHorizontal)
+ && (insertPos > lt->info[0].drawPos)
+ && ( lt->info[0].drawPos + 1 < lastpos))
+ ? 1 : 0 )
+
+ )
+ {
+ if ( lt->lines > 0
+ && (insertPos < lt->top
+ || lt->info[lt->lines].position <= lastpos
+ || hScroll)
+ ) {
+ first = lt->top;
+ second = lt->info[1].position;
+/*
+ if (insertPos < first)
+ top = (*(text->source->scan))(
+ text->source, insertPos, XwstEOL,
+ XwsdLeft, 1, FALSE);
+ else
+ top = (*(text->source->scan))(
+ text->source, insertPos, XwstEOL,
+ XwsdLeft, lt->lines, FALSE);
+ BuildLineTable(ctx, top);
+ while (insertPos >= lt->info[lt->lines].position) {
+ if (lt->info[lt->lines].position > lastpos)
+ break;
+ BuildLineTable(ctx, lt->info[1].position);
+ }
+*/
+ if (text->scroll_state & XwAutoScrollHorizontal) {
+ if ((insertPos > lt->info[0].drawPos) &&
+ (lt->info[0].drawPos + 1 < lastpos)) {
+ /* smooth scroll: scroll by one character at a time */
+
+ XwTextPosition delta = 0 ;
+ top = insertPos - (lt->info[0].drawPos
+ - lt->info[0].position) - 1;
+ while (insertPos > lt->info[0].drawPos+1) {
+ BuildLineTable (ctx, top += delta) ;
+ delta = (insertPos - top) >> 2 ;
+ }
+ first = -1 ; /* prevent scroll down by one line */
+ }
+
+ else if (insertPos < first) {
+ /* Do the same as above, for traveling to the left */
+
+ XwTextPosition delta = 0 ;
+ if (insertPos < 0) insertPos = 0;
+ top = insertPos;
+ if (top < 0) top = 0;
+ BuildLineTable (ctx, top);
+ while (insertPos < lt->top) {
+ top -= delta;
+ if (top < 0) top = 0;
+ BuildLineTable (ctx, top);
+ delta = (insertPos - top) >> 2;
+ }
+ first = -1 ; /* prevent scroll down by one line */
+ }
+ }
+
+ if (lt->top == second && lt->lines > 1) {
+ BuildLineTable(ctx, first);
+ _XtTextScroll(ctx, 1);
+ } else if (lt->info[1].position == first && lt->lines > 1) {
+ BuildLineTable(ctx, first);
+ _XtTextScroll(ctx, -1);
+ } else {
+ text->numranges = 0;
+ if (lt->top != first)
+ DisplayAllText(ctx);
+ }
+ }
+ }
+}
+
+
+
+/*
+ * This routine causes all batched screen updates to be performed
+ */
+/*--------------------------------------------------------------------------+*/
+static void _XtTextExecuteUpdate(ctx)
+/*--------------------------------------------------------------------------+*/
+ XwTextEditWidget ctx;
+{
+ if ((ctx->text.oldinsert >= 0) && ctx->text.update_flag) {
+ if (ctx->text.oldinsert != ctx->text.insertPos
+ || ctx->text.showposition)
+ _XtTextShowPosition(ctx);
+ FlushUpdate(ctx);
+ InsertCursor(ctx, XwisOn);
+ ctx->text.oldinsert = -1;
+ }
+}
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..1bc55f4
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,951 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
+[m4_warning([this file was generated for autoconf 2.68.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/colordefs.h b/colordefs.h
new file mode 100644
index 0000000..c726855
--- /dev/null
+++ b/colordefs.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------*/
+/* colordefs.h */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* Add colors here as needed. */
+/* Reflect all changes in the resource manager, xcircuit.c */
+/* And ApplicationDataPtr in xcircuit.h */
+/*-------------------------------------------------------------------------*/
+
+#define NUMBER_OF_COLORS 17
+
+#define BACKGROUND appcolors[0]
+#define FOREGROUND appcolors[1]
+#define SELECTCOLOR appcolors[2]
+#define FILTERCOLOR appcolors[3]
+#define GRIDCOLOR appcolors[4]
+#define SNAPCOLOR appcolors[5]
+#define AXESCOLOR appcolors[6]
+#define OFFBUTTONCOLOR appcolors[7]
+#define AUXCOLOR appcolors[8]
+#define BARCOLOR appcolors[9]
+#define PARAMCOLOR appcolors[10]
+
+/* The rest of the colors are layout colors, not GUI colors */
+
+#define BBOXCOLOR appcolors[11]
+#define LOCALPINCOLOR appcolors[12]
+#define GLOBALPINCOLOR appcolors[13]
+#define INFOLABELCOLOR appcolors[14]
+#define RATSNESTCOLOR appcolors[15]
+#define CLIPMASKCOLOR appcolors[15]
+
+#define DEFAULTCOLOR -1 /* Inherits color of parent */
+#define DOFORALL -2 /* All elements inherit same color */
+#define DOSUBSTRING -3 /* Only selected substring drawn */
+ /* in the SELECTCOLOR */
+#define BADCOLOR -1 /* When returned from query_named_color */
+#define ERRORCOLOR -2 /* When returned from query_named_color */
+
+/*-------------------------------------------------------------------------*/
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..dc84c68
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1501 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner. Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ LIBC=gnu
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-gnu
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ i386)
+ eval $set_cc_for_build
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ UNAME_PROCESSOR="x86_64"
+ fi
+ fi ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..12ebc78
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1410 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+
+timestamp='2001-08-13'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dsp16xx \
+ | fr30 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+ | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+ | mipsbe | mipsel | mipsle | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | s390 | s390x \
+ | sh | sh[34] | sh[34]eb | shbe | shle \
+ | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 \
+ | we32k \
+ | x86 | xscale \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alphapca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armv*-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c54x-* \
+ | clipper-* | cray2-* | cydra-* \
+ | d10v-* | d30v-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | m32r-* \
+ | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipsel-* \
+ | mipsle-* | mipstx39-* | mipstx39el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | s390-* | s390x-* \
+ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \
+ | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [cjt]90)
+ basic_machine=${basic_machine}-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=t3e-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ windows32)
+ basic_machine=i386-pc
+ os=-windows32-msvcrt
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto*)
+ os=-nto-qnx
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..c740413
--- /dev/null
+++ b/configure
@@ -0,0 +1,8887 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="xcircuit.c"
+ac_unique_file="xcircuit.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+INSTALL_TARGET
+ALL_TARGET
+HAVE_LGF
+INTERPRETER
+LD
+SHLIB_CFLAGS
+XCIRCUIT_TARGET
+WRAPPER_SCRIPT
+INTERP_PATH
+STARTUP_FILE
+STDLIBS
+SUBLIB
+SUBDIRS
+PYTHON
+SPICE_EXEC
+GS_EXEC
+WISH_EXE
+TCL_LIB_DIR
+LIB_SPECS
+INC_SPECS
+LD_RUN_PATH
+EXTRA_LIB_SPECS
+SHLIB_LIB_SPECS
+LDDL_FLAGS
+SHLIB_LD
+SHDLIB_EXT
+X_EXTRA_LIBS
+X_LIBS
+X_PRE_LIBS
+X_CFLAGS
+XMKMF
+EGREP
+GREP
+CPP
+M4
+RANLIB
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+REVISION
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_dependency_tracking
+with_x
+with_opengl
+enable_double_buffer
+enable_optimize
+with_xpm
+with_gnu_ld
+with_tcl
+with_tk
+with_tclincls
+with_tkincls
+with_tcllibs
+with_tklibs
+enable_asg
+enable_lgf
+enable_focus_fix
+with_gs
+with_ngspice
+with_python
+enable_memdebug
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+XMKMF'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+X features:
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-double-buffer disable graphics double-buffering
+ --enable-optimize enable compile-time optimizer flag -O2
+ --enable-asg enable support for Automatic Schematic Generation
+ --disable-lgf disable support for reading Caltech tools
+ analog simulator .lgf files
+ --disable-focus-fix disable focus fix for some window managers
+ --enable-memdebug enable memory debugging
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-x use the X Window System
+ --with-opengl=DIR use OpenGL include files in DIR
+ --with-xpm=DIR use Xpm include/library files in DIR
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-tcl=DIR Find tclConfig.sh in DIR
+ --with-tk=DIR Find tkConfig.sh in DIR
+ --with-tclincls=DIR Find tcl.h in DIR
+ --with-tkincls=DIR Find tk.h in DIR
+ --with-tcllibs=DIR Find Tcl library in DIR
+ --with-tklibs=DIR Find Tk library in DIR
+ --with-gs=DIR path to ghostscript
+ --with-ngspice=DIR path to ngspice
+ --with-python=DIR path to python interpreter
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ XMKMF Path to xmkmf, Makefile generator for X Window System
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid; break
+else
+ as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_lo=$ac_mid; break
+else
+ as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid
+else
+ as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+ else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (($2) < 0)
+ {
+ long int i = longval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%ld", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%lu", i);
+ }
+ /* Do not output a trailing newline, as this causes \r\n confusion
+ on some platforms. */
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+ ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+ fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_compute_int
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+PACKAGE=xcircuit
+
+VERSION=`cat ./VERSION | cut -d. -f1-2`
+am__api_version='1.11'
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if ${ac_cv_path_mkdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=${PACKAGE}
+ VERSION=${VERSION}
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+SUBDIRS=
+SUBLIB=
+STDLIBS=
+XCIRCUIT_TARGET=
+ALL_TARGET="undefined-target"
+INSTALL_TARGET="undefined-install-target"
+REVISION=`cat ./VERSION | cut -d. -f3`
+INTERPRETER=NOINTERP
+HAVE_LGF=NOFORMATS
+xc_with_GL=
+
+SHLIB_CFLAGS=""
+LIB_SPECS=""
+WISH_EXE=""
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5
+$as_echo_n "checking for library containing strerror... " >&6; }
+if ${ac_cv_search_strerror+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strerror ();
+int
+main ()
+{
+return strerror ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' cposix; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_strerror=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_strerror+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_strerror+:} false; then :
+
+else
+ ac_cv_search_strerror=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5
+$as_echo "$ac_cv_search_strerror" >&6; }
+ac_res=$ac_cv_search_strerror
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+if test "x$U" != "x"; then
+ as_fn_error $? "Compiler not ANSI compliant" "$LINENO" 5
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+for ac_prog in gm4 gnum4 m4
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_M4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $M4 in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_M4="$M4" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+M4=$ac_cv_path_M4
+if test -n "$M4"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
+$as_echo "$M4" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$M4" && break
+done
+
+
+case "$target_os" in
+ *cygwin*)
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
+$as_echo_n "checking for sin in -lm... " >&6; }
+if ${ac_cv_lib_m_sin+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sin ();
+int
+main ()
+{
+return sin ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_sin=yes
+else
+ ac_cv_lib_m_sin=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
+$as_echo "$ac_cv_lib_m_sin" >&6; }
+if test "x$ac_cv_lib_m_sin" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+fi
+
+ ;;
+esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if ${ac_cv_sizeof_void_p+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_void_p" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (void *)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_void_p=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5
+$as_echo_n "checking size of unsigned int... " >&6; }
+if ${ac_cv_sizeof_unsigned_int+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_unsigned_int" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned int)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_unsigned_int=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5
+$as_echo "$ac_cv_sizeof_unsigned_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5
+$as_echo_n "checking size of unsigned long... " >&6; }
+if ${ac_cv_sizeof_unsigned_long+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_unsigned_long" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned long)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_unsigned_long=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5
+$as_echo "$ac_cv_sizeof_unsigned_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5
+$as_echo_n "checking size of unsigned long long... " >&6; }
+if ${ac_cv_sizeof_unsigned_long_long+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_unsigned_long_long" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned long long)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_unsigned_long_long=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5
+$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long
+_ACEOF
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5
+$as_echo_n "checking for X... " >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then :
+ withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ case $x_includes,$x_libraries in #(
+ *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #(
+ *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+ cd conftest.dir
+ cat >Imakefile <<'_ACEOF'
+incroot:
+ @echo incroot='${INCROOT}'
+usrlibdir:
+ @echo usrlibdir='${USRLIBDIR}'
+libdir:
+ @echo libdir='${LIBDIR}'
+_ACEOF
+ if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+ for ac_var in incroot usrlibdir libdir; do
+ eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+ done
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl dylib la dll; do
+ if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+ test -f "$ac_im_libdir/libX11.$ac_extension"; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case $ac_im_incroot in
+ /usr/include) ac_x_includes= ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+ esac
+ case $ac_im_usrlibdir in
+ /usr/lib | /usr/lib64 | /lib | /lib64) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+ esac
+ fi
+ cd ..
+ rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R7/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R7
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R7/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R7
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+ # Guess where to find include files, by looking for Xlib.h.
+ # First, try using that file with no special directory specified.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/Xlib.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ for ac_dir in $ac_x_header_dirs; do
+ if test -r "$ac_dir/X11/Xlib.h"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+done
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+ # Check for the libraries.
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS=$LIBS
+ LIBS="-lX11 $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/Xlib.h>
+int
+main ()
+{
+XrmInitialize ()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ LIBS=$ac_save_LIBS
+for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+ # Don't even attempt the hair of trying to link an X program!
+ for ac_extension in a so sl dylib la dll; do
+ if test -r "$ac_dir/libX11.$ac_extension"; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+ no,* | *,no | *\'*)
+ # Didn't find X, or a directory has "'" in its name.
+ ac_cv_have_x="have_x=no";; #(
+ *)
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$ac_x_includes'\
+ ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+ *) have_x=yes;;
+ esac
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5
+$as_echo "$have_x" >&6; }
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$x_includes'\
+ ac_x_libraries='$x_libraries'"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5
+$as_echo "libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+if test "$no_x" = yes; then
+ # Not all programs may use this symbol, but it does not hurt to define it.
+
+$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h
+
+ X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+ if test -n "$x_includes"; then
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ # It would also be nice to do this for all -L options, not just this one.
+ if test -n "$x_libraries"; then
+ X_LIBS="$X_LIBS -L$x_libraries"
+ # For Solaris; some versions of Sun CC require a space after -R and
+ # others require no space. Words are not sufficient . . . .
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5
+$as_echo_n "checking whether -R must be followed by a space... " >&6; }
+ ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
+ ac_xsave_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ X_LIBS="$X_LIBS -R$x_libraries"
+else
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ X_LIBS="$X_LIBS -R $x_libraries"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5
+$as_echo "neither works" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_c_werror_flag=$ac_xsave_c_werror_flag
+ LIBS=$ac_xsave_LIBS
+ fi
+
+ # Check for system-dependent libraries X programs must link with.
+ # Do this before checking for the system-independent R6 libraries
+ # (-lICE), since we may need -lsocket or whatever for X linking.
+
+ if test "$ISC" = yes; then
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+ else
+ # Martyn Johnson says this is needed for Ultrix, if the X
+ # libraries were built with DECnet support. And Karl Berry says
+ # the Alpha needs dnet_stub (dnet does not exist).
+ ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XOpenDisplay ();
+int
+main ()
+{
+return XOpenDisplay ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; }
+if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dnet_dnet_ntoa=yes
+else
+ ac_cv_lib_dnet_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+fi
+
+ if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; }
+if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet_stub $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dnet_stub_dnet_ntoa=yes
+else
+ ac_cv_lib_dnet_stub_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+fi
+
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$ac_xsave_LIBS"
+
+ # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+ # to get the SysV transport functions.
+ # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4)
+ # needs -lnsl.
+ # The nsl library prevents programs from opening the X display
+ # on Irix 5.2, according to T.E. Dickey.
+ # The functions gethostbyname, getservbyname, and inet_addr are
+ # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_gethostbyname = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nsl_gethostbyname=yes
+else
+ ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+fi
+
+ if test $ac_cv_lib_nsl_gethostbyname = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
+$as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
+if ${ac_cv_lib_bsd_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_bsd_gethostbyname=yes
+else
+ ac_cv_lib_bsd_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
+$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
+fi
+
+ fi
+ fi
+
+ # lieder@skyler.mavd.honeywell.com says without -lsocket,
+ # socket/setsockopt and other routines are undefined under SCO ODT
+ # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
+ # on later versions), says Simon Leinen: it contains gethostby*
+ # variants that don't use the name server (or something). -lsocket
+ # must be given before -lnsl if both are needed. We assume that
+ # if connect needs -lnsl, so does gethostbyname.
+ ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_connect = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
+$as_echo_n "checking for connect in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_connect+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char connect ();
+int
+main ()
+{
+return connect ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_connect=yes
+else
+ ac_cv_lib_socket_connect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5
+$as_echo "$ac_cv_lib_socket_connect" >&6; }
+if test "x$ac_cv_lib_socket_connect" = xyes; then :
+ X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+fi
+
+ fi
+
+ # Guillermo Gomez says -lposix is necessary on A/UX.
+ ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove"
+if test "x$ac_cv_func_remove" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_remove = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5
+$as_echo_n "checking for remove in -lposix... " >&6; }
+if ${ac_cv_lib_posix_remove+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char remove ();
+int
+main ()
+{
+return remove ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_posix_remove=yes
+else
+ ac_cv_lib_posix_remove=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5
+$as_echo "$ac_cv_lib_posix_remove" >&6; }
+if test "x$ac_cv_lib_posix_remove" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+fi
+
+ fi
+
+ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+ ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat"
+if test "x$ac_cv_func_shmat" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_shmat = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5
+$as_echo_n "checking for shmat in -lipc... " >&6; }
+if ${ac_cv_lib_ipc_shmat+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lipc $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shmat ();
+int
+main ()
+{
+return shmat ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ipc_shmat=yes
+else
+ ac_cv_lib_ipc_shmat=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5
+$as_echo "$ac_cv_lib_ipc_shmat" >&6; }
+if test "x$ac_cv_lib_ipc_shmat" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+fi
+
+ fi
+ fi
+
+ # Check for libraries that X11R6 Xt/Xaw programs need.
+ ac_save_LDFLAGS=$LDFLAGS
+ test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+ # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+ # check for ICE first), but we must link in the order -lSM -lICE or
+ # we get undefined symbols. So assume we have SM if we have ICE.
+ # These have to be linked with before -lX11, unlike the other
+ # libraries we check for below, so use a different variable.
+ # John Interrante, Karl Berry
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5
+$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; }
+if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char IceConnectionNumber ();
+int
+main ()
+{
+return IceConnectionNumber ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ICE_IceConnectionNumber=yes
+else
+ ac_cv_lib_ICE_IceConnectionNumber=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
+$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
+if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then :
+ X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+fi
+
+ LDFLAGS=$ac_save_LDFLAGS
+
+fi
+
+CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
+LDFLAGS="${LDFLAGS} ${X_LIBS}"
+LIBS="${X_PRE_LIBS} ${LIBS} -lX11"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtToolkitInitialize in -lXt" >&5
+$as_echo_n "checking for XtToolkitInitialize in -lXt... " >&6; }
+if ${ac_cv_lib_Xt_XtToolkitInitialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XtToolkitInitialize ();
+int
+main ()
+{
+return XtToolkitInitialize ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xt_XtToolkitInitialize=yes
+else
+ ac_cv_lib_Xt_XtToolkitInitialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtToolkitInitialize" >&5
+$as_echo "$ac_cv_lib_Xt_XtToolkitInitialize" >&6; }
+if test "x$ac_cv_lib_Xt_XtToolkitInitialize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXT 1
+_ACEOF
+
+ LIBS="-lXt $LIBS"
+
+else
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtDisplayInitialize in -lXt" >&5
+$as_echo_n "checking for XtDisplayInitialize in -lXt... " >&6; }
+if ${ac_cv_lib_Xt_XtDisplayInitialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXt -lSM -lICE -lXpm -lX11 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XtDisplayInitialize ();
+int
+main ()
+{
+return XtDisplayInitialize ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xt_XtDisplayInitialize=yes
+else
+ ac_cv_lib_Xt_XtDisplayInitialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtDisplayInitialize" >&5
+$as_echo "$ac_cv_lib_Xt_XtDisplayInitialize" >&6; }
+if test "x$ac_cv_lib_Xt_XtDisplayInitialize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXT 1
+_ACEOF
+
+ LIBS="-lXt $LIBS"
+
+fi
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+for ac_func in setenv putenv
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork"
+if test "x$ac_cv_func_vfork" = xyes; then :
+
+fi
+
+
+for ac_header in dirent.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default"
+if test "x$ac_cv_header_dirent_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DIRENT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+case $target in
+ x86_64-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11 libraries" >&5
+$as_echo_n "checking for 64-bit X11 libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/X11R6/lib64" >&5
+$as_echo_n "checking for /usr/X11R6/lib64... " >&6; }
+if ${ac_cv_file__usr_X11R6_lib64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ test "$cross_compiling" = yes &&
+ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r "/usr/X11R6/lib64"; then
+ ac_cv_file__usr_X11R6_lib64=yes
+else
+ ac_cv_file__usr_X11R6_lib64=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__usr_X11R6_lib64" >&5
+$as_echo "$ac_cv_file__usr_X11R6_lib64" >&6; }
+if test "x$ac_cv_file__usr_X11R6_lib64" = xyes; then :
+
+ LDFLAGS="-L/usr/X11R6/lib64 ${LDFLAGS}"
+
+fi
+
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -Wno-pointer-sign accepted in CFLAGS" >&5
+$as_echo_n "checking if -Wno-pointer-sign accepted in CFLAGS... " >&6; }
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wno-pointer-sign"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+int foo;
+foo = 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+ CFLAGS="$ac_save_CFLAGS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5
+$as_echo_n "checking for deflate in -lz... " >&6; }
+if ${ac_cv_lib_z_deflate+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz -lz $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflate ();
+int
+main ()
+{
+return deflate ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_z_deflate=yes
+else
+ ac_cv_lib_z_deflate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5
+$as_echo "$ac_cv_lib_z_deflate" >&6; }
+if test "x$ac_cv_lib_z_deflate" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+ LIBS="-lz $LIBS"
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5
+$as_echo_n "checking for va_copy... " >&6; }
+if ${ac_cv_c_va_copy+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+int
+main ()
+{
+va_list ap1, ap2;
+ va_copy(ap1,ap2);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_c_va_copy="yes"
+else
+ ac_cv_c_va_copy="no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_va_copy" >&5
+$as_echo "$ac_cv_c_va_copy" >&6; }
+if test "$ac_cv_c_va_copy" = "yes"
+then
+
+$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __va_copy" >&5
+$as_echo_n "checking for __va_copy... " >&6; }
+if ${ac_cv_c___va_copy+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+int
+main ()
+{
+va_list ap1, ap2;
+ __va_copy(ap1,ap2);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_c___va_copy="yes"
+else
+ ac_cv_c___va_copy="no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c___va_copy" >&5
+$as_echo "$ac_cv_c___va_copy" >&6; }
+if test "$ac_cv_c___va_copy" = "yes"
+then
+
+$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if u_char defined" >&5
+$as_echo_n "checking if u_char defined... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+
+u_char foo;
+foo = 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ $as_echo "#define HAVE_U_CHAR 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+# Check whether --with-opengl was given.
+if test "${with_opengl+set}" = set; then :
+ withval=$with_opengl;
+ if test "$withval" = "no" -o "$withval" = "NO" ; then
+ xc_with_GL=
+ else
+ xc_with_GL=1
+ if test "$withval" != "no" -a "$withval" != "yes"; then
+ OGL_INCLUDE_DIR=${withval}
+ fi
+ fi
+
+fi
+
+
+# Check whether --enable-double-buffer was given.
+if test "${enable_double_buffer+set}" = set; then :
+ enableval=$enable_double_buffer;
+else
+
+ if test "x$xc_with_GL" == "x" ; then
+ $as_echo "#define DOUBLEBUFFER 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Double-buffering option not applicable to OpenGL version." >&5
+$as_echo "$as_me: WARNING: Double-buffering option not applicable to OpenGL version." >&2;}
+ fi
+
+fi
+
+
+# Check whether --enable-optimize was given.
+if test "${enable_optimize+set}" = set; then :
+ enableval=$enable_optimize;
+else
+
+ CFLAGS=`echo $CFLAGS | sed -e "s/ -O2//"`
+
+fi
+
+
+
+# Check whether --with-xpm was given.
+if test "${with_xpm+set}" = set; then :
+ withval=$with_xpm;
+ if test "$withval" != "no" -a "$withval" != "yes"; then
+ CPPFLAGS="${CPPFLAGS} -I$withval/include"
+ LDFLAGS="${LDFLAGS} -L$withval/lib"
+ fi
+
+fi
+
+
+for ac_header in X11/xpm.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/xpm.h" "ac_cv_header_X11_xpm_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_xpm_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_X11_XPM_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpmCreateImageFromData in -lXpm" >&5
+$as_echo_n "checking for XpmCreateImageFromData in -lXpm... " >&6; }
+if ${ac_cv_lib_Xpm_XpmCreateImageFromData+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXpm -lX11 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XpmCreateImageFromData ();
+int
+main ()
+{
+return XpmCreateImageFromData ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xpm_XpmCreateImageFromData=yes
+else
+ ac_cv_lib_Xpm_XpmCreateImageFromData=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xpm_XpmCreateImageFromData" >&5
+$as_echo "$ac_cv_lib_Xpm_XpmCreateImageFromData" >&6; }
+if test "x$ac_cv_lib_Xpm_XpmCreateImageFromData" = xyes; then :
+
+ LIBS="${LIBS} -lXpm"
+ $as_echo "#define HAVE_XPM 1" >>confdefs.h
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Xpm library not found" >&5
+$as_echo "$as_me: WARNING: Xpm library not found" >&2;}
+fi
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Xpm header not found" >&5
+$as_echo "$as_me: WARNING: Xpm header not found" >&2;}
+fi
+
+done
+
+
+
+
+#------------------------------------------------------------
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+# (This stuff ripped from libtool)
+#------------------------------------------------------------
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || xc_with_gnu_ld=yes
+else
+ xc_with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5
+$as_echo_n "checking for ld used by GCC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case "$ac_prog" in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ xc_with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$xc_with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${ac_cv_path_LD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$xc_with_gnu_ld" != no && break
+ else
+ test "$xc_with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${ac_cv_prog_gnu_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gnu_ld" >&5
+$as_echo "$ac_cv_prog_gnu_ld" >&6; }
+xc_with_gnu_ld=$ac_cv_prog_gnu_ld
+
+
+
+
+xc_with_tcl="yes"
+xc_with_tk="yes"
+xc_with_tcl_includes=""
+xc_with_tk_includes=""
+xc_with_tcl_libraries=""
+xc_with_tk_libraries=""
+
+
+# Check whether --with-tcl was given.
+if test "${with_tcl+set}" = set; then :
+ withval=$with_tcl;
+ xc_with_tcl=$withval
+ if test "$withval" == "no" -o "$withval" == "NO"; then
+ xc_with_tcl=""
+ fi
+
+fi
+
+
+
+if test $xc_with_GL ; then
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ if test $OGL_INCLUDE_DIR ; then
+ CPPFLAGS="$CPPFLAGS -I$OGL_INCLUDE_DIR"
+ fi
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
+if test "x$ac_cv_header_GL_gl_h" = xyes; then :
+
+else
+
+ echo "GL header files not found; disabling OpenGL"
+ xc_with_GL=
+
+fi
+
+
+ CPPFLAGS="$ac_save_CPPFLAGS"
+fi
+
+if test $xc_with_GL ; then
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glXCreateContext in -lGL" >&5
+$as_echo_n "checking for glXCreateContext in -lGL... " >&6; }
+if ${ac_cv_lib_GL_glXCreateContext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lGL $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char glXCreateContext ();
+int
+main ()
+{
+return glXCreateContext ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_GL_glXCreateContext=yes
+else
+ ac_cv_lib_GL_glXCreateContext=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glXCreateContext" >&5
+$as_echo "$ac_cv_lib_GL_glXCreateContext" >&6; }
+if test "x$ac_cv_lib_GL_glXCreateContext" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGL 1
+_ACEOF
+
+ LIBS="-lGL $LIBS"
+
+else
+
+ echo "GL library files not found; disabling OpenGL"
+ xc_with_GL=
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gluNewTess in -lGLU" >&5
+$as_echo_n "checking for gluNewTess in -lGLU... " >&6; }
+if ${ac_cv_lib_GLU_gluNewTess+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lGLU $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gluNewTess ();
+int
+main ()
+{
+return gluNewTess ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_GLU_gluNewTess=yes
+else
+ ac_cv_lib_GLU_gluNewTess=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLU_gluNewTess" >&5
+$as_echo "$ac_cv_lib_GLU_gluNewTess" >&6; }
+if test "x$ac_cv_lib_GLU_gluNewTess" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGLU 1
+_ACEOF
+
+ LIBS="-lGLU $LIBS"
+
+else
+
+ echo "GLU library files not found; disabling OpenGL"
+ xc_with_GL=
+
+fi
+
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LDFLAGS="$ac_save_LDFLAGS"
+fi
+
+if test $xc_with_GL ; then
+ $as_echo "#define OPENGL 1" >>confdefs.h
+
+ LIB_SPECS="${LIB_SPECS} -lGLU -lGL -lXi -lXmu -lXext"
+fi
+
+
+
+# Check whether --with-tk was given.
+if test "${with_tk+set}" = set; then :
+ withval=$with_tk; xc_with_tk=$withval
+fi
+
+
+# Check whether --with-tclincls was given.
+if test "${with_tclincls+set}" = set; then :
+ withval=$with_tclincls; xc_with_tcl_includes=$withval
+fi
+
+
+# Check whether --with-tkincls was given.
+if test "${with_tkincls+set}" = set; then :
+ withval=$with_tkincls; xc_with_tk_includes=$withval
+fi
+
+
+# Check whether --with-tcllibs was given.
+if test "${with_tcllibs+set}" = set; then :
+ withval=$with_tcllibs; xc_with_tcl_libraries=$withval
+fi
+
+
+# Check whether --with-tklibs was given.
+if test "${with_tklibs+set}" = set; then :
+ withval=$with_tklibs; xc_with_tk_libraries=$withval
+fi
+
+
+# -----------------------------------------------------------------------
+#
+# Find the Tcl build configuration file "tclConfig.sh"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+
+ TCL_INC_DIR="."
+ TK_INC_DIR="."
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclConfig.sh" >&5
+$as_echo_n "checking for tclConfig.sh... " >&6; }
+ tcl_config_sh=""
+
+ if test "$xc_with_tcl" = "no" ; then
+ xc_with_tcl=""
+ elif test "$xc_with_tcl" != "yes" ; then
+ #
+ # Verify that a tclConfig.sh file exists in the directory specified
+ # by --with-tcl.
+ #
+ for dir in \
+ $xc_with_tcl
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ elif test -r "$dir/unix/tclConfig.sh" ; then
+ tcl_config_sh="$dir/unix/tclConfig.sh"
+ break
+ fi
+ done
+ else
+ #
+ # Otherwise, search for Tcl configuration file.
+ #
+
+ # 1. Search previously named locations.
+
+ for dir in \
+ $prefix \
+ $exec_prefix
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ elif test -r "$dir/unix/tclConfig.sh" ; then
+ tcl_config_sh="$dir/unix/tclConfig.sh"
+ break
+ fi
+ done
+
+ # 2. Search standard locations.
+
+ if test "x$tcl_config_sh" = "x" ; then
+ for dir in \
+ `ls -dr /usr/local/tcl/tcl[7-9].[0-9]* 2>/dev/null` \
+ /usr/local/tcl \
+ /usr/local/lib \
+ /usr/local \
+ `ls -dr /usr/share/tcltk/tcl[7-9].[0-9]* 2>/dev/null` \
+ /sw/lib \
+ /usr/lib \
+ /usr/lib64 \
+ /usr
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ fi
+ done
+ fi
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_config_sh}" >&5
+$as_echo "${tcl_config_sh}" >&6; }
+
+ if test "x$tcl_config_sh" = "x" ; then
+ echo "can't find Tcl configuration script \"tclConfig.sh\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+# -----------------------------------------------------------------------
+#
+# Find the Tk build configuration file "tkConfig.sh"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tkConfig.sh" >&5
+$as_echo_n "checking for tkConfig.sh... " >&6; }
+ tk_config_sh=""
+ if test "$xc_with_tk" != "yes"; then
+ #
+ # Verify that a tkConfig.sh file exists in the directory specified
+ # by --with-tcl or --with-tk.
+ #
+ for dir in \
+ $xc_with_tk \
+ $xc_with_tcl
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ elif test -r "$dir/unix/tkConfig.sh" ; then
+ tk_config_sh="$dir/unix/tkConfig.sh"
+ break
+ fi
+ done
+ else
+ #
+ # Search for Tk configuration file.
+ #
+
+ #
+ # 1. Search previously named locations.
+ #
+ for dir in \
+ $prefix \
+ $exec_prefix
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ elif test -r "$dir/unix/tkConfig.sh" ; then
+ tk_config_sh="$dir/unix/tkConfig.sh"
+ break
+ fi
+ done
+ #
+ # 2. Search standard locations.
+ #
+ if test "x$tk_config_sh" = "x" ; then
+ for dir in \
+ /usr/local \
+ /usr \
+ `ls -dr /usr/local/lib/tk[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/lib/tk[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/local/tk/tk[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/local/tk[7-9].[0-9]* 2>/dev/null` \
+ /usr/local/tk \
+ `ls -dr /usr/local/lib/tcl[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/lib/tcl/tk[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/local/tcl/tcl[7-9].[0-9]* 2>/dev/null` \
+ `ls -dr /usr/share/tcltk/tk[7-9].[0-9]* 2>/dev/null` \
+ /sw/lib \
+ /usr/lib \
+ /usr/lib64 \
+ ${x_libraries}
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ fi
+ done
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tk_config_sh}" >&5
+$as_echo "${tk_config_sh}" >&6; }
+
+ if test "x$tk_config_sh" = "x" ; then
+ echo "can't find Tk configuration script \"tkConfig.sh\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+# -----------------------------------------------------------------------
+#
+# Source in the Tcl/Tk configuration scripts.
+#
+# BTW: Does anyone actually use the tclConfig.sh and tkConfig.sh
+# scripts? They seem to be always missing something. For example,
+# why don't they say where to find the Tcl and Tk header files?
+#
+# For example, give me the library directory paths separately
+# (I can't easily parse "-Ldir", but I can always paste a -L
+# on the front). If I want to specify equivalent of the -R flag,
+# I need the build a path of the library directories. Such as
+#
+# "-R $(BLTLIB):$(TKLIB):$(TCLLIB):($XLIB):$(JPEGLIB)"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ . $tcl_config_sh
+ . $tk_config_sh
+ LIBS="${TCL_LIBS} ${LIBS}"
+
+ if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
+ :
+ elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
+ :
+ elif test "$TCL_VERSION" = "$TK_VERSION" ; then
+ :
+ else
+ echo "Mismatched Tcl/Tk versions ($TCL_VERSION != $TK_VERSION)"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tcl_includes}" != "x" ; then
+ if test -r "${xc_with_tcl_includes}/tcl.h" ; then
+ TCL_INC_DIR=${xc_with_tcl_includes}
+ elif test "x${TCL_INCLUDE_SPEC}" == "x" ; then
+ echo "Can't find tcl.h in \"${xc_with_tcl_includes}\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ elif test "x${TCL_INCLUDE_SPEC}" == "x" ; then
+ for dir in \
+ ${TCL_PREFIX}/include/tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION} \
+ ${TCL_PREFIX}/include \
+ ${TCL_SRC_DIR}/generic \
+ ${TCL_INC_DIR}
+ do
+ if test -r "$dir/tcl.h" ; then
+ TCL_INC_DIR=$dir
+ break
+ fi
+ done
+ if test "x${TCL_INC_DIR}" = "x" ; then
+ echo "Can't find tcl.h header file"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ else
+ TCL_INC_DIR=`echo ${TCL_INCLUDE_SPEC} | sed -e '/-I/s/-I//'`
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tk_includes}" != "x" ; then
+ if test -r "${xc_with_tk_includes}/tk.h" ; then
+ TK_INC_DIR=${xc_with_tk_includes}
+ else
+ echo "Can't find tk.h in \"${xc_with_tk_includes}\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ else
+ for dir in \
+ ${TK_PREFIX}/include/tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION} \
+ ${TK_PREFIX}/include \
+ ${TK_SRC_DIR}/generic \
+ ${TK_INC_DIR} \
+ ${TCL_INC_DIR}
+ do
+ if test -r "$dir/tk.h" ; then
+ TK_INC_DIR=$dir
+ break
+ fi
+ done
+ if test "x${TK_INC_DIR}" = "x" ; then
+ echo "Can't find tk.h header file"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ case $target in
+ *-sunos4*|*-*-netbsd|NetBSD-*|FreeBSD-*|*-*-openbsd*|OpenBSD-*)
+ TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}"
+ TK_LIB_NAME="tk${TK_MAJOR_VERSION}${TK_MINOR_VERSION}"
+ ;;
+ *)
+ TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}"
+ TK_LIB_NAME="tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}"
+ ;;
+ esac
+
+ TCL_LIB_SPEC="-l${TCL_LIB_NAME}"
+ TK_LIB_SPEC="-l${TK_LIB_NAME}"
+
+# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX
+# We really ought to run "ldd" to confirm that the linked libraries match.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wish executable" >&5
+$as_echo_n "checking for wish executable... " >&6; }
+ for dir in \
+ ${TK_EXEC_PREFIX}/bin \
+ ${TK_EXEC_PREFIX}
+ do
+ for wishexe in \
+ wish \
+ wish${TK_VERSION} \
+ wish.exe \
+ wish${TK_VERSION}.exe
+ do
+ if test -r "$dir/$wishexe" ; then
+ WISH_EXE=$dir/$wishexe
+ break
+ fi
+ done
+ if test "x${WISH_EXE}" != "x" ; then
+ break
+ fi
+ done
+ if test "x${WISH_EXE}" = "x" ; then
+ echo "Warning: Can't find executable for \"wish\". You may have to"
+ echo "manually set the value for WISH_EXE in the xcircuit startup script."
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WISH_EXE}" >&5
+$as_echo "${WISH_EXE}" >&6; }
+ fi
+
+# Have to define SHDLIB_EXT here even though we have to do it below, too.
+ case $target in
+ *-hpux*)
+ SHDLIB_EXT=".sl"
+ ;;
+ *cygwin*)
+ SHDLIB_EXT=".dll"
+ ;;
+ *-darwin*)
+ SHDLIB_EXT=".dylib"
+ ;;
+ *-openbsd*)
+ SHDLIB_EXT=".so.${TCL_LIB_FILE##*.so.}"
+ ;;
+ *)
+ SHDLIB_EXT=".so"
+ ;;
+ esac
+
+ if test "x${xc_with_tcl_libraries}" != "x" ; then
+ for libname in \
+ "${xc_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT}"
+ do
+ if test -r "$libname" ; then
+ TCL_LIB_DIR="${xc_with_tcl_libraries}"
+ break
+ fi
+ done
+
+ if test "x${TCL_LIB_DIR}" = "x" ; then
+ echo "Can't find tcl library in \"${xc_with_tcl_libraries}\""
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ else
+ for libpfix in "lib64" "lib"
+ do
+ libname="${TCL_EXEC_PREFIX}/${libpfix}/lib${TCL_LIB_NAME}${SHDLIB_EXT}"
+ if test -r "$libname" ; then
+ TCL_LIB_DIR="${TCL_EXEC_PREFIX}/${libpfix}"
+ break
+ fi
+ done
+ if test "x${TCL_LIB_DIR}" = "x" ; then
+ echo "Can't find tcl library"
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tk_libraries}" != "x" ; then
+ for libname in \
+ "${xc_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT}"
+ do
+ if test -r "$libname" ; then
+ TK_LIB_DIR="${xc_with_tk_libraries}"
+ break
+ fi
+ done
+ if test "x${TK_LIB_DIR}" = "x" ; then
+ echo "Can't find tk library in \"${xc_with_tk_libraries}\""
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ else
+ for libpfix in "lib64" "lib"
+ do
+ libname="${TK_EXEC_PREFIX}/${libpfix}/lib${TK_LIB_NAME}${SHDLIB_EXT}"
+ if test -r "$libname" ; then
+ TK_LIB_DIR="${TK_EXEC_PREFIX}/${libpfix}"
+ break
+ fi
+ done
+ if test "x${TK_LIB_DIR}" = "x" ; then
+ echo "Can't find tk library"
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+
+# -----------------------------------------------------------------------
+#
+# Tk libraries and header files
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "${TK_INC_DIR}" != "/usr/include" -a \
+ "${TK_INC_DIR}" != "${TCL_INC_DIR}"; then
+ INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
+ fi
+ if test "${TK_LIB_DIR}" = "/usr/lib" -o \
+ "${TK_LIB_DIR}" = "/usr/lib64" ; then
+ LIB_SPECS="${TK_LIB_SPEC}"
+ else
+ LIB_SPECS="-L${TK_LIB_DIR} ${TK_LIB_SPEC}"
+ if test "x${loader_run_path}" = "x" ; then
+ loader_run_path="${TK_LIB_DIR}"
+ else
+ loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
+ fi
+ fi
+
+# -----------------------------------------------------------------------
+#
+# Tcl libraries and header files
+#
+# Add a header file directory specification only if the Tcl headers reside
+# in a different directory from Tk's.
+#
+#
+# -----------------------------------------------------------------------
+ if test "x${TCL_INCLUDE_SPEC}" != "x" ; then
+ INC_SPECS="${INC_SPECS} ${TCL_INCLUDE_SPEC}"
+ elif test "${TCL_INC_DIR}" != "/usr/include" ; then
+ INC_SPECS="${INC_SPECS} -I${TCL_INC_DIR}"
+ fi
+
+ if test "${TCL_LIB_DIR}" = "/usr/lib" -o \
+ "${TCL_LIB_DIR}" = "/usr/lib64" -o \
+ "${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then
+ LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}"
+ else
+ LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}"
+ if test "x${loader_run_path}" = "x" ; then
+ loader_run_path="${TCL_LIB_DIR}"
+ else
+ loader_run_path="${TCL_LIB_DIR}:${loader_run_path}"
+ fi
+ fi
+
+#--------------------------------------------------------------------
+#
+# Check if we can generate shared libraries on this system. Set flags
+# to generate shared libraries for systems that we know about. Start
+# with the values found in tclConfig.sh, make changes as we know about
+# the different systems.
+#
+#--------------------------------------------------------------------
+
+# Initialize shared library build variables
+
+ LDDL_FLAGS="-shared"
+ SHDLIB_EXT=".so"
+ LD_RUN_PATH=""
+ EXTRA_LIB_SPECS=""
+
+ build_shared="yes"
+
+ case $target in
+ *-aix4.[2-9]*)
+ # No Position-Independent flags needed
+
+ # Use the installed export file or the one found in the source directory.
+
+ if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then
+ tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp"
+ else
+ tcl_exp="${TCL_SRC_DIR}/unix/lib.exp"
+ fi
+ if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then
+ tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp"
+ else
+ tk_exp="${TK_SRC_DIR}/unix/lib.exp"
+ fi
+
+ full_src_path=`cd ${srcdir}; pwd`
+
+ # Use shell-script to link shared library
+ SHLIB_LD="${full_src_path}/cf/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}"
+
+ SHLIB_LIB_SPEC="${aix_lib_specs} -lc"
+
+ LDFLAGS="-L${loader_run_path}"
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-aix*)
+ # No Position-Independent flags needed
+
+ # Use the installed export file or the one found in the source directory.
+
+ if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then
+ tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp"
+ else
+ tcl_exp="${TCL_SRC_DIR}/unix/lib.exp"
+ fi
+ if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then
+ tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp"
+ else
+ tk_exp="${TK_SRC_DIR}/unix/lib.exp"
+ fi
+
+ full_src_path=`cd ${srcdir}/cf; pwd`
+
+ # Use shell-script to link shared library
+
+ SHLIB_LD="${full_src_path}/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}"
+
+ SHLIB_LIB_SPECS="${aix_lib_specs} -lc"
+
+ LDFLAGS="-L${loader_run_path}"
+ EXTRA_LIB_SPECS="-lld"
+ ;;
+
+ *-bsdi2*|*-bsdi3*)
+ SHLIB_LD="shlicc"
+ LDDL_FLAGS="-r"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-darwin*)
+ SHDLIB_EXT=".dylib"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS="-dynamiclib -bind_at_load"
+ else
+ LDDL_FLAGS="-single_module -dynamiclib -flat_namespace"
+ LDDL_FLAGS="${LDDL_FLAGS} -undefined suppress -noprebind"
+ SHLIB_CFLAGS="-I/sw/include -fno-common"
+ fi
+ ;;
+
+ *cygwin*)
+ $as_echo "#define CYGWIN 1" >>confdefs.h
+
+ SHDLIB_EXT=".dll"
+ LDDL_FLAGS="-shared -Wl,--enable-auto-image-base -Wl,-rpath,${loader_run_path}"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ ;;
+
+ *-bsdi4*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@'
+ ;;
+
+ *-dgux*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-hpux*)
+ if test "$GCC" = "no" ; then
+ DEFINES="$DEFINES -D_HPUX_SOURCE"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+ found=yes
+else
+ found=no
+fi
+
+ if test "${found}" = "yes" ; then
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-b -E -n +s +b,${loader_run_path}:."
+ SHDLIB_EXT=".sl"
+
+ # The run path is included in both LDFLAGS and LDDL_FLAGS
+ # because SHLIB_LD is ld and LD is cc/gcc.
+
+ LDFLAGS="-Wl,-E -Wl,+s,+b,${loader_run_path}:."
+ EXTRA_LIB_SPECS="-ldld"
+ fi
+ ;;
+
+ *-irix64-6.5*)
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-32 -shared -rdata_shared"
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ ;;
+
+ *-irix-56.*|*-irix64-*)
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-shared -rdata_shared"
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ LDFLAGS=""
+ if test "$GCC" = "yes" ; then
+ SHLIB_CFLAGS="-mabi=n32 $SHLIB_CFLAGS"
+ LDDL_FLAGS="-mabi=n32 $LDDL_FLAGS"
+ LDFLAGS="-mabi=n32 $LDFLAGS"
+ else
+ CFLAGS="-n32 $CFLAGS"
+ LDFLAGS="-n32 $LDFLAGS"
+ fi
+ ;;
+
+ *-linux*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS='-shared -Wl,-soname,$@'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+
+ EXTRA_LIB_SPECS="-ldl"
+
+ case $target in
+ x86_64-*)
+ # AMD 64-bit archictecture
+ # Add -fPIC to standard compile switch
+ CFLAGS="${CFLAGS} -fPIC"
+ ;;
+ esac
+ ;;
+
+ *-mp-ras-02*)
+ SHLIB_CFLAGS="-G -K PIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS=""
+ ;;
+
+ *-mp-ras-*)
+ SHLIB_CFLAGS="-G -K PIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS="-Wl,-Bexport"
+ ;;
+
+ *-ncr-sysv4-*2*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-ncr-sysv4*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G -Wl,-Bexport"
+
+ LDFLAGS="-Wl,-Bexport"
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-netbsd*|*-freebsd*|*-openbsd*)
+ # Not available on all versions: check for include file.
+ ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+ test_ok=yes
+else
+ test_ok=no
+fi
+
+
+ if test "$test_ok" = yes; then
+ SHLIB_CFLAGS="-fpic"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-shared"
+ fi
+ ;;
+
+ *-nextstep*)
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-nostdlib -r"
+ ;;
+
+ *-osf1-1.012*)
+ # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1
+
+ # Warning: Ugly Makefile Hack
+ # Make package name same as library name
+
+ SHLIB_LD='ld -R -export $@:'
+ ;;
+
+ *-osf1-1.*)
+ # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
+
+ SHLIB_CFLAGS="-fpic"
+ SHLIB_LD="ld -shared"
+ ;;
+
+ *-osf1V*)
+ # Digital OSF/1
+
+ SHLIB_LD='ld'
+ LDDL_FLAGS='-shared -expect_unresolved "*"'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ LDFLAGS=""
+ ;;
+
+ *-sco*)
+ # Note, dlopen is available only on SCO 3.2.5 and greater. However,
+ # this test works, since "uname -s" was non-standard in 3.2.4 and
+ # below.
+
+ SHLIB_CFLAGS="-Kpic -belf"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-G"
+ LDFLAGS="-belf -Wl,-Bexport"
+ ;;
+
+ *-sni-sysv*)
+
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-sunos4*)
+
+ SHLIB_CFLAGS="-PIC"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-assert pure-text"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-solaris2*)
+
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS='-rdynamic -shared -Wl,-E -Wl,-soname,$@'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ else
+ LDDL_FLAGS="-shared -mimpure-text"
+ LD_RUN_PATH="-R ${loader_run_path}"
+ fi
+ EXTRA_LIB_SPECS="-ldl"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ ;;
+
+ *-mips-dde-sysv*)
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-pc-sysv4* | *-unixware-5*)
+ SHLIB_CFLAGS="-G -KPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS=" -Wl,-Bexport"
+ ;;
+
+ esac
+
+# If we're running gcc, then set SHLIB_CFLAGS flags for compiling
+# shared libraries for gcc, instead of those of the vendor's
+# compiler.
+
+ if test "$GCC" = "yes" ; then
+# SHLIB_CFLAGS="${SHLIB_CFLAGS} -fPIC"
+ CFLAGS="-fPIC ${CFLAGS}"
+ fi
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS="${LDDL_FLAGS} -Wl,--version-script=symbol.map"
+ fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+fi
+
+# Check whether --enable-asg was given.
+if test "${enable_asg+set}" = set; then :
+ enableval=$enable_asg;
+ $as_echo "#define ASG 1" >>confdefs.h
+
+ $as_echo "#define CONFIGURED 1" >>confdefs.h
+
+ SUBDIRS="asg spiceparser"
+ SUBLIB="asg/libasg.a spiceparser/libspiceparser.a"
+
+fi
+
+
+# Check whether --enable-lgf was given.
+if test "${enable_lgf+set}" = set; then :
+ enableval=$enable_lgf;
+else
+
+ HAVE_LGF=LGF
+ $as_echo "#define LGF 1" >>confdefs.h
+
+
+fi
+
+
+# Check whether --enable-focus-fix was given.
+if test "${enable_focus_fix+set}" = set; then :
+ enableval=$enable_focus_fix;
+else
+
+ $as_echo "#define INPUT_FOCUS 1" >>confdefs.h
+
+
+fi
+
+
+
+# Check whether --with-gs was given.
+if test "${with_gs+set}" = set; then :
+ withval=$with_gs;
+ if test -f "$withval"; then
+ GS_EXEC=$withval
+ else
+ GS_EXEC=gs
+ fi
+
+else
+
+ # Extract the first word of "gs", so it can be a program name with args.
+set dummy gs; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_GS_EXEC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$GS_EXEC"; then
+ ac_cv_prog_GS_EXEC="$GS_EXEC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_GS_EXEC=""
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_GS_EXEC" && ac_cv_prog_GS_EXEC="gs"
+fi
+fi
+GS_EXEC=$ac_cv_prog_GS_EXEC
+if test -n "$GS_EXEC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GS_EXEC" >&5
+$as_echo "$GS_EXEC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define GS_EXEC "$GS_EXEC"
+_ACEOF
+
+
+
+# Check whether --with-ngspice was given.
+if test "${with_ngspice+set}" = set; then :
+ withval=$with_ngspice;
+ if test -f "$withval"; then
+ SPICE_EXEC=$withval
+ else
+ SPICE_EXEC=ngspice
+ fi
+
+else
+
+ # Extract the first word of "ngspice", so it can be a program name with args.
+set dummy ngspice; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_SPICE_EXEC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$SPICE_EXEC"; then
+ ac_cv_prog_SPICE_EXEC="$SPICE_EXEC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_SPICE_EXEC=""
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_SPICE_EXEC" && ac_cv_prog_SPICE_EXEC="ngspice"
+fi
+fi
+SPICE_EXEC=$ac_cv_prog_SPICE_EXEC
+if test -n "$SPICE_EXEC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SPICE_EXEC" >&5
+$as_echo "$SPICE_EXEC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define SPICE_EXEC "$SPICE_EXEC"
+_ACEOF
+
+
+
+xc_with_python=""
+PYTHON=
+
+
+# Check whether --with-python was given.
+if test "${with_python+set}" = set; then :
+ withval=$with_python; xc_with_python=$withval
+fi
+
+
+if test "x$xc_with_tcl" != "x" ; then
+ xc_with_python=""
+elif test "$xc_with_python" = "no" ; then
+ xc_with_python=""
+elif test "$xc_with_python" = "yes" ; then
+ # Extract the first word of "python", so it can be a program name with args.
+set dummy python; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+elif test "x$xc_with_python" != x; then
+ test -f "$xc_with_python" && PYTHON=$xc_with_python
+fi
+
+if test "x$PYTHON" != x; then
+ _py_version=`$PYTHON -c 'import sys; print sys.version[0:3]'`
+ _py_prefix=`$PYTHON -c 'import sys; print sys.prefix'`
+ _py_exec_prefix=`$PYTHON -c 'import sys; print sys.exec_prefix'`
+
+ _py_include="$_py_prefix/include/python$_py_version"
+ _py_lib="$_py_exec_prefix/lib/python$_py_version/config"
+ _py_makefile="$_py_lib/Makefile"
+
+ if test $_py_version = 1.5; then
+ echo
+ echo "*** WARNING:"
+ echo "*** Python version 1.5 detected: This version of Python has a known fatal"
+ echo "*** bug. Disabling Python interface. If you want the embedded Python"
+ echo "*** interface, you will need to get an updated version of Python."
+ echo
+ PYTHON=""
+ fi
+fi
+
+if test "x$PYTHON" != x; then
+ if test -f $_py_makefile; then
+ _py_libs=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $_py_makefile`
+ _py_libm=`sed -n -e 's/^LIBM=\(.*\)/\1/p' $_py_makefile`
+ else
+ _py_libs='-lpthread -ldl -lutil -ldb'
+ _py_libm='-lm'
+ fi
+
+ # Now that we think we know where the python include and
+ # library files are, make sure we can build a small
+ # program against them.
+ _save_CPPFLAGS=${CPPFLAGS}
+ _save_LDFLAGS=${LDFLAGS}
+ _save_LIBS=${LIBS}
+
+ CPPFLAGS="$CPPFLAGS -I$_py_include"
+ LDFLAGS="$LDFLAGS -L$_py_lib"
+
+ case "$target_os" in
+ *cygwin*)
+ PYLIB="-lpython$_py_version"
+ LIBS="$PYLIB.dll $LIBS $X_PRE_LIBS $_py_libs"
+ ;;
+ *)
+ LIBS="$LIBS -lpython$_py_version $_py_libs $_py_libm"
+ ;;
+ esac
+
+
+ HAVE_PYTHON=0
+ ac_fn_c_check_header_mongrel "$LINENO" "Python.h" "ac_cv_header_Python_h" "$ac_includes_default"
+if test "x$ac_cv_header_Python_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython$_py_version" >&5
+$as_echo_n "checking for Py_Initialize in -lpython$_py_version... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include "Python.h"
+int
+main ()
+{
+Py_Initialize();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ HAVE_PYTHON=1
+ INTERPRETER=PYTHON
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+
+ if test "x$HAVE_PYTHON" = x0; then
+ CPPFLAGS=$_save_CPPFLAGS
+ LDFLAGS=$_save_LDFLAGS
+ LIBS=$_save_LIBS
+ PYTHON=""
+ fi
+fi
+
+if test "x$PYTHON" != x; then
+ STARTUP_FILE="xcstartup.py"
+ INTERP_PATH="python"
+ WRAPPER_SCRIPT=""
+ SUBDIRS="${SUBDIRS} Xw"
+ SUBLIB="${SUBLIB} Xw/libxcXw.a"
+ XCIRCUIT_TARGET="xcircuit"
+elif test "x$xc_with_tcl" != "x" ; then
+ INTERPRETER=TCL
+ STARTUP_FILE="xcstartup.tcl"
+ INTERP_PATH="tcl"
+ WRAPPER_SCRIPT="wrapper.tcl"
+ $as_echo "#define TCL_WRAPPER 1" >>confdefs.h
+
+ XCIRCUIT_TARGET="tcl"
+ ALL_TARGET="all-recursive"
+ INSTALL_TARGET="install-recursive"
+else
+ STARTUP_FILE="startup.script"
+ INTERP_PATH="."
+ WRAPPER_SCRIPT=""
+ SUBDIRS="${SUBDIRS} Xw"
+ SUBLIB="${SUBLIB} Xw/libxcXw.a"
+ XCIRCUIT_TARGET="xcircuit"
+fi
+
+# Add -lm last to LDFLAGS, or Tcl/Tk's addition of -lieee can cause
+# an error.
+EXTRA_LIB_SPECS="$EXTRA_LIB_SPECS -lm"
+
+
+# Check whether --enable-memdebug was given.
+if test "${enable_memdebug+set}" = set; then :
+ enableval=$enable_memdebug;
+ if test "x$xc_with_tcl" = "x" ; then
+ LIBS="${LIBS} -lefence"
+ else
+ $as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h
+
+ fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile Xw/Makefile asg/Makefile spiceparser/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "Xw/Makefile") CONFIG_FILES="$CONFIG_FILES Xw/Makefile" ;;
+ "asg/Makefile") CONFIG_FILES="$CONFIG_FILES asg/Makefile" ;;
+ "spiceparser/Makefile") CONFIG_FILES="$CONFIG_FILES spiceparser/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..34d0f4b
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,1359 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(xcircuit.c,, xcircuit-dev@lists.sourceforge.net)
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR(xcircuit.c)
+
+AC_CANONICAL_SYSTEM
+
+dnl this call will define PACKAGE and VERSION
+dnl please use this as the primary reference for the version number
+PACKAGE=xcircuit
+
+VERSION=`cat ./VERSION | cut -d. -f1-2`
+AM_INIT_AUTOMAKE(${PACKAGE}, ${VERSION})
+
+dnl Initialize some variables
+SUBDIRS=
+SUBLIB=
+STDLIBS=
+XCIRCUIT_TARGET=
+ALL_TARGET="undefined-target"
+INSTALL_TARGET="undefined-install-target"
+REVISION=`cat ./VERSION | cut -d. -f3`
+INTERPRETER=NOINTERP
+HAVE_LGF=NOFORMATS
+xc_with_GL=
+
+SHLIB_CFLAGS=""
+LIB_SPECS=""
+WISH_EXE=""
+
+dnl Default is to use Tcl; if it can't be found, then flag a warning
+dnl and revert to the non-Tcl version.
+
+dnl pass the version string on the the makefiles
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+AC_SUBST(REVISION)
+
+dnl Setup for automake in subdirectories
+AC_PROG_MAKE_SET
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_ISC_POSIX
+dnl AM_C_PROTOTYPES
+if test "x$U" != "x"; then
+ AC_MSG_ERROR(Compiler not ANSI compliant)
+fi
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+dnl GNU M4 is preferred due to some of the option switches.
+AC_PATH_PROGS([M4], [gm4 gnum4 m4],)
+
+case "$target_os" in
+ *cygwin*)
+ ;;
+ *)
+ AC_CHECK_LIB(m, sin)
+ ;;
+esac
+
+dnl check size of pointer for correct behavior on 64-bit systems
+AC_CHECK_SIZEOF([void *], 4)
+AC_CHECK_SIZEOF([unsigned int], 4)
+AC_CHECK_SIZEOF([unsigned long], 8)
+AC_CHECK_SIZEOF([unsigned long long], 16)
+
+dnl check for X libraries and include files
+AC_PATH_XTRA
+CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
+LDFLAGS="${LDFLAGS} ${X_LIBS}"
+LIBS="${X_PRE_LIBS} ${LIBS} -lX11"
+AC_CHECK_LIB(Xt, XtToolkitInitialize,,[
+AC_CHECK_LIB(Xt, XtDisplayInitialize,,,-lSM -lICE -lXpm -lX11)])
+
+dnl Check for required header files
+AC_HEADER_STDC
+
+dnl Need either setenv or putenv
+AC_CHECK_FUNCS(setenv putenv)
+
+dnl Check for vfork
+AC_CHECK_FUNC(vfork)
+
+dnl Check for <dirent.h>
+AC_CHECK_HEADERS(dirent.h)
+
+dnl Check for lib64. This is a quick hack for Fedora Core on the
+dnl AMD Opteron; don't know if it works with others.
+case $target in
+ x86_64-*)
+ AC_MSG_CHECKING([for 64-bit X11 libraries])
+ AC_CHECK_FILE([/usr/X11R6/lib64], [
+ LDFLAGS="-L/usr/X11R6/lib64 ${LDFLAGS}"
+ ], )
+ ;;
+esac
+
+dnl Check for valid cflag "-Wno-pointer-sign"
+AC_MSG_CHECKING(if -Wno-pointer-sign accepted in CFLAGS)
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wno-pointer-sign"
+AC_TRY_COMPILE(,[
+int foo;
+foo = 0],[
+ AC_MSG_RESULT(yes)],[
+ CFLAGS="$ac_save_CFLAGS"
+ AC_MSG_RESULT(no)])
+
+dnl Check for Flate compression routines
+AC_CHECK_LIB(z, deflate,,,-lz)
+
+dnl Check for va_copy
+AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy,
+ AC_TRY_LINK(
+ [#include <stdarg.h>],
+ [va_list ap1, ap2;
+ va_copy(ap1,ap2);
+ ],
+ [ac_cv_c_va_copy="yes"],
+ [ac_cv_c_va_copy="no"])
+ )
+if test "$ac_cv_c_va_copy" = "yes"
+then
+ AC_DEFINE(HAVE_VA_COPY, 1, [Define if we have va_copy])
+fi
+AC_CACHE_CHECK([for __va_copy], ac_cv_c___va_copy,
+ AC_TRY_LINK(
+ [#include <stdarg.h>],
+ [va_list ap1, ap2;
+ __va_copy(ap1,ap2);
+ ],
+ [ac_cv_c___va_copy="yes"],
+ [ac_cv_c___va_copy="no"])
+ )
+if test "$ac_cv_c___va_copy" = "yes"
+then
+ AC_DEFINE(HAVE___VA_COPY, 1, [Define if we have __va_copy])
+fi
+
+AC_MSG_CHECKING(if u_char defined)
+AC_TRY_COMPILE([#include <sys/types.h>],[
+u_char foo;
+foo = 0],[
+ AC_DEFINE(HAVE_U_CHAR)
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no))
+
+dnl OpenGL Graphics
+AC_ARG_WITH(opengl,
+[ --with-opengl=DIR use OpenGL include files in DIR], [
+ if test "$withval" = "no" -o "$withval" = "NO" ; then
+ xc_with_GL=
+ else
+ xc_with_GL=1
+ if test "$withval" != "no" -a "$withval" != "yes"; then
+ OGL_INCLUDE_DIR=${withval}
+ fi
+ fi
+])
+
+dnl Graphics double-buffering? Enabled by default unless OpenGL used.
+AC_ARG_ENABLE(double-buffer,
+[ --disable-double-buffer disable graphics double-buffering], , [
+ if test "x$xc_with_GL" == "x" ; then
+ AC_DEFINE(DOUBLEBUFFER)
+ else
+ AC_MSG_WARN(Double-buffering option not applicable to OpenGL version.)
+ fi
+])
+
+dnl Enable compile-time Optimization? Disable by default for debugging
+AC_ARG_ENABLE(optimize,
+[ --enable-optimize enable compile-time optimizer flag -O2], , [
+ CFLAGS=`echo $CFLAGS | sed -e "s/ -O2//"`
+])
+
+dnl check for Xpm library
+AC_ARG_WITH(xpm,
+[ --with-xpm=DIR use Xpm include/library files in DIR], [
+ if test "$withval" != "no" -a "$withval" != "yes"; then
+ CPPFLAGS="${CPPFLAGS} -I$withval/include"
+ LDFLAGS="${LDFLAGS} -L$withval/lib"
+ fi
+])
+
+AC_CHECK_HEADERS(X11/xpm.h,
+ AC_CHECK_LIB(Xpm, XpmCreateImageFromData, [
+ LIBS="${LIBS} -lXpm"
+ AC_DEFINE(HAVE_XPM)], [
+ AC_MSG_WARN(Xpm library not found)], -lX11),
+ AC_MSG_WARN(Xpm header not found))
+
+dnl Check for GNU ld. This needs to be qualified for Solaris, which
+dnl may use gcc for the C compiler but not for the linker.
+
+dnl check if the linker is a GNU linker
+
+#------------------------------------------------------------
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+# (This stuff ripped from libtool)
+#------------------------------------------------------------
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [[default=no]]],
+test "$withval" = no || xc_with_gnu_ld=yes, xc_with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+dnl ###not for PostgreSQL### AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case "$ac_prog" in
+ # Accept absolute paths.
+changequote(,)dnl
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ xc_with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$xc_with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$xc_with_gnu_ld" != no && break
+ else
+ test "$xc_with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi])
+xc_with_gnu_ld=$ac_cv_prog_gnu_ld
+])
+
+AC_PROG_LD
+
+dnl --- Enable TCL by default
+
+xc_with_tcl="yes"
+xc_with_tk="yes"
+xc_with_tcl_includes=""
+xc_with_tk_includes=""
+xc_with_tcl_libraries=""
+xc_with_tk_libraries=""
+
+AC_ARG_WITH(tcl,
+[ --with-tcl=DIR Find tclConfig.sh in DIR], [
+ xc_with_tcl=$withval
+ if test "$withval" == "no" -o "$withval" == "NO"; then
+ xc_with_tcl=""
+ fi
+], )
+
+dnl -----------------------------------------------------------------------
+dnl Find OpenGL, if selected
+dnl -----------------------------------------------------------------------
+
+if test $xc_with_GL ; then
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ if test $OGL_INCLUDE_DIR ; then
+ CPPFLAGS="$CPPFLAGS -I$OGL_INCLUDE_DIR"
+ fi
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ AC_CHECK_HEADER(GL/gl.h, , [
+ echo "GL header files not found; disabling OpenGL"
+ xc_with_GL=
+ ],)
+ CPPFLAGS="$ac_save_CPPFLAGS"
+fi
+
+if test $xc_with_GL ; then
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
+ AC_CHECK_LIB(GL, glXCreateContext, , [
+ echo "GL library files not found; disabling OpenGL"
+ xc_with_GL=
+ ],)
+ AC_CHECK_LIB(GLU, gluNewTess, , [
+ echo "GLU library files not found; disabling OpenGL"
+ xc_with_GL=
+ ],)
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LDFLAGS="$ac_save_LDFLAGS"
+fi
+
+if test $xc_with_GL ; then
+ AC_DEFINE(OPENGL)
+ LIB_SPECS="${LIB_SPECS} -lGLU -lGL -lXi -lXmu -lXext"
+fi
+
+dnl -----------------------------------------------------------------------
+dnl If TCL is not disabled, do our best to find it
+dnl -----------------------------------------------------------------------
+
+AC_ARG_WITH(tk, [ --with-tk=DIR Find tkConfig.sh in DIR],
+ xc_with_tk=$withval)
+AC_ARG_WITH(tclincls, [ --with-tclincls=DIR Find tcl.h in DIR],
+ xc_with_tcl_includes=$withval)
+AC_ARG_WITH(tkincls, [ --with-tkincls=DIR Find tk.h in DIR],
+ xc_with_tk_includes=$withval)
+AC_ARG_WITH(tcllibs, [ --with-tcllibs=DIR Find Tcl library in DIR],
+ xc_with_tcl_libraries=$withval)
+AC_ARG_WITH(tklibs, [ --with-tklibs=DIR Find Tk library in DIR],
+ xc_with_tk_libraries=$withval)
+
+# -----------------------------------------------------------------------
+#
+# Find the Tcl build configuration file "tclConfig.sh"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+
+ TCL_INC_DIR="."
+ TK_INC_DIR="."
+
+
+ AC_MSG_CHECKING([for tclConfig.sh])
+ tcl_config_sh=""
+
+ if test "$xc_with_tcl" = "no" ; then
+ xc_with_tcl=""
+ elif test "$xc_with_tcl" != "yes" ; then
+ #
+ # Verify that a tclConfig.sh file exists in the directory specified
+ # by --with-tcl.
+ #
+ for dir in \
+ $xc_with_tcl
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ elif test -r "$dir/unix/tclConfig.sh" ; then
+ tcl_config_sh="$dir/unix/tclConfig.sh"
+ break
+ fi
+ done
+ else
+ #
+ # Otherwise, search for Tcl configuration file.
+ #
+
+ # 1. Search previously named locations.
+
+ for dir in \
+ $prefix \
+ $exec_prefix
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ elif test -r "$dir/unix/tclConfig.sh" ; then
+ tcl_config_sh="$dir/unix/tclConfig.sh"
+ break
+ fi
+ done
+
+ # 2. Search standard locations.
+
+ if test "x$tcl_config_sh" = "x" ; then
+ for dir in \
+ `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
+ /usr/local/tcl \
+ /usr/local/lib \
+ /usr/local \
+ `ls -dr /usr/share/tcltk/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
+ /sw/lib \
+ /usr/lib \
+ /usr/lib64 \
+ /usr
+ do
+ if test -r "$dir/tclConfig.sh" ; then
+ tcl_config_sh="$dir/tclConfig.sh"
+ break
+ elif test -r "$dir/lib/tclConfig.sh" ; then
+ tcl_config_sh="$dir/lib/tclConfig.sh"
+ break
+ fi
+ done
+ fi
+ fi
+
+ AC_MSG_RESULT([${tcl_config_sh}])
+
+ if test "x$tcl_config_sh" = "x" ; then
+ echo "can't find Tcl configuration script \"tclConfig.sh\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+# -----------------------------------------------------------------------
+#
+# Find the Tk build configuration file "tkConfig.sh"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ AC_MSG_CHECKING([for tkConfig.sh])
+ tk_config_sh=""
+ if test "$xc_with_tk" != "yes"; then
+ #
+ # Verify that a tkConfig.sh file exists in the directory specified
+ # by --with-tcl or --with-tk.
+ #
+ for dir in \
+ $xc_with_tk \
+ $xc_with_tcl
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ elif test -r "$dir/unix/tkConfig.sh" ; then
+ tk_config_sh="$dir/unix/tkConfig.sh"
+ break
+ fi
+ done
+ else
+ #
+ # Search for Tk configuration file.
+ #
+
+ #
+ # 1. Search previously named locations.
+ #
+ for dir in \
+ $prefix \
+ $exec_prefix
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ elif test -r "$dir/unix/tkConfig.sh" ; then
+ tk_config_sh="$dir/unix/tkConfig.sh"
+ break
+ fi
+ done
+ #
+ # 2. Search standard locations.
+ #
+ if test "x$tk_config_sh" = "x" ; then
+ for dir in \
+ /usr/local \
+ /usr \
+ `ls -dr /usr/local/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/tk/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ /usr/local/tk \
+ `ls -dr /usr/local/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/lib/tcl/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/share/tcltk/tk[[7-9]].[[0-9]]* 2>/dev/null` \
+ /sw/lib \
+ /usr/lib \
+ /usr/lib64 \
+ ${x_libraries}
+ do
+ if test -r "$dir/tkConfig.sh" ; then
+ tk_config_sh="$dir/tkConfig.sh"
+ break
+ elif test -r "$dir/lib/tkConfig.sh" ; then
+ tk_config_sh="$dir/lib/tkConfig.sh"
+ break
+ fi
+ done
+ fi
+ fi
+ AC_MSG_RESULT([${tk_config_sh}])
+
+ if test "x$tk_config_sh" = "x" ; then
+ echo "can't find Tk configuration script \"tkConfig.sh\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+# -----------------------------------------------------------------------
+#
+# Source in the Tcl/Tk configuration scripts.
+#
+# BTW: Does anyone actually use the tclConfig.sh and tkConfig.sh
+# scripts? They seem to be always missing something. For example,
+# why don't they say where to find the Tcl and Tk header files?
+#
+# For example, give me the library directory paths separately
+# (I can't easily parse "-Ldir", but I can always paste a -L
+# on the front). If I want to specify equivalent of the -R flag,
+# I need the build a path of the library directories. Such as
+#
+# "-R $(BLTLIB):$(TKLIB):$(TCLLIB):($XLIB):$(JPEGLIB)"
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ . $tcl_config_sh
+ . $tk_config_sh
+ LIBS="${TCL_LIBS} ${LIBS}"
+
+ if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
+ :
+ elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
+ :
+ elif test "$TCL_VERSION" = "$TK_VERSION" ; then
+ :
+ else
+ echo "Mismatched Tcl/Tk versions ($TCL_VERSION != $TK_VERSION)"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tcl_includes}" != "x" ; then
+ if test -r "${xc_with_tcl_includes}/tcl.h" ; then
+ TCL_INC_DIR=${xc_with_tcl_includes}
+ elif test "x${TCL_INCLUDE_SPEC}" == "x" ; then
+ echo "Can't find tcl.h in \"${xc_with_tcl_includes}\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ elif test "x${TCL_INCLUDE_SPEC}" == "x" ; then
+ for dir in \
+ ${TCL_PREFIX}/include/tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION} \
+ ${TCL_PREFIX}/include \
+ ${TCL_SRC_DIR}/generic \
+ ${TCL_INC_DIR}
+ do
+ if test -r "$dir/tcl.h" ; then
+ TCL_INC_DIR=$dir
+ break
+ fi
+ done
+ if test "x${TCL_INC_DIR}" = "x" ; then
+ echo "Can't find tcl.h header file"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ else
+ TCL_INC_DIR=`echo ${TCL_INCLUDE_SPEC} | sed -e '/-I/s/-I//'`
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tk_includes}" != "x" ; then
+ if test -r "${xc_with_tk_includes}/tk.h" ; then
+ TK_INC_DIR=${xc_with_tk_includes}
+ else
+ echo "Can't find tk.h in \"${xc_with_tk_includes}\""
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ else
+ for dir in \
+ ${TK_PREFIX}/include/tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION} \
+ ${TK_PREFIX}/include \
+ ${TK_SRC_DIR}/generic \
+ ${TK_INC_DIR} \
+ ${TCL_INC_DIR}
+ do
+ if test -r "$dir/tk.h" ; then
+ TK_INC_DIR=$dir
+ break
+ fi
+ done
+ if test "x${TK_INC_DIR}" = "x" ; then
+ echo "Can't find tk.h header file"
+ echo "Reverting to non-Tcl compilation"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ case $target in
+ *-sunos4*|*-*-netbsd|NetBSD-*|FreeBSD-*|*-*-openbsd*|OpenBSD-*)
+ TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}"
+ TK_LIB_NAME="tk${TK_MAJOR_VERSION}${TK_MINOR_VERSION}"
+ ;;
+ *)
+ TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}"
+ TK_LIB_NAME="tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}"
+ ;;
+ esac
+
+ TCL_LIB_SPEC="-l${TCL_LIB_NAME}"
+ TK_LIB_SPEC="-l${TK_LIB_NAME}"
+
+# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX
+# We really ought to run "ldd" to confirm that the linked libraries match.
+
+ AC_MSG_CHECKING([for wish executable])
+ for dir in \
+ ${TK_EXEC_PREFIX}/bin \
+ ${TK_EXEC_PREFIX}
+ do
+ for wishexe in \
+ wish \
+ wish${TK_VERSION} \
+ wish.exe \
+ wish${TK_VERSION}.exe
+ do
+ if test -r "$dir/$wishexe" ; then
+ WISH_EXE=$dir/$wishexe
+ break
+ fi
+ done
+ if test "x${WISH_EXE}" != "x" ; then
+ break
+ fi
+ done
+ if test "x${WISH_EXE}" = "x" ; then
+ echo "Warning: Can't find executable for \"wish\". You may have to"
+ echo "manually set the value for WISH_EXE in the xcircuit startup script."
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT([${WISH_EXE}])
+ fi
+
+# Have to define SHDLIB_EXT here even though we have to do it below, too.
+ case $target in
+ *-hpux*)
+ SHDLIB_EXT=".sl"
+ ;;
+ *cygwin*)
+ SHDLIB_EXT=".dll"
+ ;;
+ *-darwin*)
+ SHDLIB_EXT=".dylib"
+ ;;
+ *-openbsd*)
+ SHDLIB_EXT=".so.${TCL_LIB_FILE##*.so.}"
+ ;;
+ *)
+ SHDLIB_EXT=".so"
+ ;;
+ esac
+
+ if test "x${xc_with_tcl_libraries}" != "x" ; then
+ for libname in \
+ "${xc_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT}"
+ do
+ if test -r "$libname" ; then
+ TCL_LIB_DIR="${xc_with_tcl_libraries}"
+ break
+ fi
+ done
+
+ if test "x${TCL_LIB_DIR}" = "x" ; then
+ echo "Can't find tcl library in \"${xc_with_tcl_libraries}\""
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ else
+ for libpfix in "lib64" "lib"
+ do
+ libname="${TCL_EXEC_PREFIX}/${libpfix}/lib${TCL_LIB_NAME}${SHDLIB_EXT}"
+ if test -r "$libname" ; then
+ TCL_LIB_DIR="${TCL_EXEC_PREFIX}/${libpfix}"
+ break
+ fi
+ done
+ if test "x${TCL_LIB_DIR}" = "x" ; then
+ echo "Can't find tcl library"
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "x${xc_with_tk_libraries}" != "x" ; then
+ for libname in \
+ "${xc_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT}"
+ do
+ if test -r "$libname" ; then
+ TK_LIB_DIR="${xc_with_tk_libraries}"
+ break
+ fi
+ done
+ if test "x${TK_LIB_DIR}" = "x" ; then
+ echo "Can't find tk library in \"${xc_with_tk_libraries}\""
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ else
+ for libpfix in "lib64" "lib"
+ do
+ libname="${TK_EXEC_PREFIX}/${libpfix}/lib${TK_LIB_NAME}${SHDLIB_EXT}"
+ if test -r "$libname" ; then
+ TK_LIB_DIR="${TK_EXEC_PREFIX}/${libpfix}"
+ break
+ fi
+ done
+ if test "x${TK_LIB_DIR}" = "x" ; then
+ echo "Can't find tk library"
+ echo "Reverting to non-Tcl compile"
+ xc_with_tcl=""
+ fi
+ fi
+fi
+
+dnl --------------------------------
+dnl End of Tcl/Tk search
+dnl --------------------------------
+
+# -----------------------------------------------------------------------
+#
+# Tk libraries and header files
+#
+# -----------------------------------------------------------------------
+
+if test "x$xc_with_tcl" != "x" ; then
+ if test "${TK_INC_DIR}" != "/usr/include" -a \
+ "${TK_INC_DIR}" != "${TCL_INC_DIR}"; then
+ INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
+ fi
+ if test "${TK_LIB_DIR}" = "/usr/lib" -o \
+ "${TK_LIB_DIR}" = "/usr/lib64" ; then
+ LIB_SPECS="${TK_LIB_SPEC}"
+ else
+ LIB_SPECS="-L${TK_LIB_DIR} ${TK_LIB_SPEC}"
+ if test "x${loader_run_path}" = "x" ; then
+ loader_run_path="${TK_LIB_DIR}"
+ else
+ loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
+ fi
+ fi
+
+# -----------------------------------------------------------------------
+#
+# Tcl libraries and header files
+#
+# Add a header file directory specification only if the Tcl headers reside
+# in a different directory from Tk's.
+#
+#
+# -----------------------------------------------------------------------
+ if test "x${TCL_INCLUDE_SPEC}" != "x" ; then
+ INC_SPECS="${INC_SPECS} ${TCL_INCLUDE_SPEC}"
+ elif test "${TCL_INC_DIR}" != "/usr/include" ; then
+ INC_SPECS="${INC_SPECS} -I${TCL_INC_DIR}"
+ fi
+
+ if test "${TCL_LIB_DIR}" = "/usr/lib" -o \
+ "${TCL_LIB_DIR}" = "/usr/lib64" -o \
+ "${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then
+ LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}"
+ else
+ LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}"
+ if test "x${loader_run_path}" = "x" ; then
+ loader_run_path="${TCL_LIB_DIR}"
+ else
+ loader_run_path="${TCL_LIB_DIR}:${loader_run_path}"
+ fi
+ fi
+
+#--------------------------------------------------------------------
+#
+# Check if we can generate shared libraries on this system. Set flags
+# to generate shared libraries for systems that we know about. Start
+# with the values found in tclConfig.sh, make changes as we know about
+# the different systems.
+#
+#--------------------------------------------------------------------
+
+# Initialize shared library build variables
+
+ LDDL_FLAGS="-shared"
+ SHDLIB_EXT=".so"
+ LD_RUN_PATH=""
+ EXTRA_LIB_SPECS=""
+
+ build_shared="yes"
+
+ case $target in
+ *-aix4.[[2-9]]*)
+ # No Position-Independent flags needed
+
+ # Use the installed export file or the one found in the source directory.
+
+ if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then
+ tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp"
+ else
+ tcl_exp="${TCL_SRC_DIR}/unix/lib.exp"
+ fi
+ if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then
+ tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp"
+ else
+ tk_exp="${TK_SRC_DIR}/unix/lib.exp"
+ fi
+
+ full_src_path=`cd ${srcdir}; pwd`
+
+ # Use shell-script to link shared library
+ SHLIB_LD="${full_src_path}/cf/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}"
+
+ SHLIB_LIB_SPEC="${aix_lib_specs} -lc"
+
+ LDFLAGS="-L${loader_run_path}"
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-aix*)
+ # No Position-Independent flags needed
+
+ # Use the installed export file or the one found in the source directory.
+
+ if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then
+ tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp"
+ else
+ tcl_exp="${TCL_SRC_DIR}/unix/lib.exp"
+ fi
+ if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then
+ tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp"
+ else
+ tk_exp="${TK_SRC_DIR}/unix/lib.exp"
+ fi
+
+ full_src_path=`cd ${srcdir}/cf; pwd`
+
+ # Use shell-script to link shared library
+
+ SHLIB_LD="${full_src_path}/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}"
+
+ SHLIB_LIB_SPECS="${aix_lib_specs} -lc"
+
+ LDFLAGS="-L${loader_run_path}"
+ EXTRA_LIB_SPECS="-lld"
+ ;;
+
+ *-bsdi2*|*-bsdi3*)
+ SHLIB_LD="shlicc"
+ LDDL_FLAGS="-r"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-darwin*)
+ SHDLIB_EXT=".dylib"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS="-dynamiclib -bind_at_load"
+ else
+ LDDL_FLAGS="-single_module -dynamiclib -flat_namespace"
+ LDDL_FLAGS="${LDDL_FLAGS} -undefined suppress -noprebind"
+ SHLIB_CFLAGS="-I/sw/include -fno-common"
+ fi
+ ;;
+
+ *cygwin*)
+ AC_DEFINE(CYGWIN)
+ SHDLIB_EXT=".dll"
+ LDDL_FLAGS="-shared -Wl,--enable-auto-image-base -Wl,-rpath,${loader_run_path}"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ ;;
+
+ *-bsdi4*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@'
+ ;;
+
+ *-dgux*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-hpux*)
+ if test "$GCC" = "no" ; then
+ DEFINES="$DEFINES -D_HPUX_SOURCE"
+ fi
+ AC_CHECK_LIB(dld, shl_load, [found=yes], [found=no])
+ if test "${found}" = "yes" ; then
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-b -E -n +s +b,${loader_run_path}:."
+ SHDLIB_EXT=".sl"
+
+ # The run path is included in both LDFLAGS and LDDL_FLAGS
+ # because SHLIB_LD is ld and LD is cc/gcc.
+
+ LDFLAGS="-Wl,-E -Wl,+s,+b,${loader_run_path}:."
+ EXTRA_LIB_SPECS="-ldld"
+ fi
+ ;;
+
+ *-irix64-6.5*)
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-32 -shared -rdata_shared"
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ ;;
+
+ *-irix-[56].*|*-irix64-*)
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-shared -rdata_shared"
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ LDFLAGS=""
+ if test "$GCC" = "yes" ; then
+ SHLIB_CFLAGS="-mabi=n32 $SHLIB_CFLAGS"
+ LDDL_FLAGS="-mabi=n32 $LDDL_FLAGS"
+ LDFLAGS="-mabi=n32 $LDFLAGS"
+ else
+ CFLAGS="-n32 $CFLAGS"
+ LDFLAGS="-n32 $LDFLAGS"
+ fi
+ ;;
+
+ *-linux*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS='-shared -Wl,-soname,$@'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+
+ EXTRA_LIB_SPECS="-ldl"
+
+ case $target in
+ x86_64-*)
+ # AMD 64-bit archictecture
+ # Add -fPIC to standard compile switch
+ CFLAGS="${CFLAGS} -fPIC"
+ ;;
+ esac
+ ;;
+
+ *-mp-ras-02*)
+ SHLIB_CFLAGS="-G -K PIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS=""
+ ;;
+
+ *-mp-ras-*)
+ SHLIB_CFLAGS="-G -K PIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS="-Wl,-Bexport"
+ ;;
+
+ *-ncr-sysv4-*2*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-ncr-sysv4*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G -Wl,-Bexport"
+
+ LDFLAGS="-Wl,-Bexport"
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-netbsd*|*-freebsd*|*-openbsd*)
+ # Not available on all versions: check for include file.
+ AC_CHECK_HEADER(dlfcn.h, test_ok=yes, test_ok=no)
+ if test "$test_ok" = yes; then
+ SHLIB_CFLAGS="-fpic"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-shared"
+ fi
+ ;;
+
+ *-nextstep*)
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-nostdlib -r"
+ ;;
+
+ *-osf1-1.[012]*)
+ # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1
+
+ # Warning: Ugly Makefile Hack
+ # Make package name same as library name
+
+ SHLIB_LD='ld -R -export $@:'
+ ;;
+
+ *-osf1-1.*)
+ # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
+
+ SHLIB_CFLAGS="-fpic"
+ SHLIB_LD="ld -shared"
+ ;;
+
+ *-osf1V*)
+ # Digital OSF/1
+
+ SHLIB_LD='ld'
+ LDDL_FLAGS='-shared -expect_unresolved "*"'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ LDFLAGS=""
+ ;;
+
+ *-sco*)
+ # Note, dlopen is available only on SCO 3.2.5 and greater. However,
+ # this test works, since "uname -s" was non-standard in 3.2.4 and
+ # below.
+
+ SHLIB_CFLAGS="-Kpic -belf"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-G"
+ LDFLAGS="-belf -Wl,-Bexport"
+ ;;
+
+ *-sni-sysv*)
+
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-sunos4*)
+
+ SHLIB_CFLAGS="-PIC"
+ SHLIB_LD="ld"
+ LDDL_FLAGS="-assert pure-text"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-solaris2*)
+
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS='-rdynamic -shared -Wl,-E -Wl,-soname,$@'
+ LD_RUN_PATH="-Wl,-rpath,${loader_run_path}"
+ else
+ LDDL_FLAGS="-shared -mimpure-text"
+ LD_RUN_PATH="-R ${loader_run_path}"
+ fi
+ EXTRA_LIB_SPECS="-ldl"
+ SHLIB_LIB_SPECS="${LIB_SPECS}"
+ ;;
+
+ *-mips-dde-sysv*)
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_LD="cc"
+ LDDL_FLAGS="-G"
+
+ EXTRA_LIB_SPECS="-ldl"
+ ;;
+
+ *-pc-sysv4* | *-unixware-5*)
+ SHLIB_CFLAGS="-G -KPIC"
+ SHLIB_LD="${CC}"
+ LDDL_FLAGS=" -Wl,-Bexport"
+ ;;
+
+ esac
+
+# If we're running gcc, then set SHLIB_CFLAGS flags for compiling
+# shared libraries for gcc, instead of those of the vendor's
+# compiler.
+
+ if test "$GCC" = "yes" ; then
+# SHLIB_CFLAGS="${SHLIB_CFLAGS} -fPIC"
+ CFLAGS="-fPIC ${CFLAGS}"
+ fi
+ if test "${xc_with_gnu_ld}" = "yes" ; then
+ LDDL_FLAGS="${LDDL_FLAGS} -Wl,--version-script=symbol.map"
+ fi
+
+ AC_SUBST(SHDLIB_EXT)
+ AC_SUBST(SHLIB_LD)
+ AC_SUBST(LDDL_FLAGS)
+ AC_SUBST(SHLIB_LIB_SPECS)
+ AC_SUBST(EXTRA_LIB_SPECS)
+ AC_SUBST(LD_RUN_PATH)
+ AC_SUBST(LDFLAGS)
+ AC_SUBST(INC_SPECS)
+ AC_SUBST(LIB_SPECS)
+ AC_SUBST(TCL_LIB_DIR)
+ AC_SUBST(WISH_EXE)
+
+fi
+
+dnl Disable the ASG (automatic schematic generation) package. Disabled by default.
+AC_ARG_ENABLE(asg,
+[ --enable-asg enable support for Automatic Schematic Generation], [
+ AC_DEFINE(ASG)
+ AC_DEFINE(CONFIGURED)
+ SUBDIRS="asg spiceparser"
+ dnl Object files to link into the final executable or shared object
+ dnl These must be in the correct order!
+ SUBLIB="asg/libasg.a spiceparser/libspiceparser.a"
+],)
+
+dnl Disable LGF (analog/diglog) file support. Enabled by default.
+AC_ARG_ENABLE(lgf,
+[ --disable-lgf disable support for reading Caltech tools
+ analog simulator .lgf files], , [
+ HAVE_LGF=LGF
+ AC_DEFINE(LGF)
+])
+
+dnl Disable fix for input focus on some window managers. Enabled by default.
+AC_ARG_ENABLE(focus-fix,
+[ --disable-focus-fix disable focus fix for some window managers], , [
+ AC_DEFINE(INPUT_FOCUS)
+])
+
+dnl Path to Ghostscript
+AC_ARG_WITH(gs,
+[ --with-gs=DIR path to ghostscript], [
+ if test -f "$withval"; then
+ GS_EXEC=$withval
+ else
+ GS_EXEC=gs
+ fi
+], [
+ AC_CHECK_PROG(GS_EXEC, gs, , gs)])
+AC_DEFINE_UNQUOTED(GS_EXEC, "$GS_EXEC")
+
+dnl Path to ngspice
+AC_ARG_WITH(ngspice,
+[ --with-ngspice=DIR path to ngspice], [
+ if test -f "$withval"; then
+ SPICE_EXEC=$withval
+ else
+ SPICE_EXEC=ngspice
+ fi
+], [
+ AC_CHECK_PROG(SPICE_EXEC, ngspice, , ngspice)])
+AC_DEFINE_UNQUOTED(SPICE_EXEC, "$SPICE_EXEC")
+
+dnl Path to Python
+
+xc_with_python=""
+PYTHON=
+
+AC_ARG_WITH(python,
+[ --with-python=DIR path to python interpreter],
+ xc_with_python=$withval)
+
+if test "x$xc_with_tcl" != "x" ; then
+ xc_with_python=""
+elif test "$xc_with_python" = "no" ; then
+ xc_with_python=""
+elif test "$xc_with_python" = "yes" ; then
+ AC_PATH_PROG(PYTHON,python)
+elif test "x$xc_with_python" != x; then
+ test -f "$xc_with_python" && PYTHON=$xc_with_python
+fi
+
+if test "x$PYTHON" != x; then
+ _py_version=`$PYTHON -c 'import sys; print sys.version[[0:3]]'`
+ _py_prefix=`$PYTHON -c 'import sys; print sys.prefix'`
+ _py_exec_prefix=`$PYTHON -c 'import sys; print sys.exec_prefix'`
+
+ _py_include="$_py_prefix/include/python$_py_version"
+ _py_lib="$_py_exec_prefix/lib/python$_py_version/config"
+ _py_makefile="$_py_lib/Makefile"
+
+ if test $_py_version = 1.5; then
+ echo
+ echo "*** WARNING:"
+ echo "*** Python version 1.5 detected: This version of Python has a known fatal"
+ echo "*** bug. Disabling Python interface. If you want the embedded Python"
+ echo "*** interface, you will need to get an updated version of Python."
+ echo
+ PYTHON=""
+ fi
+fi
+
+if test "x$PYTHON" != x; then
+ if test -f $_py_makefile; then
+ _py_libs=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $_py_makefile`
+ _py_libm=`sed -n -e 's/^LIBM=\(.*\)/\1/p' $_py_makefile`
+ else
+ _py_libs='-lpthread -ldl -lutil -ldb'
+ _py_libm='-lm'
+ fi
+
+ # Now that we think we know where the python include and
+ # library files are, make sure we can build a small
+ # program against them.
+ _save_CPPFLAGS=${CPPFLAGS}
+ _save_LDFLAGS=${LDFLAGS}
+ _save_LIBS=${LIBS}
+
+ CPPFLAGS="$CPPFLAGS -I$_py_include"
+ LDFLAGS="$LDFLAGS -L$_py_lib"
+
+ case "$target_os" in
+ *cygwin*)
+ PYLIB="-lpython$_py_version"
+ LIBS="$PYLIB.dll $LIBS $X_PRE_LIBS $_py_libs"
+ ;;
+ *)
+ LIBS="$LIBS -lpython$_py_version $_py_libs $_py_libm"
+ ;;
+ esac
+
+
+ HAVE_PYTHON=0
+ AC_CHECK_HEADER(Python.h,[
+ AC_MSG_CHECKING([for Py_Initialize in -lpython$_py_version])
+ AC_TRY_LINK([#include "Python.h"],[Py_Initialize();],[
+ HAVE_PYTHON=1
+ INTERPRETER=PYTHON
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PYTHON)],
+ AC_MSG_RESULT(no))])
+
+ if test "x$HAVE_PYTHON" = x0; then
+ CPPFLAGS=$_save_CPPFLAGS
+ LDFLAGS=$_save_LDFLAGS
+ LIBS=$_save_LIBS
+ PYTHON=""
+ fi
+fi
+
+if test "x$PYTHON" != x; then
+ STARTUP_FILE="xcstartup.py"
+ INTERP_PATH="python"
+ WRAPPER_SCRIPT=""
+ SUBDIRS="${SUBDIRS} Xw"
+ SUBLIB="${SUBLIB} Xw/libxcXw.a"
+ XCIRCUIT_TARGET="xcircuit"
+elif test "x$xc_with_tcl" != "x" ; then
+ INTERPRETER=TCL
+ STARTUP_FILE="xcstartup.tcl"
+ INTERP_PATH="tcl"
+ WRAPPER_SCRIPT="wrapper.tcl"
+ AC_DEFINE(TCL_WRAPPER)
+ XCIRCUIT_TARGET="tcl"
+ ALL_TARGET="all-recursive"
+ INSTALL_TARGET="install-recursive"
+else
+ STARTUP_FILE="startup.script"
+ INTERP_PATH="."
+ WRAPPER_SCRIPT=""
+ SUBDIRS="${SUBDIRS} Xw"
+ SUBLIB="${SUBLIB} Xw/libxcXw.a"
+ XCIRCUIT_TARGET="xcircuit"
+fi
+
+# Add -lm last to LDFLAGS, or Tcl/Tk's addition of -lieee can cause
+# an error.
+EXTRA_LIB_SPECS="$EXTRA_LIB_SPECS -lm"
+
+dnl Memory debugging:
+dnl The non-Tcl version uses (links to) ElectricFence.
+dnl Tcl must use the Tcl memory debugger.
+dnl Caveats:
+dnl We should try to ensure that ElectricFence is available, or that
+dnl the Tcl version used has memory debugging compiled in
+
+AC_ARG_ENABLE(memdebug,
+[ --enable-memdebug enable memory debugging], [
+ if test "x$xc_with_tcl" = "x" ; then
+ LIBS="${LIBS} -lefence"
+ else
+ AC_DEFINE(TCL_MEM_DEBUG)
+ fi
+],)
+
+AC_SUBST(SUBDIRS)
+AC_SUBST(SUBLIB)
+AC_SUBST(STDLIBS)
+AC_SUBST(STARTUP_FILE)
+AC_SUBST(INTERP_PATH)
+AC_SUBST(WRAPPER_SCRIPT)
+AC_SUBST(XCIRCUIT_TARGET)
+AC_SUBST(SHLIB_CFLAGS)
+AC_SUBST(CFLAGS)
+AC_SUBST(LD)
+AC_SUBST(LDFLAGS)
+
+AC_SUBST(INTERPRETER)
+AC_SUBST(HAVE_LGF)
+
+AC_SUBST(ALL_TARGET)
+AC_SUBST(INSTALL_TARGET)
+
+dnl Automake requires these
+AC_SUBST(ACLOCAL)
+AC_SUBST(AUTOCONF)
+AC_SUBST(AUTOMAKE)
+AC_SUBST(AUTOHEADER)
+
+AC_OUTPUT(Makefile Xw/Makefile asg/Makefile spiceparser/Makefile)
diff --git a/cursors.h b/cursors.h
new file mode 100644
index 0000000..195bbac
--- /dev/null
+++ b/cursors.h
@@ -0,0 +1,141 @@
+/*------------------------------------------------------------------*/
+/* cursors.h --- definitions for bitmapped cursors used by xcircuit */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*------------------------------------------------------------------*/
+
+#define arrow_width 16
+#define arrow_height 18
+#define arrow_x_hot 0
+#define arrow_y_hot 1
+static u_char arrow_bits[] = {
+ 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x1e, 0x00, 0xfe, 0x00, 0xfc, 0x07,
+ 0xfc, 0x01, 0x78, 0x00, 0xf8, 0x00, 0xb8, 0x01, 0x10, 0x03, 0x10, 0x06,
+ 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00};
+static u_char arrowmask_bits[] = {
+ 0x00, 0x00, 0x07, 0x00, 0x1f, 0x00, 0xff, 0x00, 0xfe, 0x07, 0xfe, 0x0f,
+ 0xfc, 0x07, 0xfc, 0x01, 0xfc, 0x01, 0xf8, 0x03, 0xb8, 0x07, 0x38, 0x0f,
+ 0x10, 0x1e, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0, 0x00, 0x70, 0x00, 0x20};
+#define scissors_width 20
+#define scissors_height 14
+#define scissors_x_hot 8
+#define scissors_y_hot 6
+static u_char scissors_bits[] = {
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1c, 0xc0, 0x03, 0xf0, 0x20, 0x04,
+ 0xc0, 0x23, 0x04, 0x00, 0xaf, 0x03, 0xff, 0x7b, 0x00, 0xfe, 0x3f, 0x00,
+ 0x00, 0xe0, 0x01, 0x00, 0x80, 0x02, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04,
+ 0x00, 0x80, 0x03, 0x00, 0x00, 0x00};
+static u_char scissorsmask_bits[] = {
+ 0x06, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfe, 0xe0, 0x07, 0xfc, 0x73, 0x0e,
+ 0xf0, 0x3f, 0x0c, 0xc0, 0xff, 0x07, 0xff, 0xfb, 0x03, 0xff, 0xff, 0x01,
+ 0xfe, 0xff, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x60, 0x0c, 0x00, 0xe0, 0x0e,
+ 0x00, 0xc0, 0x07, 0x00, 0x80, 0x03};
+#define cross_width 17
+#define cross_height 17
+#define cross_x_hot 8
+#define cross_y_hot 8
+static u_char cross_bits[] = {
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x00};
+static u_char crossmask_bits[] = {
+ 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00,
+ 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0xff, 0xff, 0x01,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0x01, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00,
+ 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00,
+ 0x80, 0x03, 0x00};
+#define copy_width 17
+#define copy_height 17
+#define copy_x_hot 8
+#define copy_y_hot 8
+static u_char copy_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x03, 0x80, 0x01, 0x07, 0xc0, 0x01,
+ 0x0d, 0x60, 0x01, 0x19, 0x30, 0x01, 0x31, 0x18, 0x01, 0x61, 0x0c, 0x01,
+ 0xc1, 0x06, 0x01, 0x61, 0x0c, 0x01, 0x31, 0x18, 0x01, 0x19, 0x30, 0x01,
+ 0x0d, 0x60, 0x01, 0x07, 0xc0, 0x01, 0x03, 0x80, 0x01, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00};
+static u_char copymask_bits[] = {
+ 0x01, 0x00, 0x01, 0x03, 0x80, 0x01, 0x07, 0xc0, 0x01, 0x0f, 0xe0, 0x01,
+ 0x1f, 0xf0, 0x01, 0x3d, 0x78, 0x01, 0x79, 0x3c, 0x01, 0xf1, 0x1e, 0x01,
+ 0xe1, 0x0e, 0x01, 0xf1, 0x1e, 0x01, 0x79, 0x3c, 0x01, 0x3d, 0x78, 0x01,
+ 0x1f, 0xf0, 0x01, 0x0f, 0xe0, 0x01, 0x07, 0xc0, 0x01, 0x03, 0x80, 0x01,
+ 0x01, 0x00, 0x01};
+#define question_width 17
+#define question_height 17
+#define question_x_hot 8
+#define question_y_hot 5
+static u_char question_bits[] = {
+ 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0x70, 0x1c, 0x00,
+ 0x30, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x0e, 0x00,
+ 0x00, 0x07, 0x00, 0x80, 0x03, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00};
+static u_char questionmask_bits[] = {
+ 0xc0, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0xf0, 0x1f, 0x00, 0x70, 0x3c, 0x00,
+ 0x70, 0x38, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00,
+ 0x80, 0x07, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00};
+#define circle_width 17
+#define circle_height 17
+#define circle_x_hot 8
+#define circle_y_hot 8
+static u_char circle_bits[] = {
+ 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x70, 0x1c, 0x00, 0x18, 0x30, 0x00,
+ 0x0c, 0x60, 0x00, 0x04, 0x40, 0x00, 0x06, 0xc0, 0x00, 0x82, 0x83, 0x00,
+ 0x82, 0x83, 0x00, 0x82, 0x83, 0x00, 0x06, 0xc0, 0x00, 0x04, 0x40, 0x00,
+ 0x0c, 0x60, 0x00, 0x18, 0x30, 0x00, 0x70, 0x1c, 0x00, 0xc0, 0x07, 0x00,
+ 0x00, 0x00, 0x00};
+static u_char circlemask_bits[] = {
+ 0xc0, 0x07, 0x00, 0xf0, 0x1f, 0x00, 0x7c, 0x7c, 0x00, 0x1c, 0x70, 0x00,
+ 0x0e, 0xe0, 0x00, 0x06, 0xc0, 0x00, 0x07, 0xc1, 0x01, 0x83, 0x83, 0x01,
+ 0xc3, 0x87, 0x01, 0x83, 0x83, 0x01, 0x07, 0xc1, 0x01, 0x06, 0xc0, 0x00,
+ 0x0e, 0xe0, 0x00, 0x1c, 0x70, 0x00, 0x7c, 0x7c, 0x00, 0xf0, 0x1f, 0x00,
+ 0xc0, 0x07, 0x00};
+#define exx_width 17
+#define exx_height 17
+#define exx_x_hot 8
+#define exx_y_hot 8
+static u_char exx_bits[] = {
+ 0x00, 0x00, 0x00, 0x06, 0xc0, 0x00, 0x0e, 0xe0, 0x00, 0x1c, 0x70, 0x00,
+ 0x18, 0x38, 0x00, 0x30, 0x08, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x00, 0x20, 0x18, 0x00,
+ 0x38, 0x30, 0x00, 0x1c, 0x70, 0x00, 0x0e, 0xe0, 0x00, 0x06, 0xc0, 0x00,
+ 0x00, 0x00, 0x00};
+static u_char exxmask_bits[] = {
+ 0x0f, 0xe0, 0x01, 0x1f, 0xf0, 0x01, 0x3f, 0xf8, 0x01, 0x3f, 0xfc, 0x01,
+ 0x7e, 0xfc, 0x00, 0xfc, 0x7e, 0x00, 0xf8, 0x1e, 0x00, 0xe0, 0x0e, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x0e, 0x00, 0xf0, 0x3e, 0x00, 0xfc, 0x7e, 0x00,
+ 0x7e, 0xfc, 0x00, 0x7f, 0xf8, 0x01, 0x3f, 0xf8, 0x01, 0x1f, 0xf0, 0x01,
+ 0x0f, 0xe0, 0x01};
+#define rot_width 17
+#define rot_height 17
+static u_char rot_bits[] = {
+ 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf0, 0x1f, 0x00, 0x78, 0x3d, 0x00,
+ 0x1c, 0x71, 0x00, 0x0c, 0x61, 0x00, 0x0e, 0xe1, 0x00, 0x06, 0xc1, 0x00,
+ 0x06, 0xc1, 0x00, 0x06, 0xc1, 0x00, 0x0e, 0xe1, 0x00, 0x0c, 0x61, 0x00,
+ 0x1c, 0x71, 0x00, 0x78, 0x3d, 0x00, 0xf0, 0x1f, 0x00, 0xc0, 0x07, 0x00,
+ 0x00, 0x00, 0x00};
+static u_char rotmask_bits[] = {
+ 0xc0, 0x07, 0x00, 0xf0, 0x1f, 0x00, 0xf8, 0x3f, 0x00, 0xfc, 0x7f, 0x00,
+ 0xfe, 0xff, 0x00, 0x9e, 0xf3, 0x00, 0x9f, 0xf3, 0x01, 0x8f, 0xe3, 0x01,
+ 0x8f, 0xe3, 0x01, 0x8f, 0xe3, 0x01, 0x9f, 0xf3, 0x01, 0x9e, 0xf3, 0x00,
+ 0xfe, 0xff, 0x00, 0xfc, 0x7f, 0x00, 0xf8, 0x3f, 0x00, 0xf0, 0x1f, 0x00,
+ 0xc0, 0x07, 0x00};
+#define hand_width 20
+#define hand_height 20
+#define hand_x_hot 7
+#define hand_y_hot 12
+static unsigned char hand_bits[] = {
+ 0x80, 0x0d, 0x00, 0xb0, 0x0d, 0x00, 0xb0, 0x0d, 0x00, 0xb0, 0x0d, 0x00,
+ 0xb6, 0x0d, 0x00, 0xb6, 0x0d, 0x00, 0xb6, 0x0d, 0x00, 0xf6, 0x0f, 0x03,
+ 0xfe, 0x8f, 0x03, 0xfe, 0xcf, 0x03, 0xfc, 0xef, 0x01, 0xfc, 0xef, 0x00,
+ 0xfc, 0xff, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x3f, 0x00, 0xf8, 0x1f, 0x00,
+ 0xf8, 0x1f, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x0f, 0x00, 0xe0, 0x0f, 0x00};
+static unsigned char handmask_bits[] = {
+ 0x80, 0x0d, 0x00, 0xb0, 0x0d, 0x00, 0xb0, 0x0d, 0x00, 0xb0, 0x0d, 0x00,
+ 0xb6, 0x0d, 0x00, 0xb6, 0x0d, 0x00, 0xb6, 0x0d, 0x00, 0xf6, 0x0f, 0x03,
+ 0xfe, 0x8f, 0x03, 0xfe, 0xcf, 0x03, 0xfc, 0xef, 0x01, 0xfc, 0xef, 0x00,
+ 0xfc, 0xff, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x3f, 0x00, 0xf8, 0x1f, 0x00,
+ 0xf8, 0x1f, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x0f, 0x00, 0xe0, 0x0f, 0x00};
diff --git a/elements.c b/elements.c
new file mode 100644
index 0000000..7187691
--- /dev/null
+++ b/elements.c
@@ -0,0 +1,2315 @@
+/*----------------------------------------------------------------------*/
+/* elements.c --- xcircuit routines for creating basic elements */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/13/93 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern Display *dpy; /* Works well to make this globally accessible */
+extern int *appcolors;
+extern Cursor appcursors[NUM_CURSORS];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern xcWidget top;
+extern fontinfo *fonts;
+extern short fontcount;
+extern char _STR[150], _STR2[250];
+extern int number_colors;
+
+extern double atan2();
+
+/*------------------------------------------------------------------------*/
+/* Declarations of global variables */
+/*------------------------------------------------------------------------*/
+
+char extchar[20];
+double saveratio;
+u_char texttype;
+
+/*--------------------------------------*/
+/* Element constructor functions */
+/*--------------------------------------*/
+
+/*--------------------------------------------------------------*/
+/* Label constructor: Create a new label element in the object */
+/* whose instance is "destinst" and return a pointer to it. */
+/* */
+/* "destinst" is the destination instance. If NULL, the */
+/* top-level instance (areawin->topinstance) is used. */
+/* "strptr" is a pointer to a stringpart string, and may */
+/* be NULL. If non-NULL, should NOT be free'd by the */
+/* calling routine. */
+/* "pintype" is NORMAL, LOCAL, GLOBAL, or INFO */
+/* "x" and "y" are the label coordinates. */
+/* */
+/* Other properties must be set individually by the calling */
+/* routine. */
+/* */
+/* Return value is a pointer to the newly created label. */
+/*--------------------------------------------------------------*/
+
+labelptr new_label(objinstptr destinst, stringpart *strptr, int pintype,
+ int x, int y)
+{
+ labelptr *newlab;
+ objectptr destobject;
+ objinstptr locdestinst;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ NEW_LABEL(newlab, destobject);
+ labeldefaults(*newlab, pintype, x, y);
+
+ if (strptr->type == FONT_NAME) {
+ free ((*newlab)->string);
+ (*newlab)->string = strptr;
+ }
+ else
+ (*newlab)->string->nextpart = strptr;
+
+ calcbboxvalues(locdestinst, (genericptr *)newlab);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+ return *newlab;
+}
+
+/*--------------------------------------------------------------*/
+/* Variant of the above; creates a label from a (char *) string */
+/* instead of a stringpart pointer. Like the stringpart */
+/* pointer above, "cstr" should NOT be free'd by the calling */
+/* routine. */
+/*--------------------------------------------------------------*/
+
+labelptr new_simple_label(objinstptr destinst, char *cstr,
+ int pintype, int x, int y)
+{
+ stringpart *strptr;
+
+ strptr = (stringpart *)malloc(sizeof(stringpart));
+ strptr->type = TEXT_STRING;
+ strptr->nextpart = NULL;
+ strptr->data.string = cstr;
+
+ return new_label(destinst, strptr, pintype, x, y);
+}
+
+/*--------------------------------------------------------------*/
+/* Another variant of the above; creates a "temporary" label */
+/* from a (char *) string. As above, "cstr" should NOT be */
+/* free'd by the calling routine. The "temporary" label has no */
+/* font information, and cannot be displayed nor saved/loaded */
+/* from the PostScript output file. Used to name networks or */
+/* to mark port positions. Pin type is always LOCAL. Does not */
+/* require updating bounding box info since it cannot be */
+/* displayed. Consequently, only requires passing the object */
+/* to get the new label, not its instance. */
+/*--------------------------------------------------------------*/
+
+labelptr new_temporary_label(objectptr destobject, char *cstr,
+ int x, int y)
+{
+ labelptr *newlab;
+
+ NEW_LABEL(newlab, destobject);
+ labeldefaults(*newlab, LOCAL, x, y);
+
+ (*newlab)->string->type = TEXT_STRING; /* overwrites FONT record */
+ (*newlab)->string->data.string = cstr;
+ return *newlab;
+}
+
+/*--------------------------------------------------------------*/
+/* Polygon constructor: Create a new polygon element in the */
+/* object whose instance is "destinst" and return a pointer to */
+/* it. */
+/* */
+/* "destinst" is the destination instance. If NULL, the */
+/* top-level instance (areawin->topinstance) is used. */
+/* "points" is a list of XPoint pointers, should not be */
+/* NULL. It is transferred to the polygon verbatim, */
+/* and should NOT be free'd by the calling routine. */
+/* "number" is the number of points in the list, or zero */
+/* if "points" is NULL. */
+/* */
+/* Other properties must be set individually by the calling */
+/* routine. */
+/* */
+/* Return value is a pointer to the newly created polygon. */
+/*--------------------------------------------------------------*/
+
+polyptr new_polygon(objinstptr destinst, pointlist *points, int number)
+{
+ polyptr *newpoly;
+ objectptr destobject;
+ objinstptr locdestinst;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ NEW_POLY(newpoly, destobject);
+ polydefaults(*newpoly, 0, 0, 0);
+ (*newpoly)->number = number;
+ (*newpoly)->points = *points;
+
+ calcbboxvalues(locdestinst, (genericptr *)newpoly);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+ return *newpoly;
+}
+
+/*--------------------------------------------------------------*/
+/* Spline constructor: Create a new spline element in the */
+/* object whose instance is "destinst" and return a pointer to */
+/* it. */
+/* */
+/* "destinst" is the destination instance. If NULL, the */
+/* top-level instance (areawin->topinstance) is used. */
+/* "points" is a array of 4 XPoints; should not be NULL. */
+/* */
+/* Other properties must be set individually by the calling */
+/* routine. */
+/* */
+/* Return value is a pointer to the newly created spline. */
+/*--------------------------------------------------------------*/
+
+splineptr new_spline(objinstptr destinst, pointlist points)
+{
+ splineptr *newspline;
+ objectptr destobject;
+ objinstptr locdestinst;
+ int i;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ NEW_SPLINE(newspline, destobject);
+ splinedefaults(*newspline, 0, 0);
+
+ for (i = 0; i < 4; i++)
+ (*newspline)->ctrl[i] = points[i];
+
+ calcspline(*newspline);
+ calcbboxvalues(locdestinst, (genericptr *)newspline);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+ return *newspline;
+}
+
+/*--------------------------------------------------------------*/
+/* Arc constructor: Create a new arc element in the object */
+/* whose instance is "destinst" and return a pointer to it. */
+/* */
+/* "destinst" is the destination instance. If NULL, the */
+/* top-level instance (areawin->topinstance) is used. */
+/* "radius" is the radius of the (circular) arc. */
+/* "x" and "y" represents the arc center position. */
+/* */
+/* Other properties must be set individually by the calling */
+/* routine. */
+/* */
+/* Return value is a pointer to the newly created arc. */
+/*--------------------------------------------------------------*/
+
+arcptr new_arc(objinstptr destinst, int radius, int x, int y)
+{
+ arcptr *newarc;
+ objectptr destobject;
+ objinstptr locdestinst;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ NEW_ARC(newarc, destobject);
+ arcdefaults(*newarc, x, y);
+ (*newarc)->radius = (*newarc)->yaxis = radius;
+
+ calcarc(*newarc);
+ calcbboxvalues(locdestinst, (genericptr *)newarc);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+ return *newarc;
+}
+
+/*--------------------------------------------------------------*/
+/* Instance constructor: Create a new object instance element */
+/* in the object whose instance is "destinst" and return a */
+/* pointer to it. */
+/* */
+/* "destinst" is the destination instance. If NULL, the */
+/* top-level instance (areawin->topinstance) is used. */
+/* "srcinst" is the source instance of which this is a */
+/* copy. */
+/* "x" and "y" represents the instance position. */
+/* */
+/* Other properties must be set individually by the calling */
+/* routine. */
+/* */
+/* Return value is a pointer to the newly created arc. */
+/*--------------------------------------------------------------*/
+
+objinstptr new_objinst(objinstptr destinst, objinstptr srcinst, int x, int y)
+{
+ objinstptr *newobjinst;
+ objectptr destobject;
+ objinstptr locdestinst;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ NEW_OBJINST(newobjinst, destobject);
+ instcopy(*newobjinst, srcinst);
+ (*newobjinst)->position.x = x;
+ (*newobjinst)->position.y = y;
+
+ calcbboxvalues(locdestinst, (genericptr *)newobjinst);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+ return *newobjinst;
+}
+
+/*--------------------------------------------------------------*/
+/* Generic element destructor function */
+/* (Note---this function is not being used anywhere. . .) */
+/*--------------------------------------------------------------*/
+
+void remove_element(objinstptr destinst, genericptr genelem)
+{
+ objectptr destobject;
+ objinstptr locdestinst;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ genelem->type &= REMOVE_TAG;
+ delete_tagged(locdestinst);
+ calcbboxvalues(locdestinst, (genericptr *)NULL);
+ updatepagebounds(destobject);
+}
+
+/*-------------------------------------*/
+/* Sane values for a new path instance */
+/*-------------------------------------*/
+
+void pathdefaults(pathptr newpath, int x, int y)
+{
+ newpath->style = NORMAL;
+ newpath->width = areawin->linewidth;
+ newpath->style = areawin->style;
+ newpath->color = areawin->color;
+ newpath->parts = 0;
+ newpath->plist = (genericptr *)NULL;
+ newpath->passed = NULL;
+}
+
+/*---------------------------------------*/
+/* Sane values for a new object instance */
+/*---------------------------------------*/
+
+void instancedefaults(objinstptr newinst, objectptr thisobj, int x, int y)
+{
+ newinst->position.x = x;
+ newinst->position.y = y;
+ newinst->rotation = 0;
+ newinst->scale = 1.0;
+ newinst->style = LINE_INVARIANT;
+ newinst->thisobject = thisobj;
+ newinst->color = areawin->color;
+ newinst->params = NULL;
+ newinst->passed = NULL;
+
+ newinst->bbox.lowerleft.x = thisobj->bbox.lowerleft.x;
+ newinst->bbox.lowerleft.y = thisobj->bbox.lowerleft.y;
+ newinst->bbox.width = thisobj->bbox.width;
+ newinst->bbox.height = thisobj->bbox.height;
+
+ newinst->schembbox = NULL;
+}
+
+/*--------------------------------------*/
+/* Draw a dot at the current point. */
+/*--------------------------------------*/
+
+void drawdot(int xpos, int ypos)
+{
+ arcptr *newarc;
+ objinstptr *newdot;
+ objectptr dotobj;
+
+ /* Find the object "dot" in the builtin library, or else use an arc */
+
+ if ((dotobj = finddot()) != (objectptr)NULL) {
+ NEW_OBJINST(newdot, topobject);
+ instancedefaults(*newdot, dotobj, xpos, ypos);
+ register_for_undo(XCF_Dot, UNDO_DONE, areawin->topinstance, *newdot);
+ }
+ else {
+ NEW_ARC(newarc, topobject);
+ arcdefaults(*newarc, xpos, ypos);
+ (*newarc)->radius = 6;
+ (*newarc)->yaxis = 6;
+ (*newarc)->width = 1.0;
+ (*newarc)->style = FILLED | FILLSOLID | NOBORDER;
+ (*newarc)->passed = NULL;
+ (*newarc)->cycle = NULL;
+ calcarc(*newarc);
+ register_for_undo(XCF_Arc, UNDO_DONE, areawin->topinstance, *newarc);
+ }
+ incr_changes(topobject);
+}
+
+/*--------------------------------------*/
+/* Sane default values for a label */
+/*--------------------------------------*/
+
+void labeldefaults(labelptr newlabel, u_char dopin, int x, int y)
+{
+ newlabel->rotation = 0;
+ newlabel->color = areawin->color;
+ newlabel->scale = areawin->textscale;
+ newlabel->string = (stringpart *)malloc(sizeof(stringpart));
+ newlabel->passed = NULL;
+ newlabel->cycle = NULL;
+
+ /* initialize string with font designator */
+ newlabel->string->type = FONT_NAME;
+ newlabel->string->data.font = areawin->psfont;
+ newlabel->string->nextpart = NULL;
+
+ newlabel->pin = dopin;
+ if (dopin == LOCAL) newlabel->color = LOCALPINCOLOR;
+ else if (dopin == GLOBAL) newlabel->color = GLOBALPINCOLOR;
+ else if (dopin == INFO) newlabel->color = INFOLABELCOLOR;
+
+ newlabel->justify = areawin->justify;
+ newlabel->position.x = x;
+ newlabel->position.y = y;
+}
+
+/*--------------------------------------*/
+/* Button handler when creating a label */
+/*--------------------------------------*/
+
+void textbutton(u_char dopin, int x, int y)
+{
+ labelptr *newlabel;
+ XPoint userpt;
+ short tmpheight, *newselect;
+
+ XDefineCursor(dpy, areawin->window, TEXTPTR);
+ W3printf("Click to end or cancel.");
+
+ if (fontcount == 0)
+ Wprintf("Warning: No fonts available!");
+
+ unselect_all();
+ NEW_LABEL(newlabel, topobject);
+ newselect = allocselect();
+ *newselect = topobject->parts - 1;
+ snap(x, y, &userpt);
+ labeldefaults(*newlabel, dopin, userpt.x, userpt.y);
+
+ tmpheight = (short)(TEXTHEIGHT * (*newlabel)->scale);
+ userpt.y -= ((*newlabel)->justify & NOTBOTTOM) ?
+ (((*newlabel)->justify & TOP) ? tmpheight : tmpheight / 2) : 0;
+ UDrawTLine(*newlabel);
+ areawin->origin.x = userpt.x;
+ areawin->origin.y = userpt.y;
+ areawin->textpos = 1; /* Text position is *after* the font declaration */
+}
+
+/*----------------------------------------------------------------------*/
+/* Report on characters surrounding the current text position */
+/*----------------------------------------------------------------------*/
+
+#define MAXCHARS 10
+
+void charreport(labelptr curlabel)
+{
+ int i, locpos, cleft = 149;
+ stringpart *strptr;
+
+ _STR2[0] = '\0';
+ for (i = areawin->textpos - MAXCHARS; i <= areawin->textpos + MAXCHARS - 1; i++) {
+ if (i < 0) continue;
+ strptr = findstringpart(i, &locpos, curlabel->string, areawin->topinstance);
+ if (i == areawin->textpos) {
+ strncat(_STR2, "| ", cleft);
+ cleft -= 2;
+ }
+ if (strptr == NULL) break;
+ if (strptr->type != RETURN || strptr->data.flags == 0) {
+ charprint(_STR, strptr, locpos);
+ cleft -= strlen(_STR);
+ strncat(_STR2, _STR, cleft);
+ strncat(_STR2, " ", --cleft);
+ if (cleft <= 0) break;
+ }
+ }
+ W3printf("%s", _STR2);
+}
+
+/*----------------------------------------------------------------------*/
+/* See if a (pin) label has a copy (at least one) in this drawing. */
+/*----------------------------------------------------------------------*/
+
+labelptr findlabelcopy(labelptr curlabel, stringpart *curstring)
+{
+ genericptr *tgen;
+ labelptr tlab;
+
+ for (tgen = topobject->plist; tgen < topobject->plist + topobject->parts; tgen++) {
+ if (IS_LABEL(*tgen)) {
+ tlab = TOLABEL(tgen);
+ if (tlab->pin != LOCAL) continue;
+ else if (tlab == curlabel) continue; /* Don't count self! */
+ else if (!stringcomp(tlab->string, curstring)) return tlab;
+ }
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Interpret string and add to current label. */
+/* keypressed is a KeySym */
+/* clientdata can pass information for label controls */
+/* */
+/* Return TRUE if labeltext handled the character, FALSE if the */
+/* character was not recognized. */
+/*--------------------------------------------------------------*/
+
+Boolean labeltext(int keypressed, char *clientdata)
+{
+ labelptr curlabel;
+ stringpart *curpos, *labelbuf;
+ int locpos;
+ Boolean r = True, do_redraw = False;
+ short tmplength, tmpheight, cfont;
+ TextExtents tmpext;
+ TechPtr oldtech, newtech;
+
+ curlabel = TOLABEL(EDITPART);
+
+ if (curlabel == NULL || curlabel->type != LABEL) {
+ Wprintf("Error: Bad label string");
+ eventmode = NORMAL_MODE;
+ return FALSE;
+ }
+
+ /* find text segment of the current position */
+ curpos = findstringpart(areawin->textpos, &locpos, curlabel->string,
+ areawin->topinstance);
+
+ UDrawTLine(curlabel);
+
+ if (clientdata != NULL && keypressed == TEXT_DELETE) {
+ if (areawin->textpos > 1) {
+ int curloc, strpos;
+ stringpart *strptr;
+
+ if (areawin->textend == 0) areawin->textend = areawin->textpos - 1;
+
+ undrawtext(curlabel);
+ for (strpos = areawin->textpos - 1; strpos >= areawin->textend; strpos--) {
+ strptr = findstringpart(strpos, &curloc, curlabel->string,
+ areawin->topinstance);
+ if (curloc >= 0) {
+ memmove(strptr->data.string + curloc,
+ strptr->data.string + curloc + 1,
+ strlen(strptr->data.string + curloc + 1) + 1);
+ if (strlen(strptr->data.string) == 0)
+ deletestring(strptr, &curlabel->string, areawin->topinstance);
+ }
+
+ /* Don't delete any parameter boundaries---must use */
+ /* "unparameterize" command for that. */
+
+ else if (strptr != NULL) {
+ if ((strptr->type != PARAM_START) && (strptr->type != PARAM_END))
+ deletestring(strptr, &curlabel->string, areawin->topinstance);
+ else
+ areawin->textpos++;
+ }
+ else
+ Fprintf(stdout, "Error: Unexpected NULL string part\n");
+ areawin->textpos--;
+ }
+ areawin->textend = 0;
+ do_redraw = True;
+ }
+ }
+ else if (clientdata != NULL && keypressed == TEXT_DEL_PARAM) {
+ if (areawin->textpos > 1) {
+ int curloc, strpos;
+ stringpart *strptr;
+
+ strptr = findstringpart(areawin->textpos - 1, &curloc, curlabel->string,
+ areawin->topinstance);
+ if ((curloc < 0) && (strptr != NULL) && (strptr->type == PARAM_END)) {
+ undrawtext(curlabel);
+ while (strptr->type != PARAM_START)
+ strptr = findstringpart(--strpos, &curloc, curlabel->string,
+ areawin->topinstance);
+ unmakeparam(curlabel, strptr);
+ do_redraw = True;
+ }
+ }
+ }
+ else if (clientdata != NULL && keypressed == TEXT_RETURN) {
+ Boolean hasstuff = False; /* Check for null string */
+ stringpart *tmppos;
+
+ for (tmppos = curlabel->string; tmppos != NULL; tmppos = tmppos->nextpart) {
+ if (tmppos->type == PARAM_START) hasstuff = True;
+ else if (tmppos->type == TEXT_STRING) hasstuff = True;
+ }
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+
+ W3printf("");
+
+ if (hasstuff && (eventmode != ETEXT_MODE && eventmode != CATTEXT_MODE)) {
+ register_for_undo(XCF_Text, UNDO_MORE, areawin->topinstance,
+ curlabel);
+
+ incr_changes(topobject);
+ invalidate_netlist(topobject);
+
+ }
+ else if (!hasstuff && (eventmode == ETEXT_MODE)) {
+ if (*(areawin->selectlist) < topobject->parts) {
+ /* Force the "delete" undo record to be a continuation of */
+ /* the undo series containing the edit. That way, "undo" */
+ /* does not generate a label with null text. */
+
+ xobjs.undostack->idx = -xobjs.undostack->idx;
+ standard_element_delete(NORMAL);
+ }
+ else {
+ /* Label had just been created; just delete it w/o undo */
+ freelabel(curlabel->string);
+ free(curlabel);
+ topobject->parts--;
+ unselect_all();
+ }
+ }
+
+ if ((!hasstuff) && (eventmode == CATTEXT_MODE)) { /* can't have null labels! */
+ undo_action();
+ XcSetFunction(GXcopy);
+ redrawtext(curlabel);
+ Wprintf("Object must have a name!");
+ eventmode = CATALOG_MODE;
+ }
+ else if (!hasstuff) {
+ eventmode = NORMAL_MODE;
+ }
+ else if (eventmode == CATTEXT_MODE) {
+ objectptr libobj;
+ stringpart *oldname;
+ int page, libnum;
+
+ /* Get the library object whose name matches the original string */
+ oldname = get_original_string(curlabel);
+ if ((libobj = NameToObject(oldname->nextpart->data.string, NULL, FALSE))
+ != NULL) {
+
+ /* Set name of object to new string. Don't overwrite the */
+ /* object's technology *unless* the new string has a */
+ /* namespace, in which case the object's technology gets */
+ /* changed. */
+
+ char *techptr, *libobjname = libobj->name;
+ if ((techptr = strstr(libobjname, "::")) != NULL &&
+ (strstr(curlabel->string->nextpart->data.string, "::")
+ == NULL))
+ libobjname = techptr + 2;
+
+ /* Save a pointer to the old technology before we overwrite the name */
+ oldtech = GetObjectTechnology(libobj);
+
+ strcpy(libobjname, curlabel->string->nextpart->data.string);
+
+ /* If checkname() alters the name, it has to be copied back to */
+ /* the catalog label for the object. */
+
+ if (checkname(libobj)) {
+ undrawtext(curlabel);
+ curlabel->string->nextpart->data.string = (char *)realloc(
+ curlabel->string->nextpart->data.string,
+ (strlen(libobj->name) + 1) * sizeof(char));
+ strcpy(curlabel->string->nextpart->data.string, libobj->name);
+ XcSetFunction(GXcopy);
+ redrawtext(curlabel);
+ }
+ AddObjectTechnology(libobj);
+
+ /* If the technology name has changed, then both the old */
+ /* technology and the new technology need to be marked as */
+ /* having been modified. */
+
+ newtech = GetObjectTechnology(libobj);
+
+ if (oldtech != newtech) {
+ if (oldtech) oldtech->flags |= (u_char)TECH_CHANGED;
+ if (newtech) newtech->flags |= (u_char)TECH_CHANGED;
+ }
+ }
+
+ /* Check if we altered a page name */
+ else if ((libobj = NameToPageObject(oldname->nextpart->data.string,
+ NULL, &page)) != NULL) {
+ strcpy(libobj->name, curlabel->string->nextpart->data.string);
+ renamepage(page);
+ }
+
+ /* Check if we altered a library name */
+ else if ((libnum = NameToLibrary(oldname->nextpart->data.string)) != -1) {
+ libobj = xobjs.libtop[libnum + LIBRARY]->thisobject;
+ strcpy(libobj->name, curlabel->string->nextpart->data.string);
+ }
+ else {
+ Wprintf("Error: Cannot match name to any object, page, or library!");
+ refresh(NULL, NULL, NULL);
+ }
+
+ eventmode = CATALOG_MODE;
+ }
+ else { /* (hasstuff && eventmode != CATTEXT_MODE) */
+ eventmode = NORMAL_MODE;
+ incr_changes(topobject);
+ if (curlabel->pin != False) invalidate_netlist(topobject);
+ }
+
+ setdefaultfontmarks();
+ setcolormark(areawin->color);
+
+ if (!hasstuff) {
+ /* Delete empty labels */
+ standard_element_delete(NORMAL);
+ }
+ else if ((labelbuf = get_original_string(curlabel)) != NULL) {
+
+ /* If the original label (before modification) is a pin in a */
+ /* schematic/symbol with a matching symbol/schematic, and the */
+ /* name is unique, change every pin in the matching symbol/ */
+ /* schematic to match the new text. */
+
+ if ((curlabel->pin == LOCAL) && (topobject->symschem != NULL) &&
+ (topobject->symschem->schemtype != PRIMARY)) {
+ if ((findlabelcopy(curlabel, labelbuf) == NULL)
+ && (findlabelcopy(curlabel, curlabel->string) == NULL)) {
+ if (changeotherpins(curlabel, labelbuf) > 0) {
+ if (topobject->schemtype == PRIMARY ||
+ topobject->schemtype == SECONDARY)
+ Wprintf("Changed corresponding pin in associated symbol");
+ else
+ Wprintf("Changed corresponding pin in associated schematic");
+ incr_changes(topobject->symschem);
+ invalidate_netlist(topobject->symschem);
+ }
+ }
+ }
+
+ resolveparams(areawin->topinstance);
+ updateinstparam(topobject);
+ setobjecttype(topobject);
+ }
+ else
+ calcbbox(areawin->topinstance);
+
+ unselect_all();
+ return r;
+ }
+ else if (clientdata != NULL && keypressed == TEXT_RIGHT) {
+ if (curpos != NULL) areawin->textpos++;
+ }
+ else if (clientdata != NULL && keypressed == TEXT_LEFT) {
+ if (areawin->textpos > 1) areawin->textpos--;
+ }
+ else if (clientdata != NULL && keypressed == TEXT_DOWN) {
+ while (curpos != NULL) {
+ areawin->textpos++;
+ curpos = findstringpart(areawin->textpos, &locpos, curlabel->string,
+ areawin->topinstance);
+ if (curpos != NULL)
+ if (curpos->type == RETURN || curpos->type == MARGINSTOP)
+ break;
+ }
+ }
+ else if (clientdata != NULL && keypressed == TEXT_UP) {
+ while (areawin->textpos > 1) {
+ areawin->textpos--;
+ curpos = findstringpart(areawin->textpos, &locpos, curlabel->string,
+ areawin->topinstance);
+ if (curpos->type == RETURN || curpos->type == MARGINSTOP) {
+ if (areawin->textpos > 1) areawin->textpos--;
+ break;
+ }
+ }
+ }
+ else if (clientdata != NULL && keypressed == TEXT_HOME)
+ areawin->textpos = 1;
+ else if (clientdata != NULL && keypressed == TEXT_END)
+ areawin->textpos = stringlength(curlabel->string, True, areawin->topinstance);
+ else if (clientdata != NULL && keypressed == TEXT_SPLIT) {
+ labelptr *newlabel;
+ XPoint points[4], points1[4], points2[4];
+
+ /* Everything after the cursor gets dumped into a new label */
+
+ if ((areawin->textpos > 1) && (curpos != NULL)) {
+ labelbbox(curlabel, points, areawin->topinstance);
+ undrawtext(curlabel);
+ NEW_LABEL(newlabel, topobject);
+ labeldefaults(*newlabel, curlabel->pin, curlabel->position.x,
+ curlabel->position.y);
+ if (locpos > 0)
+ curpos = splitstring(areawin->textpos, &curlabel->string,
+ areawin->topinstance);
+ /* move back one position to find end of top part of string */
+ curpos = splitstring(areawin->textpos - 1, &curlabel->string,
+ areawin->topinstance);
+ if (curpos->nextpart->type == FONT_NAME) {
+ freelabel((*newlabel)->string);
+ (*newlabel)->string = curpos->nextpart;
+ }
+ else {
+ (*newlabel)->string->data.font = curlabel->string->data.font;
+ (*newlabel)->string->nextpart = curpos->nextpart;
+ }
+ curpos->nextpart = NULL;
+
+ /* Adjust position of both labels to retain their original */
+ /* relative positions. */
+
+ labelbbox(curlabel, points1, areawin->topinstance);
+ labelbbox((*newlabel), points2, areawin->topinstance);
+ curlabel->position.x += (points[1].x - points1[1].x);
+ curlabel->position.y += (points[1].y - points1[1].y);
+ (*newlabel)->position.x += (points[3].x - points2[3].x);
+ (*newlabel)->position.y += (points[3].y - points2[3].y);
+
+ XcSetFunction(GXcopy);
+ redrawtext(*newlabel);
+ do_redraw = True;
+ }
+ }
+
+ /* Write a font designator or other control into the string */
+
+ else if (clientdata != NULL) {
+ oparamptr ops;
+ stringpart *newpart;
+ Boolean errcond = False;
+
+ /* erase first before redrawing unless the string is empty */
+ undrawtext(curlabel);
+
+ /* Get text width first. Don't back up over spaces; this */
+ /* allows the margin width to be padded out with spaces. */
+
+ if (keypressed == MARGINSTOP)
+ tmpext = ULength(curlabel, areawin->topinstance, areawin->textpos, NULL);
+
+ if (locpos > 0) {
+ if (keypressed == MARGINSTOP) {
+ /* Move forward by any spaces; if we're at the text */
+ /* end, move to the next text part; otherwise, */
+ /* split the string. */
+
+ while (*(curpos->data.string + locpos) == ' ') locpos++;
+ if (*(curpos->data.string + locpos) == '\0') locpos = 0;
+ }
+ if (locpos > 0)
+ curpos = splitstring(areawin->textpos, &curlabel->string,
+ areawin->topinstance);
+ curpos = curpos->nextpart;
+ }
+ newpart = makesegment(&curlabel->string, curpos);
+ newpart->type = keypressed;
+ switch (keypressed) {
+ case RETURN:
+ // Identify this as an explicitly placed line break
+ newpart->data.flags = 0;
+ break;
+ case FONT_SCALE:
+ newpart->data.scale = *((float *)clientdata);
+ break;
+ case KERN:
+ newpart->data.kern[0] = *((short *)clientdata);
+ newpart->data.kern[1] = *((short *)clientdata + 1);
+ break;
+ case FONT_COLOR:
+ newpart->data.color = *((int *)clientdata);
+ if (newpart->data.color >= number_colors) errcond = True;
+ break;
+ case FONT_NAME:
+ newpart->data.font = *((int *)clientdata);
+ if (newpart->data.font >= fontcount) errcond = True;
+ break;
+ case MARGINSTOP:
+ /* A margin of 1 or 0 is useless, so such a value */
+ /* indicates to take the margin from the current */
+ /* position. */
+
+ if (*((int *)clientdata) <= 1)
+ newpart->data.width = (int)tmpext.width;
+ else
+ newpart->data.width = *((int *)clientdata);
+ CheckMarginStop(curlabel, areawin->topinstance, FALSE);
+ break;
+ case PARAM_START:
+ newpart->data.string = (char *)malloc(1 + strlen(clientdata));
+ strcpy(newpart->data.string, clientdata);
+ ops = match_param(topobject, clientdata);
+ if (ops == NULL) errcond = True;
+ else {
+ /* Forward edit cursor position to the end of the parameter */
+ do {
+ areawin->textpos++;
+ curpos = findstringpart(areawin->textpos, &locpos, curlabel->string,
+ areawin->topinstance);
+ } while (curpos && (curpos->type != PARAM_END));
+ }
+ break;
+ }
+ if (errcond == True) {
+ Wprintf("Error in insertion. Ignoring.");
+ deletestring(newpart, &curlabel->string, areawin->topinstance);
+ r = FALSE;
+ }
+ else {
+ areawin->textpos++;
+ }
+ do_redraw = True;
+ }
+
+ /* Append the character to the string. If the current label segment is */
+ /* not text, then create a text segment for it. */
+
+ else if (keypressed > 0 && keypressed < 256) {
+ stringpart *lastpos;
+
+ /* erase first. */
+ undrawtext(curlabel);
+
+ /* Current position is not in a text string */
+ if (locpos < 0) {
+
+ /* Find part of string which is immediately in front of areawin->textpos */
+ lastpos = findstringpart(areawin->textpos - 1, &locpos, curlabel->string,
+ areawin->topinstance);
+
+ /* No text on either side to attach to: make a new text segment */
+ if (locpos < 0) {
+ curpos = makesegment(&curlabel->string, curpos);
+ curpos->type = TEXT_STRING;
+ curpos->data.string = (u_char *) malloc(2);
+ curpos->data.string[0] = keypressed;
+ curpos->data.string[1] = '\0';
+ }
+ else { /* append to end of lastpos text string */
+ int slen = strlen(lastpos->data.string);
+ lastpos->data.string = (u_char *) realloc(lastpos->data.string,
+ 2 + slen);
+ *(lastpos->data.string + slen) = keypressed;
+ *(lastpos->data.string + slen + 1) = '\0';
+ }
+ }
+ else { /* prepend to end of curpos text string */
+ curpos->data.string = (u_char *) realloc(curpos->data.string,
+ 2 + strlen(curpos->data.string));
+ memmove(curpos->data.string + locpos + 1, curpos->data.string + locpos,
+ strlen(curpos->data.string + locpos) + 1);
+ *(curpos->data.string + locpos) = keypressed;
+ }
+ areawin->textpos++; /* move forward to next text position */
+ do_redraw = True;
+ r = TRUE;
+ }
+
+ /* Redraw the label */
+
+ if (do_redraw) {
+ /* Generate automatic line breaks if there is a MARGINSTOP directive */
+ CheckMarginStop(curlabel, areawin->topinstance, TRUE);
+
+ XcSetFunction(GXcopy);
+ redrawtext(curlabel);
+ }
+
+ UDrawTLine(curlabel);
+
+ if (r || do_redraw) {
+
+ /* Report on characters at the cursor position in the message window */
+
+ charreport(curlabel);
+
+ /* find current font and adjust menubuttons as necessary */
+
+ cfont = findcurfont(areawin->textpos, curlabel->string, areawin->topinstance);
+ if (cfont < 0) {
+ Wprintf("Error: Illegal label string");
+ return r;
+ }
+ else
+ setfontmarks(cfont, -1);
+
+ areawin->textend = 0;
+ }
+ return r;
+}
+
+/*-------------------------------------*/
+/* Initiate return from text edit mode */
+/*-------------------------------------*/
+
+void textreturn()
+{
+ labeltext(TEXT_RETURN, (char *)1);
+}
+
+/*-------------------------------------*/
+/* Change the justification of a label */
+/*-------------------------------------*/
+
+void rejustify(short mode)
+{
+ labelptr curlabel = NULL;
+ short *tsel;
+ short jsave;
+ Boolean preselected = False, changed = False;
+ static short transjust[] = {15, 13, 12, 7, 5, 4, 3, 1, 0};
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ curlabel = TOLABEL(EDITPART);
+ UDrawTLine(curlabel);
+ undrawtext(curlabel);
+ jsave = curlabel->justify;
+ curlabel->justify = transjust[mode] |
+ (curlabel->justify & NONJUSTFIELD);
+ if (jsave != curlabel->justify) {
+ register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance,
+ (genericptr)curlabel, (int)jsave);
+ changed = True;
+ }
+ redrawtext(curlabel);
+ UDrawTLine(curlabel);
+
+ setfontmarks(-1, curlabel->justify);
+ }
+ else {
+ if (areawin->selects == 0) {
+ if (!checkselect(LABEL))
+ return;
+ }
+ else preselected = TRUE;
+
+ for (tsel = areawin->selectlist; tsel < areawin->selectlist +
+ areawin->selects; tsel++) {
+ if (SELECTTYPE(tsel) == LABEL) {
+ curlabel = SELTOLABEL(tsel);
+ jsave = curlabel->justify;
+ undrawtext(curlabel);
+ curlabel->justify = transjust[mode] |
+ (curlabel->justify & NONJUSTFIELD);
+ if (jsave != curlabel->justify) {
+ register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance,
+ (genericptr)curlabel, (int)jsave);
+ changed = True;
+ }
+ }
+ }
+ if (preselected == FALSE && eventmode != MOVE_MODE && eventmode != COPY_MODE)
+ unselect_all();
+ else
+ draw_all_selected();
+ }
+ if (curlabel == NULL)
+ Wprintf("No labels chosen to rejustify");
+ else if (changed) {
+ pwriteback(areawin->topinstance);
+ calcbbox(areawin->topinstance);
+ incr_changes(topobject);
+ }
+}
+
+/*----------------------------------*/
+/* Sane default values for a spline */
+/*----------------------------------*/
+
+void splinedefaults(splineptr newspline, int x, int y)
+{
+ short j;
+
+ for (j = 0; j < 4; j++) {
+ newspline->ctrl[j].x = x;
+ newspline->ctrl[j].y = y;
+ }
+ newspline->ctrl[1].x += (int)(xobjs.pagelist[areawin->page]->gridspace / 2);
+ newspline->ctrl[2].x -= (int)(xobjs.pagelist[areawin->page]->gridspace / 2);
+ newspline->width = areawin->linewidth;
+ newspline->style = areawin->style;
+ newspline->color = areawin->color;
+ newspline->passed = NULL;
+ newspline->cycle = NULL;
+ calcspline(newspline);
+}
+
+/*-------------------------*/
+/* Start drawing a spline. */
+/*-------------------------*/
+
+void splinebutton(int x, int y)
+{
+ splineptr *newspline;
+ XPoint userpt;
+ short *newselect;
+
+ unselect_all();
+ NEW_SPLINE(newspline, topobject);
+ newselect = allocselect();
+ *newselect = topobject->parts - 1;
+
+ snap(x, y, &userpt);
+ splinedefaults(*newspline, userpt.x, userpt.y);
+ addcycle((genericptr *)newspline, 3, 0);
+ makerefcycle((*newspline)->cycle, 3);
+
+ XcSetXORFg(areawin->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawSpline(*newspline, xobjs.pagelist[areawin->page]->wirewidth);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+
+ eventmode = SPLINE_MODE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate cycles on a path where endpoints meet, so that the path */
+/* remains connected during an edit. If the last point on any part */
+/* of the path is a cycle, then the first point on the next part of */
+/* the path should also be a cycle, with the same flags. */
+/* */
+/* If the global setting "tangents" is set, then the control points of */
+/* connecting splines set the corresponding control point to "ANTIXY" */
+/* so that the control points track angle and distance from the */
+/* endpoint. */
+/*----------------------------------------------------------------------*/
+
+void updatepath(pathptr thepath)
+{
+ genericptr *ggen, *ngen;
+ short locparts, cycle, ncycle;
+ pointselect *cptr;
+ polyptr thispoly;
+ splineptr thisspline;
+
+ for (ggen = thepath->plist; ggen < thepath->plist + thepath->parts; ggen++) {
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ findconstrained(TOPOLY(ggen));
+ break;
+ }
+ }
+
+ locparts = (thepath->style & UNCLOSED) ? thepath->parts - 1 : thepath->parts;
+ for (ggen = thepath->plist; ggen < thepath->plist + locparts; ggen++) {
+ ngen = (ggen == thepath->plist + thepath->parts - 1) ? thepath->plist : ggen + 1;
+
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ thispoly = TOPOLY(ggen);
+ if (thispoly->cycle == NULL) continue;
+ cycle = thispoly->number - 1;
+ for (cptr = thispoly->cycle;; cptr++) {
+ if (cptr->number == cycle) break;
+ if (cptr->flags & LASTENTRY) break;
+ }
+ if (cptr->number != cycle) continue;
+ break;
+ case SPLINE:
+ thisspline = TOSPLINE(ggen);
+ if (thisspline->cycle == NULL) continue;
+ cycle = 3;
+ for (cptr = thisspline->cycle;; cptr++) {
+ if (cptr->number == cycle) break;
+ if (cptr->flags & LASTENTRY) break;
+ }
+ if (cptr->number != cycle) continue;
+ break;
+ }
+ addcycle(ngen, 0, cptr->flags & (EDITX | EDITY));
+ switch (ELEMENTTYPE(*ngen)) {
+ case POLYGON:
+ findconstrained(TOPOLY(ngen));
+ break;
+ }
+ }
+
+ /* Do the same thing in the other direction */
+ locparts = (thepath->style & UNCLOSED) ? 1 : 0;
+ for (ggen = thepath->plist + thepath->parts - 1; ggen >= thepath->plist + locparts;
+ ggen--) {
+ ngen = (ggen == thepath->plist) ? thepath->plist + thepath->parts - 1 : ggen - 1;
+
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ thispoly = TOPOLY(ggen);
+ if (thispoly->cycle == NULL) continue;
+ cycle = 0;
+ for (cptr = thispoly->cycle;; cptr++) {
+ if (cptr->number == cycle) break;
+ if (cptr->flags & LASTENTRY) break;
+ }
+ if (cptr->number != cycle) continue;
+ break;
+ case SPLINE:
+ thisspline = TOSPLINE(ggen);
+ if (thisspline->cycle == NULL) continue;
+ cycle = 0;
+ for (cptr = thisspline->cycle;; cptr++) {
+ if (cptr->number == cycle) break;
+ if (cptr->flags & LASTENTRY) break;
+ }
+ if (cptr->number != cycle) continue;
+ break;
+ }
+ switch (ELEMENTTYPE(*ngen)) {
+ case POLYGON:
+ addcycle(ngen, TOPOLY(ngen)->number - 1, cptr->flags & (EDITX | EDITY));
+ break;
+ case SPLINE:
+ addcycle(ngen, 3, cptr->flags & (EDITX | EDITY));
+ break;
+ }
+ }
+}
+
+/*--------------------------------------*/
+/* Set default values for an arc */
+/*--------------------------------------*/
+
+void arcdefaults(arcptr newarc, int x, int y)
+{
+ newarc->style = areawin->style;
+ newarc->color = areawin->color;
+ newarc->position.x = x;
+ newarc->position.y = y;
+ newarc->width = areawin->linewidth;
+ newarc->radius = 0;
+ newarc->yaxis = 0;
+ newarc->angle1 = 0;
+ newarc->angle2 = 360;
+ newarc->passed = NULL;
+ newarc->cycle = NULL;
+ calcarc(newarc);
+}
+
+/*-------------------------------------*/
+/* Button handler when creating an arc */
+/*-------------------------------------*/
+
+void arcbutton(int x, int y)
+{
+ arcptr *newarc;
+ XPoint userpt;
+ short *newselect;
+
+ unselect_all();
+ NEW_ARC(newarc, topobject);
+ newselect = allocselect();
+ *newselect = topobject->parts - 1;
+ snap(x, y, &userpt);
+ saveratio = 1.0;
+ arcdefaults(*newarc, userpt.x, userpt.y);
+ addcycle((genericptr *)newarc, 0, 0);
+
+ XcSetXORFg((*newarc)->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawArc(*newarc, xobjs.pagelist[areawin->page]->wirewidth);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackarc, NULL);
+
+ eventmode = ARC_MODE;
+}
+
+/*----------------------------------*/
+/* Track an arc during mouse motion */
+/*----------------------------------*/
+
+void trackarc(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ XPoint newpos;
+ arcptr newarc;
+ double adjrat;
+ short cycle;
+
+ newarc = TOARC(EDITPART);
+
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+ if (areawin->save.x == newpos.x && areawin->save.y == newpos.y) return;
+
+ UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth);
+ UDrawXLine(areawin->save, newarc->position);
+
+ cycle = (newarc->cycle == NULL) ? -1 : newarc->cycle->number;
+ if (cycle == 1 || cycle == 2) {
+ float *angleptr, tmpang;
+
+ adjrat = (newarc->yaxis == 0) ? 1 :
+ (double)(abs(newarc->radius)) / (double)newarc->yaxis;
+ angleptr = (cycle == 1) ? &newarc->angle1 : &newarc->angle2;
+ tmpang = (float)(atan2((double)(newpos.y - newarc->position.y) * adjrat,
+ (double)(newpos.x - newarc->position.x)) / RADFAC);
+ if (cycle == 1) {
+ if (tmpang > newarc->angle2) tmpang -= 360;
+ else if (newarc->angle2 - tmpang > 360) newarc->angle2 -= 360;
+ }
+ else {
+ if (tmpang < newarc->angle1) tmpang += 360;
+ else if (tmpang - newarc->angle1 > 360) newarc->angle1 += 360;
+ }
+ *angleptr = tmpang;
+
+ if (newarc->angle2 <= 0) {
+ newarc->angle2 += 360;
+ newarc->angle1 += 360;
+ }
+ if (newarc->angle2 <= newarc->angle1)
+ newarc->angle1 -= 360;
+ }
+ else if (cycle == 0) {
+ short direc = (newarc->radius < 0);
+ newarc->radius = wirelength(&newpos, &(newarc->position));
+ newarc->yaxis = (short)((double)newarc->radius * saveratio);
+ if (direc) newarc->radius = -newarc->radius;
+ }
+ else {
+ newarc->yaxis = wirelength(&newpos, &(newarc->position));
+ saveratio = (double)newarc->yaxis / (double)newarc->radius;
+ }
+
+ calcarc(newarc);
+
+ XcSetXORFg(newarc->color, BACKGROUND);
+ UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth);
+ UDrawXLine(newpos, newarc->position);
+ printpos(newpos.x, newpos.y);
+
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+
+ flusharea();
+}
+
+/*--------------------------------------*/
+/* Sane default values for a polygon */
+/*--------------------------------------*/
+
+void polydefaults(polyptr newpoly, int number, int x, int y)
+{
+ pointlist pointptr;
+
+ newpoly->style = areawin->style & ~UNCLOSED;
+ newpoly->color = areawin->color;
+ newpoly->width = areawin->linewidth;
+ newpoly->number = number;
+ newpoly->passed = NULL;
+ newpoly->cycle = NULL;
+ if (number == 0)
+ newpoly->points = NULL;
+ else {
+ newpoly->points = (pointlist) malloc(number * sizeof(XPoint));
+
+ for (pointptr = newpoly->points; pointptr < newpoly->points + number;
+ pointptr++) {
+ pointptr->x = x;
+ pointptr->y = y;
+ }
+ }
+}
+
+/*------------------------------------*/
+/* Button handler when creating a box */
+/*------------------------------------*/
+
+void boxbutton(int x, int y)
+{
+ polyptr *newbox;
+ XPoint userpt;
+ short *newselect;
+
+ unselect_all();
+ NEW_POLY(newbox, topobject);
+ newselect = allocselect();
+ *newselect = topobject->parts - 1;
+ snap(x, y, &userpt);
+ polydefaults(*newbox, 4, userpt.x, userpt.y);
+
+ XcSetXORFg((*newbox)->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawPolygon(*newbox, xobjs.pagelist[areawin->page]->wirewidth);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackbox, NULL);
+
+ eventmode = BOX_MODE;
+}
+
+/*---------------------------------*/
+/* Track a box during mouse motion */
+/*---------------------------------*/
+
+void trackbox(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ XPoint newpos;
+ polyptr newbox;
+ pointlist pointptr;
+
+ newbox = TOPOLY(EDITPART);
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+
+ if (areawin->save.x == newpos.x && areawin->save.y == newpos.y) return;
+
+ UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth);
+
+ pointptr = newbox->points + 1; pointptr->y = newpos.y;
+ pointptr++; pointptr->y = newpos.y; pointptr->x = newpos.x;
+ pointptr++; pointptr->x = newpos.x;
+
+ XcSetXORFg(newbox->color, BACKGROUND);
+ UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth);
+ printpos(newpos.x, newpos.y);
+
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+
+ flusharea();
+}
+
+/*----------------------------------------------------------------------*/
+/* Track a wire during mouse motion */
+/* Note: The manhattanize algorithm will change the effective cursor */
+/* position to keep the wire manhattan if the wire is only 1 segment. */
+/* It will change the previous point's position if the wire has more */
+/* than one segment. They are called at different times to ensure the */
+/* wire redraw is correct. */
+/*----------------------------------------------------------------------*/
+
+void trackwire(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ XPoint newpos, upos, *tpoint;
+ polyptr newwire;
+
+ newwire = TOPOLY(EDITPART);
+
+ if (areawin->attachto >= 0) {
+ upos = UGetCursorPos();
+ findattach(&newpos, NULL, &upos);
+ }
+ else {
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+ if (areawin->manhatn && (newwire->number == 2))
+ manhattanize(&newpos, newwire, -1, TRUE);
+ }
+
+ if (areawin->save.x != newpos.x || areawin->save.y != newpos.y) {
+ tpoint = newwire->points + newwire->number - 1;
+ UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth);
+ if (areawin->manhatn && (newwire->number > 2))
+ manhattanize(&newpos, newwire, -1, TRUE);
+ tpoint->x = newpos.x;
+ tpoint->y = newpos.y;
+ XcSetXORFg(newwire->color, BACKGROUND);
+ UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth);
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+ printpos(newpos.x, newpos.y);
+ }
+
+ flusharea();
+}
+
+/*--------------------------*/
+/* Start drawing a polygon. */
+/*--------------------------*/
+
+void startwire(XPoint *userpt)
+{
+ polyptr *newwire;
+ pointlist pointptr;
+ short *newselect;
+
+ unselect_all();
+ NEW_POLY(newwire, topobject);
+ newselect = allocselect();
+ *newselect = topobject->parts - 1;
+
+ /* always start unfilled, unclosed; can fix on next button-push. */
+
+ (*newwire)->style = UNCLOSED | (areawin->style & (DASHED | DOTTED));
+ (*newwire)->color = areawin->color;
+ (*newwire)->number = 2;
+ (*newwire)->width = areawin->linewidth;
+ (*newwire)->points = (pointlist) malloc(2 * sizeof(XPoint));
+ (*newwire)->passed = NULL;
+ (*newwire)->cycle = NULL;
+ pointptr = (*newwire)->points;
+ pointptr->x = (pointptr + 1)->x = areawin->save.x = userpt->x;
+ pointptr->y = (pointptr + 1)->y = areawin->save.y = userpt->y;
+
+ XcSetXORFg((*newwire)->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawPolygon(*newwire, xobjs.pagelist[areawin->page]->wirewidth);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackwire, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Find which points should track along with the edit point in */
+/* in polygon RHOMBOID or MANHATTAN edit modes. */
+/* (point number is stored in lastpoly->cycle) */
+/* */
+/* NOTE: This routine assumes that either the points have just */
+/* been selected, or that advancecycle() has been called to */
+/* remove all previously recorded tracking points. */
+/*--------------------------------------------------------------*/
+
+void findconstrained(polyptr lastpoly)
+{
+ XPoint *savept, *npt, *lpt;
+ short cycle;
+ short lflags, nflags;
+ short lcyc, ncyc;
+ pointselect *cptr, *nptr;
+
+ if (areawin->boxedit == NORMAL) return;
+
+ if (lastpoly->cycle == NULL) return;
+
+ /* Set "process" flags on all original points */
+ for (cptr = lastpoly->cycle;; cptr++) {
+ cptr->flags |= PROCESS;
+ if (cptr->flags & LASTENTRY) break;
+ }
+
+ cptr = lastpoly->cycle;
+ while (1) {
+ if (cptr->flags & PROCESS) {
+ cptr->flags &= ~PROCESS;
+ cycle = cptr->number;
+ savept = lastpoly->points + cycle;
+
+ /* find points before and after the edit point */
+
+ lcyc = (cycle == 0) ? ((lastpoly->style & UNCLOSED) ?
+ -1 : lastpoly->number - 1) : cycle - 1;
+ ncyc = (cycle == lastpoly->number - 1) ?
+ ((lastpoly->style & UNCLOSED) ? -1 : 0) : cycle + 1;
+
+ lpt = (lcyc == -1) ? NULL : lastpoly->points + lcyc;
+ npt = (ncyc == -1) ? NULL : lastpoly->points + ncyc;
+
+ lflags = nflags = NONE;
+
+ /* two-point polygons (lines) are a degenerate case in RHOMBOID edit mode */
+
+ if (areawin->boxedit != MANHATTAN && lastpoly->number <= 2) return;
+
+ /* This is complicated but logical: in MANHATTAN mode, boxes maintain */
+ /* box shape. In RHOMBOID modes, parallelagrams maintain shape. The */
+ /* "savedir" variable determines which coordinate(s) of which point(s) */
+ /* should track along with the edit point. */
+
+ if (areawin->boxedit != RHOMBOIDY) {
+ if (lpt != NULL) {
+ if (lpt->y == savept->y) {
+ lflags |= EDITY;
+ if (areawin->boxedit == RHOMBOIDX && lpt->x != savept->x)
+ lflags |= EDITX;
+ else if (areawin->boxedit == RHOMBOIDA && npt != NULL) {
+ if (npt->y != savept->y) nflags |= EDITX;
+ }
+ }
+ }
+ if (npt != NULL) {
+ if (npt->y == savept->y) {
+ nflags |= EDITY;
+ if (areawin->boxedit == RHOMBOIDX && npt->x != savept->x)
+ nflags |= EDITX;
+ else if (areawin->boxedit == RHOMBOIDA && lpt != NULL) {
+ if (lpt->y != savept->y) lflags |= EDITX;
+ }
+ }
+ }
+ }
+ if (areawin->boxedit != RHOMBOIDX) {
+ if (lpt != NULL) {
+ if (lpt->x == savept->x) {
+ lflags |= EDITX;
+ if (areawin->boxedit == RHOMBOIDY && lpt->y != savept->y)
+ lflags |= EDITY;
+ else if (areawin->boxedit == RHOMBOIDA && npt != NULL) {
+ if (npt->x != savept->x) nflags |= EDITY;
+ }
+ }
+ }
+ if (npt != NULL) {
+ if (npt->x == savept->x) {
+ nflags |= EDITX;
+ if (areawin->boxedit == RHOMBOIDY && npt->y != savept->y)
+ nflags |= EDITY;
+ else if (areawin->boxedit == RHOMBOIDA && lpt != NULL) {
+ if (lpt->x != savept->x) lflags |= EDITY;
+ }
+ }
+ }
+ }
+ nptr = cptr + 1;
+ if (lpt != NULL && lflags != 0) {
+ addcycle((genericptr *)(&lastpoly), lcyc, lflags);
+ cptr = nptr = lastpoly->cycle;
+ }
+ if (npt != NULL && nflags != 0) {
+ addcycle((genericptr *)(&lastpoly), ncyc, nflags);
+ cptr = nptr = lastpoly->cycle;
+ }
+ }
+ else
+ nptr = cptr + 1;
+ if (cptr->flags & LASTENTRY) break;
+ cptr = nptr;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Track movement of arc, spline, or polygon segments */
+/* during edit mode */
+/*------------------------------------------------------*/
+
+void trackelement(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ XPoint newpos, origpt, *curpt;
+ polyptr editpoly;
+ genericptr *ggen;
+ short cycle, *selobj;
+ pointselect *cptr;
+ int deltax, deltay;
+
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+
+ /* force attachment if required */
+ if (areawin->attachto >= 0) {
+ XPoint apos;
+ findattach(&apos, NULL, &newpos);
+ newpos = apos;
+ }
+
+ if (areawin->save.x == newpos.x && areawin->save.y == newpos.y) return;
+
+ /* Find the reference point */
+
+ cptr = getrefpoint(TOGENERIC(EDITPART), &curpt);
+ switch(ELEMENTTYPE(TOGENERIC(EDITPART))) {
+ case POLYGON:
+ if (cptr == NULL)
+ curpt = TOPOLY(EDITPART)->points;
+ break;
+ case SPLINE:
+ if (cptr == NULL)
+ curpt = &(TOSPLINE(EDITPART)->ctrl[0]);
+ break;
+ case ARC:
+ curpt = &(TOARC(EDITPART)->position);
+ break;
+ case OBJINST:
+ curpt = &(TOOBJINST(EDITPART)->position);
+ break;
+ case GRAPHIC:
+ curpt = &(TOGRAPHIC(EDITPART)->position);
+ break;
+ }
+ origpt = *curpt;
+ deltax = newpos.x - curpt->x;
+ deltay = newpos.y - curpt->y;
+
+ /* Now adjust all edited elements relative to the reference point */
+
+ for (selobj = areawin->selectlist; selobj < areawin->selectlist +
+ areawin->selects; selobj++)
+ {
+ easydraw(*selobj, DOFORALL);
+ editpoints(SELTOGENERICPTR(selobj), deltax, deltay);
+ XcSetXORFg(topobject->plist[*selobj]->color, BACKGROUND);
+ easydraw(*selobj, DOFORALL);
+ }
+
+ printpos(newpos.x, newpos.y);
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+
+ flusharea();
+}
+
+/*-------------------------------------------------*/
+/* Determine values of endpoints of an element */
+/*-------------------------------------------------*/
+
+void setendpoint(short *scnt, short direc, XPoint **endpoint, XPoint *arcpoint)
+{
+ genericptr *sptr = topobject->plist + (*scnt);
+
+ switch(ELEMENTTYPE(*sptr)) {
+ case POLYGON:
+ if (direc)
+ *endpoint = TOPOLY(sptr)->points + TOPOLY(sptr)->number - 1;
+ else
+ *endpoint = TOPOLY(sptr)->points;
+ break;
+ case SPLINE:
+ if (direc)
+ *endpoint = &(TOSPLINE(sptr)->ctrl[3]);
+ else
+ *endpoint = &(TOSPLINE(sptr)->ctrl[0]);
+ break;
+ case ARC:
+ if (direc) {
+ arcpoint->x = (short)(TOARC(sptr)->points[TOARC(sptr)->number - 1].x
+ + 0.5);
+ arcpoint->y = (short)(TOARC(sptr)->points[TOARC(sptr)->number - 1].y
+ + 0.5);
+ }
+ else {
+ arcpoint->x = (short)(TOARC(sptr)->points[0].x + 0.5);
+ arcpoint->y = (short)(TOARC(sptr)->points[0].y + 0.5);
+ }
+ *endpoint = arcpoint;
+ break;
+ }
+}
+
+/*------------------------------------------------------------*/
+/* Reverse points in a point list */
+/*------------------------------------------------------------*/
+
+void reversepoints(XPoint *plist, short number)
+{
+ XPoint hold, *ppt;
+ XPoint *pend = plist + number - 1;
+ short hnum = number >> 1;
+
+ for (ppt = plist; ppt < plist + hnum; ppt++, pend--) {
+ hold.x = ppt->x;
+ hold.y = ppt->y;
+ ppt->x = pend->x;
+ ppt->y = pend->y;
+ pend->x = hold.x;
+ pend->y = hold.y;
+ }
+}
+
+/*------------------------------------------------------------*/
+/* Same as above for floating-point positions */
+/*------------------------------------------------------------*/
+
+void reversefpoints(XfPoint *plist, short number)
+{
+ XfPoint hold, *ppt;
+ XfPoint *pend = plist + number - 1;
+ short hnum = number >> 1;
+
+ for (ppt = plist; ppt < plist + hnum; ppt++, pend--) {
+ hold.x = ppt->x;
+ hold.y = ppt->y;
+ ppt->x = pend->x;
+ ppt->y = pend->y;
+ pend->x = hold.x;
+ pend->y = hold.y;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Permanently remove an element from the topobject plist */
+/* add = 1 if plist has (parts + 1) elements */
+/*--------------------------------------------------------------*/
+
+void freepathparts(short *selectobj, short add)
+{
+ genericptr *oldelem = topobject->plist + (*selectobj);
+ switch(ELEMENTTYPE(*oldelem)) {
+ case POLYGON:
+ free((TOPOLY(oldelem))->points);
+ break;
+ }
+ free(*oldelem);
+ removep(selectobj, add);
+}
+
+/*--------------------------------------------------------------*/
+/* Remove a part from an object */
+/* add = 1 if plist has (parts + 1) elements */
+/*--------------------------------------------------------------*/
+
+void removep(short *selectobj, short add)
+{
+ genericptr *oldelem = topobject->plist + (*selectobj);
+
+ for (++oldelem; oldelem < topobject->plist + topobject->parts + add; oldelem++)
+ *(oldelem - 1) = *oldelem;
+
+ topobject->parts--;
+}
+
+/*-------------------------------------------------*/
+/* Break a path into its constituent components */
+/*-------------------------------------------------*/
+
+void unjoin()
+{
+ short *selectobj;
+ genericptr *genp, *newg;
+ pathptr oldpath;
+ polyptr oldpoly, *newpoly;
+ Boolean preselected;
+ short i, cycle;
+
+ if (areawin->selects == 0) {
+ select_element(PATH | POLYGON);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+
+ if (areawin->selects == 0) {
+ Wprintf("No objects selected.");
+ return;
+ }
+
+ /* for each selected path or polygon */
+
+ XcSetFunction(GXcopy);
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ XSetForeground(dpy, areawin->gc, BACKGROUND);
+ if (SELECTTYPE(selectobj) == PATH) {
+ oldpath = SELTOPATH(selectobj);
+
+ /* undraw the path */
+
+ UDrawPath(oldpath, xobjs.pagelist[areawin->page]->wirewidth);
+
+ /* move components to the top level */
+
+ topobject->plist = (genericptr *)realloc(topobject->plist,
+ (topobject->parts + oldpath->parts) * sizeof(genericptr));
+ newg = topobject->plist + topobject->parts;
+ for (genp = oldpath->plist; genp < oldpath->plist +
+ oldpath->parts; genp++, newg++) {
+ *newg = *genp;
+ }
+ topobject->parts += oldpath->parts;
+
+ /* remove the path object and revise the selectlist */
+
+ freepathparts(selectobj, 0);
+ reviseselect(areawin->selectlist, areawin->selects, selectobj);
+ }
+ else if (SELECTTYPE(selectobj) == POLYGON) {
+ /* Method to break a polygon, in lieu of the edit-mode */
+ /* polygon break that was removed. */
+ oldpoly = SELTOPOLY(selectobj);
+ UDrawPolygon(oldpoly, xobjs.pagelist[areawin->page]->wirewidth);
+
+ /* Get the point nearest the cursor, and break at that point */
+ cycle = closepoint(oldpoly, &areawin->save);
+ if (cycle > 0 && cycle < (oldpoly->number - 1)) {
+ NEW_POLY(newpoly, topobject);
+ polycopy(*newpoly, oldpoly);
+ for (i = cycle; i < oldpoly->number; i++)
+ (*newpoly)->points[i - cycle] = (*newpoly)->points[i];
+ oldpoly->number = cycle + 1;
+ (*newpoly)->number = (*newpoly)->number - cycle;
+ }
+ }
+ }
+ if (!preselected) clearselects();
+ drawarea(NULL, NULL, NULL);
+}
+
+/*-------------------------------------------------*/
+/* Test if two points are near each other */
+/*-------------------------------------------------*/
+
+Boolean neartest(XPoint *point1, XPoint *point2)
+{
+ short diff[2];
+
+ diff[0] = point1->x - point2->x;
+ diff[1] = point1->y - point2->y;
+ diff[0] = abs(diff[0]);
+ diff[1] = abs(diff[1]);
+
+ if (diff[0] <= 2 && diff[1] <= 2) return True;
+ else return False;
+}
+
+
+/*-------------------------------------------------*/
+/* Join stuff together */
+/*-------------------------------------------------*/
+
+void join()
+{
+ short *selectobj;
+ polyptr *newpoly, nextwire;
+ pathptr *newpath;
+ genericptr *pgen;
+ short *scount, *sptr, *sptr2, *direc, *order;
+ short ordered, startpt = 0;
+ short numpolys, numlabels, numpoints, polytype;
+ int polycolor;
+ float polywidth;
+ XPoint *testpoint, *testpoint2, *begpoint, *endpoint, arcpoint[4];
+ XPoint *begpoint2, *endpoint2;
+ Boolean allpolys = True;
+ objectptr delobj;
+
+ numpolys = numlabels = 0;
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ if (SELECTTYPE(selectobj) == POLYGON) {
+ /* arbitrary: keep style of last polygon in selectlist */
+ polytype = SELTOPOLY(selectobj)->style;
+ polywidth = SELTOPOLY(selectobj)->width;
+ polycolor = SELTOPOLY(selectobj)->color;
+ numpolys++;
+ }
+ else if (SELECTTYPE(selectobj) == SPLINE) {
+ polytype = SELTOSPLINE(selectobj)->style;
+ polywidth = SELTOSPLINE(selectobj)->width;
+ polycolor = SELTOSPLINE(selectobj)->color;
+ numpolys++;
+ allpolys = False;
+ }
+ else if (SELECTTYPE(selectobj) == ARC) {
+ polytype = SELTOARC(selectobj)->style;
+ polywidth = SELTOARC(selectobj)->width;
+ polycolor = SELTOARC(selectobj)->color;
+ numpolys++;
+ allpolys = False;
+ }
+ else if (SELECTTYPE(selectobj) == LABEL)
+ numlabels++;
+ }
+ if ((numpolys == 0) && (numlabels == 0)) {
+ Wprintf("No elements selected for joining.");
+ return;
+ }
+ else if ((numpolys == 1) || (numlabels == 1)) {
+ Wprintf("Only one element: nothing to join to.");
+ return;
+ }
+ else if ((numpolys > 1) && (numlabels > 1)) {
+ Wprintf("Selection mixes labels and line segments. Ignoring.");
+ return;
+ }
+ else if (numlabels > 0) {
+ joinlabels();
+ return;
+ }
+
+ /* scount is a table of element numbers */
+ /* order is an ordered table of end-to-end elements */
+ /* direc is an ordered table of path directions (0=same as element, */
+ /* 1=reverse from element definition) */
+
+ scount = (short *) malloc(numpolys * sizeof(short));
+ order = (short *) malloc(numpolys * sizeof(short));
+ direc = (short *) malloc(numpolys * sizeof(short));
+ sptr = scount;
+ numpoints = 1;
+
+ /* make a record of the element instances involved */
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ if (SELECTTYPE(selectobj) == POLYGON) {
+ numpoints += SELTOPOLY(selectobj)->number - 1;
+ *(sptr++) = *selectobj;
+ }
+ else if (SELECTTYPE(selectobj) == SPLINE || SELECTTYPE(selectobj) == ARC)
+ *(sptr++) = *selectobj;
+ }
+
+ /* Sort the elements by sorting the scount array: */
+ /* Loop through each point as starting point in case of strangely connected */
+ /* structures. . . for normal structures it should break out on the first */
+ /* loop (startpt = 0). */
+
+ for (startpt = 0; startpt < numpolys; startpt++) {
+
+ /* set first in ordered list */
+
+ direc[0] = 0;
+ order[0] = *(scount + startpt);
+
+ for (ordered = 0; ordered < numpolys - 1; ordered++) {
+
+ setendpoint(order + ordered, (1 ^ direc[ordered]), &endpoint2, &arcpoint[0]);
+ setendpoint(order, (0 ^ direc[0]), &begpoint2, &arcpoint[1]);
+
+ for (sptr = scount; sptr < scount + numpolys; sptr++) {
+
+ /* don't compare with things already in the list */
+ for (sptr2 = order; sptr2 <= order + ordered; sptr2++)
+ if (*sptr == *sptr2) break;
+ if (sptr2 != order + ordered + 1) continue;
+
+ setendpoint(sptr, 0, &begpoint, &arcpoint[2]);
+ setendpoint(sptr, 1, &endpoint, &arcpoint[3]);
+
+ /* four cases of matching endpoint of one element to another */
+
+ if (neartest(begpoint, endpoint2)) {
+ order[ordered + 1] = *sptr;
+ direc[ordered + 1] = 0;
+ break;
+ }
+ else if (neartest(endpoint, endpoint2)) {
+ order[ordered + 1] = *sptr;
+ direc[ordered + 1] = 1;
+ break;
+ }
+ else if (neartest(begpoint, begpoint2)) {
+ for (sptr2 = order + ordered + 1; sptr2 > order; sptr2--)
+ *sptr2 = *(sptr2 - 1);
+ for (sptr2 = direc + ordered + 1; sptr2 > direc; sptr2--)
+ *sptr2 = *(sptr2 - 1);
+ order[0] = *sptr;
+ direc[0] = 1;
+ break;
+ }
+ else if (neartest(endpoint, begpoint2)) {
+ for (sptr2 = order + ordered + 1; sptr2 > order; sptr2--)
+ *sptr2 = *(sptr2 - 1);
+ for (sptr2 = direc + ordered + 1; sptr2 > direc; sptr2--)
+ *sptr2 = *(sptr2 - 1);
+ order[0] = *sptr;
+ direc[0] = 0;
+ break;
+ }
+ }
+ if (sptr == scount + numpolys) break;
+ }
+ if (ordered == numpolys - 1) break;
+ }
+
+ if (startpt == numpolys) {
+ Wprintf("Cannot join: Too many free endpoints");
+ free(order);
+ free(direc);
+ free(scount);
+ return;
+ }
+
+ /* create the new polygon or path */
+
+ if (allpolys) {
+ NEW_POLY(newpoly, topobject);
+
+ (*newpoly)->number = numpoints;
+ (*newpoly)->points = (pointlist) malloc(numpoints * sizeof(XPoint));
+ (*newpoly)->width = polywidth;
+ (*newpoly)->style = polytype;
+ (*newpoly)->color = polycolor;
+ (*newpoly)->passed = NULL;
+ (*newpoly)->cycle = NULL;
+
+ /* insert the points into the new polygon */
+
+ testpoint2 = (*newpoly)->points;
+ for (sptr = order; sptr < order + numpolys; sptr++) {
+ nextwire = SELTOPOLY(sptr);
+ if (*(direc + (short)(sptr - order)) == 0) {
+ for (testpoint = nextwire->points; testpoint < nextwire->points +
+ nextwire->number - 1; testpoint++) {
+ testpoint2->x = testpoint->x;
+ testpoint2->y = testpoint->y;
+ testpoint2++;
+ }
+ }
+ else {
+ for (testpoint = nextwire->points + nextwire->number - 1; testpoint
+ > nextwire->points; testpoint--) {
+ testpoint2->x = testpoint->x;
+ testpoint2->y = testpoint->y;
+ testpoint2++;
+ }
+ }
+ }
+ /* pick up the last point */
+ testpoint2->x = testpoint->x;
+ testpoint2->y = testpoint->y;
+
+ /* delete the old elements from the list */
+
+ register_for_undo(XCF_Wire, UNDO_MORE, areawin->topinstance, *newpoly);
+
+ delobj = delete_element(areawin->topinstance, areawin->selectlist,
+ areawin->selects, NORMAL);
+ register_for_undo(XCF_Delete, UNDO_DONE, areawin->topinstance,
+ delobj, NORMAL);
+
+ }
+ else { /* create a path */
+
+ NEW_PATH(newpath, topobject);
+ (*newpath)->style = polytype;
+ (*newpath)->color = polycolor;
+ (*newpath)->width = polywidth;
+ (*newpath)->parts = 0;
+ (*newpath)->plist = (genericptr *) malloc(sizeof(genericptr));
+ (*newpath)->passed = NULL;
+
+ /* copy the elements from the top level into the path structure */
+
+ for (sptr = order; sptr < order + numpolys; sptr++) {
+ genericptr *oldelem = topobject->plist + *sptr;
+ genericptr *newelem;
+
+ switch (ELEMENTTYPE(*oldelem)) {
+ case POLYGON: {
+ polyptr copypoly = TOPOLY(oldelem);
+ polyptr *newpoly;
+ NEW_POLY(newpoly, (*newpath));
+ polycopy(*newpoly, copypoly);
+ } break;
+ case ARC: {
+ arcptr copyarc = TOARC(oldelem);
+ arcptr *newarc;
+ NEW_ARC(newarc, (*newpath));
+ arccopy(*newarc, copyarc);
+ } break;
+ case SPLINE: {
+ splineptr copyspline = TOSPLINE(oldelem);
+ splineptr *newspline;
+ NEW_SPLINE(newspline, (*newpath));
+ splinecopy(*newspline, copyspline);
+ } break;
+ }
+ newelem = (*newpath)->plist + (*newpath)->parts - 1;
+
+ /* reverse point order if necessary */
+
+ if (*(direc + (short)(sptr - order)) == 1) {
+ switch (ELEMENTTYPE(*newelem)) {
+ case POLYGON:
+ reversepoints(TOPOLY(newelem)->points, TOPOLY(newelem)->number);
+ break;
+ case ARC:
+ TOARC(newelem)->radius = -TOARC(newelem)->radius;
+ break;
+ case SPLINE:
+ reversepoints(TOSPLINE(newelem)->ctrl, 4);
+ calcspline(TOSPLINE(newelem));
+ break;
+ }
+ }
+
+ /* decompose arcs into bezier curves */
+ if (ELEMENTTYPE(*newelem) == ARC)
+ decomposearc(*newpath);
+ }
+
+ /* delete the old elements from the list */
+
+ register_for_undo(XCF_Join, UNDO_MORE, areawin->topinstance, *newpath);
+
+ delobj = delete_element(areawin->topinstance, scount, numpolys, NORMAL);
+
+ register_for_undo(XCF_Delete, UNDO_DONE, areawin->topinstance,
+ delobj, NORMAL);
+
+ /* Remove the path parts from the selection list and add the path */
+ clearselects();
+ selectobj = allocselect();
+ for (pgen = topobject->plist; pgen < topobject->plist + topobject->parts;
+ pgen++) {
+ if ((TOPATH(pgen)) == (*newpath)) {
+ *selectobj = (short)(pgen - topobject->plist);
+ break;
+ }
+ }
+ }
+
+ /* clean up */
+
+ incr_changes(topobject);
+ /* Do not clear the selection, to be consistent with all the */
+ /* other actions that clear only when something has not been */
+ /* preselected before the action. Elements must be selected */
+ /* prior to the "join" action, by necessity. */
+ free(scount);
+ free(order);
+ free(direc);
+}
+
+/*----------------------------------------------*/
+/* Add a new point to a polygon */
+/*----------------------------------------------*/
+
+void poly_add_point(polyptr thispoly, XPoint *newpoint) {
+ XPoint *tpoint;
+
+ thispoly->number++;
+ thispoly->points = (XPoint *)realloc(thispoly->points,
+ thispoly->number * sizeof(XPoint));
+ tpoint = thispoly->points + thispoly->number - 1;
+ tpoint->x = newpoint->x;
+ tpoint->y = newpoint->y;
+}
+
+/*-------------------------------------------------*/
+/* ButtonPress handler while a wire is being drawn */
+/*-------------------------------------------------*/
+
+void wire_op(int op, int x, int y)
+{
+ XPoint userpt, *tpoint;
+ polyptr newwire;
+
+ snap(x, y, &userpt);
+
+ newwire = TOPOLY(EDITPART);
+
+ /* This undraws the wire */
+ UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth);
+
+ if (areawin->attachto >= 0) {
+ XPoint apos;
+ findattach(&apos, NULL, &userpt);
+ userpt = apos;
+ areawin->attachto = -1;
+ }
+ else {
+ if (areawin->manhatn) manhattanize(&userpt, newwire, -1, TRUE);
+ }
+
+ tpoint = newwire->points + newwire->number - 1;
+ tpoint->x = userpt.x;
+ tpoint->y = userpt.y;
+
+ /* cancel wire operation completely */
+ if (op == XCF_Cancel) {
+ free(newwire->points);
+ free(newwire);
+ newwire = NULL;
+ eventmode = NORMAL_MODE;
+ topobject->parts--;
+ }
+
+ /* back up one point; prevent length zero wires */
+ else if ((op == XCF_Cancel_Last) || ((tpoint - 1)->x == userpt.x &&
+ (tpoint - 1)->y == userpt.y)) {
+ if (newwire->number <= 2) {
+ free(newwire->points);
+ free(newwire);
+ newwire = NULL;
+ eventmode = NORMAL_MODE;
+ topobject->parts--;
+ }
+ else {
+ if (--newwire->number == 2) newwire->style = UNCLOSED |
+ (areawin->style & (DASHED | DOTTED));
+ }
+ }
+
+ if (newwire && (op == XCF_Wire || op == XCF_Continue_Element)) {
+ if (newwire->number == 2)
+ newwire->style = areawin->style;
+ poly_add_point(newwire, &userpt);
+ }
+ else if ((newwire == NULL) || op == XCF_Finish_Element || op == XCF_Cancel) {
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackwire, NULL);
+ }
+
+ if (newwire) {
+ if (op == XCF_Finish_Element) {
+
+ /* If the last points are the same, remove all redundant ones. */
+ /* This avoids the problem of extra points when people do left */
+ /* click followed by middle click to finish (the redundant way */
+ /* a lot of drawing programs work). */
+
+ XPoint *t2pt;
+ while (newwire->number > 2) {
+ tpoint = newwire->points + newwire->number - 1;
+ t2pt = newwire->points + newwire->number - 2;
+ if (tpoint->x != t2pt->x || tpoint->y != t2pt->y)
+ break;
+ newwire->number--;
+ }
+
+ XcSetFunction(GXcopy);
+ XcTopSetForeground(newwire->color);
+ incr_changes(topobject);
+ if (!nonnetwork(newwire)) invalidate_netlist(topobject);
+ register_for_undo(XCF_Wire, UNDO_MORE, areawin->topinstance, newwire);
+ }
+ UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth);
+ if (op == XCF_Cancel_Last)
+ checkwarp(newwire->points + newwire->number - 1);
+ }
+
+ if (op == XCF_Finish_Element) {
+ eventmode = NORMAL_MODE;
+ singlebbox(EDITPART);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/events.c b/events.c
new file mode 100644
index 0000000..75edfd7
--- /dev/null
+++ b/events.c
@@ -0,0 +1,6827 @@
+/*-------------------------------------------------------------------------*/
+/* events.c --- xcircuit routines handling Xevents and Callbacks */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/13/93 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#define XK_MISCELLANY
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+#else
+#ifdef TCL_WRAPPER
+#define XK_MISCELLANY
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+#endif
+#endif
+
+#ifdef OPENGL
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif /* OPENGL */
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+#define HOLD_MASK (Mod4Mask << 16)
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*-------------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*-------------------------------------------------------------------------*/
+
+extern XtAppContext app;
+extern Display *dpy;
+extern int *appcolors;
+extern Cursor appcursors[NUM_CURSORS];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern ApplicationData appdata;
+extern short popups;
+extern int pressmode;
+extern xcWidget message2, top;
+extern char _STR[150], _STR2[250];
+extern short beeper;
+extern double saveratio;
+extern u_char texttype;
+extern aliasptr aliastop;
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#else
+extern short help_up;
+#endif
+
+/* double buffer */
+#ifdef DOUBLEBUFFER
+Pixmap dbuf = (Pixmap)NULL;
+#endif
+
+#ifdef OPENGL
+extern GLXContext grXcontext;
+#endif
+
+Boolean was_preselected;
+
+/*----------------------------------------------------------------------------*/
+/* Edit Object pushing and popping. */
+/*----------------------------------------------------------------------------*/
+
+Boolean recursefind(objectptr parent, objectptr suspect)
+{
+ genericptr *shell;
+
+ if (parent == suspect) return True;
+
+ for (shell = parent->plist; shell < parent->plist + parent->parts; shell++)
+ if (IS_OBJINST(*shell))
+ if (recursefind(TOOBJINST(shell)->thisobject, suspect)) return True;
+
+ return False;
+}
+
+/*--------------------------------------------------------------*/
+/* Transfer objects in the select list to the current object */
+/* (but disallow infinitely recursive loops!) */
+/*--------------------------------------------------------------*/
+/* IMPORTANT: delete_for_xfer() MUST be executed prior to */
+/* calling transferselects(), so that the deleted elements are */
+/* in an object saved in areawin->editstack. */
+/*--------------------------------------------------------------*/
+
+void transferselects()
+{
+ short locselects;
+ objinstptr tobj;
+ XPoint newpos;
+
+ if (areawin->editstack->parts == 0) return;
+
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == UNDO_MODE || eventmode == CATMOVE_MODE) {
+ short ps = topobject->parts;
+
+ freeselects();
+
+ locselects = areawin->editstack->parts;
+ areawin->selectlist = xc_undelete(areawin->topinstance,
+ areawin->editstack, (short)NORMAL, (short *)NULL);
+ areawin->selects = locselects;
+
+ /* Move all selected items to the cursor position */
+ newpos = UGetCursor();
+ drag((int)newpos.x, (int)newpos.y);
+
+ /* check to make sure this object is not the current object */
+ /* or one of its direct ancestors, else an infinite loop results. */
+
+ for (ps = 0; ps < topobject->parts; ps++) {
+ if (IS_OBJINST(*(topobject->plist + ps))) {
+ tobj = TOOBJINST(topobject->plist + ps);
+ if (recursefind(tobj->thisobject, topobject)) {
+ Wprintf("Attempt to place object inside of itself");
+ delete_noundo(NORMAL);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* Make a new matrix corresponding to the current position and scale */
+/*-------------------------------------------------------------------*/
+
+void newmatrix()
+{
+ if (DCTM == NULL) {
+ DCTM = (Matrixptr)malloc(sizeof(Matrix));
+ DCTM->nextmatrix = NULL;
+ }
+ UResetCTM(DCTM);
+ UMakeWCTM(DCTM);
+}
+
+/*-------------------------------------------------------*/
+/* set the viewscale variable to the proper address */
+/*-------------------------------------------------------*/
+
+void setpage(Boolean killselects)
+{
+ areawin->vscale = topobject->viewscale;
+ areawin->pcorner = topobject->pcorner;
+ newmatrix();
+
+ if (killselects) clearselects();
+
+#ifdef TCL_WRAPPER
+ if (xobjs.suspend < 0)
+ XcInternalTagCall(xcinterp, 2, "page", "goto");
+#endif
+}
+
+/*-------------------------------------------------------*/
+/* switch to a new page */
+/*-------------------------------------------------------*/
+
+int changepage(short pagenumber)
+{
+ short npage;
+ objectptr pageobj;
+ u_char undo_type;
+
+ /* to add to existing number of top level pages. . . */
+
+ if (pagenumber == 255) {
+ if (xobjs.pages == 255) {
+ Wprintf("Out of available pages!");
+ return -1;
+ }
+ else pagenumber = xobjs.pages;
+ }
+
+ if (pagenumber >= xobjs.pages) {
+
+ xobjs.pagelist = (Pagedata **)realloc(xobjs.pagelist, (pagenumber + 1)
+ * sizeof(Pagedata *));
+ xobjs.pagelist[pagenumber] = (Pagedata *)malloc(sizeof(Pagedata));
+ xobjs.pagelist[pagenumber]->filename = NULL;
+ xobjs.pagelist[pagenumber]->background.name = NULL;
+ xobjs.pagelist[pagenumber]->pageinst = NULL;
+
+ // If we skipped ahead to pagenumber, fill in the pages in between
+ for (npage = xobjs.pages; npage < pagenumber; npage++) {
+ xobjs.pagelist[npage] = (Pagedata *)malloc(sizeof(Pagedata));
+ xobjs.pagelist[npage]->pageinst = NULL;
+ }
+
+ xobjs.pages = pagenumber + 1;
+ makepagebutton();
+ }
+
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE || eventmode == UNDO_MODE) {
+ delete_for_xfer(NORMAL, areawin->selectlist, areawin->selects);
+ undo_type = UNDO_MORE;
+ }
+ else {
+ clearselects();
+ undo_type = UNDO_DONE;
+ }
+ if (areawin->page != pagenumber)
+ register_for_undo(XCF_Page, undo_type, areawin->topinstance,
+ areawin->page, pagenumber);
+
+ if (eventmode != ASSOC_MODE) {
+ areawin->page = pagenumber;
+ free_stack(&areawin->stack);
+ }
+ if (xobjs.pagelist[pagenumber]->pageinst == NULL) {
+
+ /* initialize a new page */
+
+ pageobj = (objectptr) malloc (sizeof(object));
+ initmem(pageobj);
+ sprintf(pageobj->name, "Page %d", pagenumber + 1);
+
+ xobjs.pagelist[pagenumber]->pageinst = newpageinst(pageobj);
+ xobjs.pagelist[pagenumber]->filename = NULL;
+ xobjs.pagelist[pagenumber]->background.name = NULL;
+
+ pagereset(pagenumber);
+ }
+
+ /* Write back the current view parameters */
+ if (areawin->topinstance != NULL) {
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ }
+
+ areawin->topinstance = xobjs.pagelist[pagenumber]->pageinst;
+
+ setpage(TRUE);
+
+ return 0;
+}
+
+/*-------------------------------------------------------*/
+/* switch to a new page and redisplay */
+/*-------------------------------------------------------*/
+
+void newpage(short pagenumber)
+{
+ switch (eventmode) {
+ case CATALOG_MODE:
+ eventmode = NORMAL_MODE;
+ catreturn();
+ break;
+
+ case NORMAL_MODE: case COPY_MODE: case MOVE_MODE: case UNDO_MODE:
+ if (changepage(pagenumber) >= 0) {
+ transferselects();
+ renderbackground();
+ refresh(NULL, NULL, NULL);
+
+ togglegrid((u_short)xobjs.pagelist[areawin->page]->coordstyle);
+ setsymschem();
+ }
+ break;
+
+ default:
+ Wprintf("Cannot switch pages from this mode");
+ break;
+ }
+}
+
+/*---------------------------------------*/
+/* Stack structure push and pop routines */
+/*---------------------------------------*/
+
+void push_stack(pushlistptr *stackroot, objinstptr thisinst, char *clientdata)
+{
+ pushlistptr newpush;
+
+ newpush = (pushlistptr)malloc(sizeof(pushlist));
+ newpush->next = *stackroot;
+ newpush->clientdata = clientdata;
+ newpush->thisinst = thisinst;
+ *stackroot = newpush;
+}
+
+/*----------------------------------------------------------*/
+
+void pop_stack(pushlistptr *stackroot)
+{
+ pushlistptr lastpush;
+
+ if (!(*stackroot)) {
+ Fprintf(stderr, "pop_genstack() Error: NULL instance stack!\n");
+ return;
+ }
+
+ lastpush = (*stackroot)->next;
+ free(*stackroot);
+ *stackroot = lastpush;
+}
+
+/*----------------------------------------------------------*/
+
+void free_stack(pushlistptr *stackroot)
+{
+ while ((*stackroot) != NULL)
+ pop_stack(stackroot);
+}
+
+/*------------------------------------------*/
+/* Push object onto hierarchy stack to edit */
+/*------------------------------------------*/
+
+void pushobject(objinstptr thisinst)
+{
+ short *selectobj, *savelist;
+ int saves;
+ u_char undo_type = UNDO_DONE;
+ objinstptr pushinst = thisinst;
+
+ savelist = NULL;
+ saves = 0;
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE) {
+ savelist = areawin->selectlist;
+ saves = areawin->selects;
+ areawin->selectlist = NULL;
+ areawin->selects = 0;
+ undo_type = UNDO_MORE;
+ }
+
+ if (pushinst == NULL) {
+ selectobj = areawin->selectlist;
+ if (areawin->selects == 0) {
+ disable_selects(topobject, savelist, saves);
+ selectobj = select_element(OBJINST);
+ enable_selects(topobject, savelist, saves);
+ }
+ if (areawin->selects == 0) {
+ Wprintf("No objects selected.");
+ return;
+ }
+ else if (areawin->selects > 1) {
+ Wprintf("Choose only one object.");
+ return;
+ }
+ else if (SELECTTYPE(selectobj) != OBJINST) {
+ Wprintf("Element to push must be an object.");
+ return;
+ }
+ else pushinst = SELTOOBJINST(selectobj);
+ }
+
+ if (savelist != NULL) {
+ delete_for_xfer(NORMAL, savelist, saves);
+ free(savelist);
+ }
+
+ register_for_undo(XCF_Push, undo_type, areawin->topinstance, pushinst);
+
+ /* save the address of the current object to the push stack */
+
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = pushinst;
+
+ /* move selected items to the new object */
+
+ setpage(TRUE);
+ transferselects();
+ refresh(NULL, NULL, NULL);
+ setsymschem();
+}
+
+/*--------------------------*/
+/* Pop edit hierarchy stack */
+/*--------------------------*/
+
+void popobject(xcWidget w, pointertype no_undo, caddr_t calldata)
+{
+ u_char undo_type = UNDO_DONE;
+
+ if (areawin->stack == NULL || (eventmode != NORMAL_MODE && eventmode != MOVE_MODE
+ && eventmode != COPY_MODE && eventmode != FONTCAT_MODE &&
+ eventmode != ASSOC_MODE && eventmode != UNDO_MODE &&
+ eventmode != EFONTCAT_MODE)) return;
+
+ if ((eventmode == MOVE_MODE || eventmode == COPY_MODE || eventmode == UNDO_MODE)
+ && ((areawin->stack->thisinst == xobjs.libtop[LIBRARY]) ||
+ (areawin->stack->thisinst == xobjs.libtop[USERLIB]))) return;
+
+ /* remove any selected items from the current object */
+
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE || eventmode == UNDO_MODE) {
+ undo_type = UNDO_MORE;
+ delete_for_xfer(NORMAL, areawin->selectlist, areawin->selects);
+ }
+ else if (eventmode != FONTCAT_MODE && eventmode != EFONTCAT_MODE)
+ unselect_all();
+
+ /* If coming from the library, don't register an undo action, because */
+ /* it has already been registered as type XCF_Library_Pop. */
+
+ if (no_undo == (pointertype)0)
+ register_for_undo(XCF_Pop, undo_type, areawin->topinstance);
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = areawin->stack->thisinst;
+ pop_stack(&areawin->stack);
+
+ /* if new object is a library or PAGELIB, put back into CATALOG_MODE */
+
+ if (is_library(topobject) >= 0) eventmode = CATALOG_MODE;
+
+ /* move selected items to the new object */
+
+ if (eventmode == FONTCAT_MODE || eventmode == EFONTCAT_MODE)
+ setpage(False);
+ else {
+ setpage(True);
+ setsymschem();
+ if (eventmode != ASSOC_MODE)
+ transferselects();
+ }
+ refresh(NULL, NULL, NULL);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Destructive reset of entire object */
+/*-------------------------------------------------------------------------*/
+
+void resetbutton(xcWidget button, pointertype pageno, caddr_t calldata)
+{
+ short page;
+ objectptr pageobj;
+ objinstptr pageinst;
+
+ if (eventmode != NORMAL_MODE) return;
+
+ page = (pageno == (pointertype)0) ? areawin->page : (short)(pageno - 1);
+
+ pageinst = xobjs.pagelist[page]->pageinst;
+
+ if (pageinst == NULL) return; /* page already cleared */
+
+ pageobj = pageinst->thisobject;
+
+ /* Make sure this is a real top-level page */
+
+ if (is_page(topobject) < 0) {
+ if (pageno == (pointertype)0) {
+ Wprintf("Can only clear top-level pages!");
+ return;
+ }
+ else {
+ /* Make sure that we're not in the hierarchy of the page being deleted */
+ pushlistptr slist;
+ for (slist = areawin->stack; slist != NULL; slist = slist->next)
+ if (slist->thisinst->thisobject == pageobj) {
+ Wprintf("Can't delete the page while you're in its hierarchy!");
+ return;
+ }
+ }
+ }
+
+ /* Watch for pages which are linked by schematic/symbol. */
+
+ if (pageobj->symschem != NULL) {
+ Wprintf("Schematic association to object %s", pageobj->symschem->name);
+ return;
+ }
+
+ sprintf(pageobj->name, "Page %d", page + 1);
+ xobjs.pagelist[page]->filename = (char *)realloc(xobjs.pagelist[page]->filename,
+ (strlen(pageobj->name) + 1) * sizeof(char));
+ strcpy(xobjs.pagelist[page]->filename, pageobj->name);
+ reset(pageobj, NORMAL);
+ flush_undo_stack();
+
+ if (page == areawin->page) {
+ drawarea(areawin->area, NULL, NULL);
+ printname(pageobj);
+ renamepage(page);
+ Wprintf("Page cleared.");
+ }
+}
+
+/*------------------------------------------------------*/
+/* Redraw the horizontal scrollbar */
+/*------------------------------------------------------*/
+
+void drawhbar(xcWidget bar, caddr_t clientdata, caddr_t calldata)
+{
+ Window bwin;
+ float frac;
+ long rleft, rright, rmid;
+
+ if (!xcIsRealized(bar)) return;
+ if (xobjs.suspend >= 0) return;
+
+ bwin = xcWindow(bar);
+
+ if (topobject->bbox.width > 0) {
+ frac = (float) areawin->width / (float) topobject->bbox.width;
+ rleft = (long)(frac * (float)(areawin->pcorner.x
+ - topobject->bbox.lowerleft.x));
+ rright = rleft + (long)(frac * (float)areawin->width / areawin->vscale);
+ }
+ else {
+ rleft = 0L;
+ rright = (long)areawin->width;
+ }
+ rmid = (rright + rleft) >> 1;
+
+ if (rleft < 0) rleft = 0;
+ if (rright > areawin->width) rright = areawin->width;
+
+ XSetFunction(dpy, areawin->gc, GXcopy);
+ XSetForeground(dpy, areawin->gc, BARCOLOR);
+ if (rmid > 0 && rleft > 0)
+ XClearArea(dpy, bwin, 0, 0, (int)rleft, SBARSIZE, FALSE);
+ XFillRectangle(dpy, bwin, areawin->gc, (int)rleft + 1, 1,
+ (int)(rright - rleft), SBARSIZE - 1);
+ if (rright > rmid)
+ XClearArea(dpy, bwin, (int)rright + 1, 0, areawin->width
+ - (int)rright, SBARSIZE, FALSE);
+ XClearArea(dpy, bwin, (int)rmid - 1, 1, 3, SBARSIZE, FALSE);
+
+ XSetFunction(dpy, areawin->gc, areawin->gctype);
+ XSetForeground(dpy, areawin->gc, areawin->gccolor);
+}
+
+/*------------------------------------------------------*/
+/* Redraw the vertical scrollbar */
+/*------------------------------------------------------*/
+
+void drawvbar(xcWidget bar, caddr_t clientdata, caddr_t calldata)
+{
+ Window bwin = xcWindow(bar);
+ float frac;
+ long rtop, rbot, rmid;
+
+ if (!xcIsRealized(bar)) return;
+ if (xobjs.suspend >= 0) return;
+
+ if (topobject->bbox.height > 0) {
+ frac = (float)areawin->height / (float)topobject->bbox.height;
+ rbot = (long)(frac * (float)(topobject->bbox.lowerleft.y
+ - areawin->pcorner.y + topobject->bbox.height));
+ rtop = rbot - (long)(frac * (float)areawin->height / areawin->vscale);
+ }
+ else {
+ rbot = areawin->height;
+ rtop = 0;
+ }
+ rmid = (rtop + rbot) >> 1;
+
+ if (rtop < 0) rtop = 0;
+ if (rbot > areawin->height) rbot = areawin->height;
+
+ XSetFunction(dpy, areawin->gc, GXcopy);
+ XSetForeground(dpy, areawin->gc, BARCOLOR);
+ if (rmid > 0 && rtop > 0)
+ XClearArea(dpy, bwin, 0, 0, SBARSIZE, (int)rtop, FALSE);
+ XFillRectangle(dpy, bwin, areawin->gc, 0, (int)rtop + 2, SBARSIZE,
+ (int)(rbot - rtop));
+ if (rbot > rmid)
+ XClearArea(dpy, bwin, 0, (int)rbot + 1, SBARSIZE, areawin->height
+ - (int)rbot, FALSE);
+ XClearArea(dpy, bwin, 0, (int)rmid - 1, SBARSIZE, 3, FALSE);
+
+ XSetFunction(dpy, areawin->gc, areawin->gctype);
+ XSetForeground(dpy, areawin->gc, areawin->gccolor);
+}
+
+/*------------------------------------------------------*/
+/* Simultaneously scroll the screen and horizontal */
+/* bar when dragging the mouse in the scrollbar area */
+/*------------------------------------------------------*/
+
+void panhbar(xcWidget bar, caddr_t clientdata, XButtonEvent *event)
+{
+ long newx, newpx;
+ short savex = areawin->pcorner.x;
+
+ if (eventmode == SELAREA_MODE) return;
+
+ newx = (long)(event->x * ((float)topobject->bbox.width /
+ areawin->width) + topobject->bbox.lowerleft.x - 0.5 *
+ ((float)areawin->width / areawin->vscale));
+ areawin->pcorner.x = (short)newx;
+ drawhbar(bar, NULL, NULL);
+ areawin->pcorner.x = savex;
+
+#ifdef DOUBLEBUFFER
+ if ((newpx = (long)(newx - savex) * areawin->vscale) == 0) return;
+ SetFunction(dpy, areawin->gc, GXcopy);
+ if (newpx > 0) {
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, newpx, 0,
+ areawin->width - newpx, areawin->height, 0, 0);
+ XClearArea(dpy, areawin->window, areawin->width - newpx, 0, newpx,
+ areawin->height, FALSE);
+ }
+ else {
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, 0,
+ areawin->width + newpx, areawin->height, -newpx, 0);
+ XClearArea(dpy, areawin->window, 0, 0, -newpx, areawin->height, FALSE);
+ }
+#endif
+}
+
+/*------------------------------------------------------*/
+/* End the horizontal scroll and refresh entire screen */
+/*------------------------------------------------------*/
+
+void endhbar(xcWidget bar, caddr_t clientdata, XButtonEvent *event)
+{
+ long newx;
+ short savex = areawin->pcorner.x;
+
+ newx = (long)(event->x * ((float)topobject->bbox.width /
+ areawin->width) + topobject->bbox.lowerleft.x - 0.5 *
+ ((float)areawin->width / areawin->vscale));
+
+ areawin->pcorner.x = (short)newx;
+
+ if ((newx << 1) != (long)((short)(newx << 1)) || checkbounds() == -1) {
+ areawin->pcorner.x = savex;
+ Wprintf("Reached boundary: cannot pan further");
+ }
+ else
+ W3printf(" ");
+
+ areawin->lastbackground = NULL;
+ renderbackground();
+ drawhbar(bar, NULL, NULL);
+ drawarea(bar, NULL, NULL);
+}
+
+/*------------------------------------------------------*/
+/* Simultaneously scroll the screen and vertical */
+/* bar when dragging the mouse in the scrollbar area */
+/*------------------------------------------------------*/
+
+void panvbar(xcWidget bar, caddr_t clientdata, XButtonEvent *event)
+{
+ long newy, newpy;
+ short savey = areawin->pcorner.y;
+
+ if (eventmode == SELAREA_MODE) return;
+
+ newy = (int)((areawin->height - event->y) *
+ ((float)topobject->bbox.height / areawin->height) +
+ topobject->bbox.lowerleft.y - 0.5 * ((float)areawin->height /
+ areawin->vscale));
+ areawin->pcorner.y = (short)newy;
+ drawvbar(bar, NULL, NULL);
+ areawin->pcorner.y = savey;
+
+#ifdef DOUBLEBUFFER
+ if ((newpy = (long)(newy - savey) * areawin->vscale) == 0) return;
+ SetFunction(dpy, areawin->gc, GXcopy);
+ if (newpy > 0) {
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, 0,
+ areawin->width, areawin->height - newpy, 0, newpy);
+ XClearArea(dpy, areawin->window, 0, 0, areawin->width, newpy, FALSE);
+ }
+ else {
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, -newpy,
+ areawin->width, areawin->height + newpy, 0, 0);
+ XClearArea(dpy, areawin->window, 0, areawin->height + newpy,
+ areawin->width, -newpy, FALSE);
+ }
+#endif
+
+}
+
+/*------------------------------------------------------*/
+/* Pan the screen to follow the cursor position */
+/*------------------------------------------------------*/
+
+void trackpan(int x, int y)
+{
+ long newpx, newpy;
+ XPoint newpos;
+ short savey = areawin->pcorner.y;
+ short savex = areawin->pcorner.x;
+
+ newpos.x = areawin->origin.x - x;
+ newpos.y = y - areawin->origin.y;
+
+ areawin->pcorner.x += newpos.x / areawin->vscale;
+ areawin->pcorner.y += newpos.y / areawin->vscale;
+
+ drawhbar(areawin->scrollbarh, NULL, NULL);
+ drawvbar(areawin->scrollbarv, NULL, NULL);
+
+#ifdef DOUBLEBUFFER
+ newpx = (long)areawin->pcorner.x * areawin->vscale;
+ newpy = (long)areawin->pcorner.y * areawin->vscale;
+
+ SetFunction(dpy, areawin->gc, GXcopy);
+ /* To-do: Clear or repaint areas not in copy region */
+
+/*
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, 0,
+ areawin->width, areawin->height, newpx,
+ areawin->height - newpy);
+*/
+ drawarea(NULL, NULL, NULL);
+#endif
+
+ areawin->pcorner.x = savex;
+ areawin->pcorner.y = savey;
+
+}
+
+/*------------------------------------------------------*/
+/* End the vertical scroll and refresh entire screen */
+/*------------------------------------------------------*/
+
+void endvbar(xcWidget bar, caddr_t clientdata, XButtonEvent *event)
+{
+ long newy;
+ short savey = areawin->pcorner.y;
+
+ newy = (int)((areawin->height - event->y) *
+ ((float)topobject->bbox.height / areawin->height) +
+ topobject->bbox.lowerleft.y - 0.5 * ((float)areawin->height /
+ areawin->vscale));
+
+ areawin->pcorner.y = (short)newy;
+
+ if ((newy << 1) != (long)((short)(newy << 1)) || checkbounds() == -1) {
+ areawin->pcorner.y = savey;
+ Wprintf("Reached boundary: cannot pan further");
+ }
+ else
+ W3printf(" ");
+
+ areawin->lastbackground = NULL;
+ renderbackground();
+ drawvbar(bar, NULL, NULL);
+ drawarea(bar, NULL, NULL);
+}
+
+/*--------------------------------------------------------------------*/
+/* Zoom functions-- zoom box, zoom in, zoom out, and pan. */
+/*--------------------------------------------------------------------*/
+
+void postzoom()
+{
+ W3printf(" ");
+ areawin->lastbackground = NULL;
+ renderbackground();
+ newmatrix();
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoominbox(int x, int y)
+{
+ float savescale;
+ float delxscale, delyscale;
+ XPoint savell; /* ucenter, ncenter, (jdk)*/
+
+ savescale = areawin->vscale;
+ savell.x = areawin->pcorner.x;
+ savell.y = areawin->pcorner.y;
+
+ /* zoom-box function: corners are in areawin->save and areawin->origin */
+ /* select box has lower-left corner in .origin, upper-right in .save */
+ /* ignore if zoom box is size zero */
+
+ if (areawin->save.x == areawin->origin.x || areawin->save.y == areawin->origin.y) {
+ Wprintf("Zoom box of size zero: Ignoring.");
+ eventmode = NORMAL_MODE;
+ return;
+ }
+
+ /* determine whether x or y is limiting factor in zoom */
+ delxscale = (areawin->width / areawin->vscale) /
+ abs(areawin->save.x - areawin->origin.x);
+ delyscale = (areawin->height / areawin->vscale) /
+ abs(areawin->save.y - areawin->origin.y);
+ areawin->vscale *= min(delxscale, delyscale);
+
+ areawin->pcorner.x = min(areawin->origin.x, areawin->save.x) -
+ (areawin->width / areawin->vscale -
+ abs(areawin->save.x - areawin->origin.x)) / 2;
+ areawin->pcorner.y = min(areawin->origin.y, areawin->save.y) -
+ (areawin->height / areawin->vscale -
+ abs(areawin->save.y - areawin->origin.y)) / 2;
+ eventmode = NORMAL_MODE;
+
+ /* check for minimum scale */
+
+ if (checkbounds() == -1) {
+ areawin->pcorner.x = savell.x;
+ areawin->pcorner.y = savell.y;
+ areawin->vscale = savescale;
+ Wprintf("At minimum scale: cannot scale further");
+
+ /* this is a rare case where an object gets out-of-bounds */
+
+ if (checkbounds() == -1) {
+ if (beeper) XBell(dpy, 100);
+ Wprintf("Unable to scale: Delete out-of-bounds object!");
+ }
+ return;
+ }
+ postzoom();
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoomin(int x, int y)
+{
+ float savescale;
+ XPoint ucenter, ncenter, savell;
+
+ savescale = areawin->vscale;
+ savell.x = areawin->pcorner.x;
+ savell.y = areawin->pcorner.y;
+
+ window_to_user(areawin->width / 2, areawin->height / 2, &ucenter);
+ areawin->vscale *= areawin->zoomfactor;
+ window_to_user(areawin->width / 2, areawin->height / 2, &ncenter);
+ areawin->pcorner.x += (ucenter.x - ncenter.x);
+ areawin->pcorner.y += (ucenter.y - ncenter.y);
+
+ /* check for minimum scale */
+
+ if (checkbounds() == -1) {
+ areawin->pcorner.x = savell.x;
+ areawin->pcorner.y = savell.y;
+ areawin->vscale = savescale;
+ Wprintf("At minimum scale: cannot scale further");
+
+ /* this is a rare case where an object gets out-of-bounds */
+
+ if (checkbounds() == -1) {
+ if (beeper) XBell(dpy, 100);
+ Wprintf("Unable to scale: Delete out-of-bounds object!");
+ }
+ return;
+ }
+ else if (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == CATMOVE_MODE)
+ drag(x, y);
+
+ postzoom();
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoominrefresh(int x, int y)
+{
+ if (eventmode == SELAREA_MODE)
+ zoominbox(x, y);
+ else
+ zoomin(x, y);
+ refresh(NULL, NULL, NULL);
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoomoutbox(int x, int y)
+{
+ float savescale;
+ float delxscale, delyscale, scalefac;
+ XPoint savell; /* ucenter, ncenter, (jdk)*/
+ XlPoint newll;
+
+ savescale = areawin->vscale;
+ savell.x = areawin->pcorner.x;
+ savell.y = areawin->pcorner.y;
+
+ /* zoom-box function, analogous to that for zoom-in */
+ /* ignore if zoom box is size zero */
+
+ if (areawin->save.x == areawin->origin.x || areawin->save.y == areawin->origin.y) {
+ Wprintf("Zoom box of size zero: Ignoring.");
+ eventmode = NORMAL_MODE;
+ return;
+ }
+
+ /* determine whether x or y is limiting factor in zoom */
+ delxscale = abs(areawin->save.x - areawin->origin.x) /
+ (areawin->width / areawin->vscale);
+ delyscale = abs(areawin->save.y - areawin->origin.y) /
+ (areawin->height / areawin->vscale);
+ scalefac = min(delxscale, delyscale);
+ areawin->vscale *= scalefac;
+
+ /* compute lower-left corner of (reshaped) select box */
+ if (delxscale < delyscale) {
+ newll.y = min(areawin->save.y, areawin->origin.y);
+ newll.x = (areawin->save.x + areawin->origin.x
+ - (abs(areawin->save.y - areawin->origin.y) *
+ areawin->width / areawin->height)) / 2;
+ }
+ else {
+ newll.x = min(areawin->save.x, areawin->origin.x);
+ newll.y = (areawin->save.y + areawin->origin.y
+ - (abs(areawin->save.x - areawin->origin.x) *
+ areawin->height / areawin->width)) / 2;
+ }
+
+ /* extrapolate to find new lower-left corner of screen */
+ newll.x = areawin->pcorner.x - (int)((float)(newll.x -
+ areawin->pcorner.x) / scalefac);
+ newll.y = areawin->pcorner.y - (int)((float)(newll.y -
+ areawin->pcorner.y) / scalefac);
+
+ eventmode = NORMAL_MODE;
+ areawin->pcorner.x = (short)newll.x;
+ areawin->pcorner.y = (short)newll.y;
+
+ if ((newll.x << 1) != (long)(areawin->pcorner.x << 1) || (newll.y << 1)
+ != (long)(areawin->pcorner.y << 1) || checkbounds() == -1) {
+ areawin->vscale = savescale;
+ areawin->pcorner.x = savell.x;
+ areawin->pcorner.y = savell.y;
+ Wprintf("At maximum scale: cannot scale further.");
+ return;
+ }
+ postzoom();
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoomout(int x, int y)
+{
+ float savescale;
+ XPoint ucenter, ncenter, savell;
+ XlPoint newll;
+
+ savescale = areawin->vscale;
+ savell.x = areawin->pcorner.x;
+ savell.y = areawin->pcorner.y;
+
+ window_to_user(areawin->width / 2, areawin->height / 2, &ucenter);
+ areawin->vscale /= areawin->zoomfactor;
+ window_to_user(areawin->width / 2, areawin->height / 2, &ncenter);
+ newll.x = (long)areawin->pcorner.x + (long)(ucenter.x - ncenter.x);
+ newll.y = (long)areawin->pcorner.y + (long)(ucenter.y - ncenter.y);
+ areawin->pcorner.x = (short)newll.x;
+ areawin->pcorner.y = (short)newll.y;
+
+ if ((newll.x << 1) != (long)(areawin->pcorner.x << 1) || (newll.y << 1)
+ != (long)(areawin->pcorner.y << 1) || checkbounds() == -1) {
+ areawin->vscale = savescale;
+ areawin->pcorner.x = savell.x;
+ areawin->pcorner.y = savell.y;
+ Wprintf("At maximum scale: cannot scale further.");
+ return;
+ }
+ else if (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == CATMOVE_MODE)
+ drag(x, y);
+
+ postzoom();
+}
+
+/*--------------------------------------------------------------------*/
+
+void zoomoutrefresh(int x, int y)
+{
+ if (eventmode == SELAREA_MODE)
+ zoomoutbox(x, y);
+ else
+ zoomout(x, y);
+ refresh(NULL, NULL, NULL);
+}
+
+/*--------------------------------------*/
+/* Call to XWarpPointer */
+/*--------------------------------------*/
+
+void warppointer(int x, int y)
+{
+ XWarpPointer(dpy, None, areawin->window, 0, 0, 0, 0, x, y);
+}
+
+/*--------------------------------------------------------------*/
+/* ButtonPress handler during center pan */
+/* x and y are cursor coordinates. */
+/* If ptype is 1-4 (directional), then "value" is a fraction of */
+/* the screen to scroll. */
+/*--------------------------------------------------------------*/
+
+void panbutton(u_int ptype, int x, int y, float value)
+{
+ /* Window pwin; (jdk) */
+ int xpos, ypos, newllx, newlly;
+ XPoint savell; /* , newpos; (jdk)*/
+ Dimension hwidth = areawin->width >> 1, hheight = areawin->height >> 1;
+
+ savell.x = areawin->pcorner.x;
+ savell.y = areawin->pcorner.y;
+
+ switch(ptype) {
+ case 1:
+ xpos = hwidth - (hwidth * 2 * value);
+ ypos = hheight;
+ break;
+ case 2:
+ xpos = hwidth + (hwidth * 2 * value);
+ ypos = hheight;
+ break;
+ case 3:
+ xpos = hwidth;
+ ypos = hheight - (hheight * 2 * value);
+ break;
+ case 4:
+ xpos = hwidth;
+ ypos = hheight + (hheight * 2 * value);
+ break;
+ case 5:
+ xpos = x;
+ ypos = y;
+ break;
+ case 6: /* "pan follow" */
+ if (eventmode == PAN_MODE)
+ finish_op(XCF_Finish, x, y);
+ else if (eventmode == NORMAL_MODE) {
+ eventmode = PAN_MODE;
+ areawin->save.x = x;
+ areawin->save.y = y;
+ u2u_snap(&areawin->save);
+ areawin->origin = areawin->save;
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcAddEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask , False, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ }
+ return;
+ break;
+ default: /* "pan here" */
+ xpos = x;
+ ypos = y;
+ warppointer(hwidth, hheight);
+ break;
+ }
+
+ xpos -= hwidth;
+ ypos = hheight - ypos;
+
+ newllx = (int)areawin->pcorner.x + (int)((float)xpos / areawin->vscale);
+ newlly = (int)areawin->pcorner.y + (int)((float)ypos / areawin->vscale);
+
+ areawin->pcorner.x = (short) newllx;
+ areawin->pcorner.y = (short) newlly;
+
+ if ((newllx << 1) != (long)(areawin->pcorner.x << 1) || (newlly << 1)
+ != (long)(areawin->pcorner.y << 1) || checkbounds() == -1) {
+ areawin->pcorner.x = savell.x;
+ areawin->pcorner.x = savell.y;
+ Wprintf("Reached bounds: cannot pan further.");
+ return;
+ }
+ else if (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == CATMOVE_MODE)
+ drag(x, y);
+
+ postzoom();
+}
+
+/*--------------------------------------------------------------*/
+
+void panrefresh(u_int ptype, int x, int y, float value)
+{
+ panbutton(ptype, x, y, value);
+ refresh(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Check for out-of-bounds before warping pointer, and pan window */
+/* if necessary. */
+/*----------------------------------------------------------------*/
+
+void checkwarp(XPoint *userpt)
+{
+ XPoint wpoint;
+
+ user_to_window(*userpt, &wpoint);
+
+ if (wpoint.x < 0 || wpoint.y < 0 || wpoint.x > areawin->width ||
+ wpoint.y > areawin->height) {
+ panrefresh(5, wpoint.x, wpoint.y, 0);
+ wpoint.x = areawin->width >> 1;
+ wpoint.y = areawin->height >> 1;
+ /* snap(wpoint.x, wpoint.y, userpt); */
+ }
+ warppointer(wpoint.x, wpoint.y);
+}
+
+/*--------------------------------------------------------------*/
+/* Return a pointer to the element containing a reference point */
+/*--------------------------------------------------------------*/
+
+genericptr getsubpart(pathptr editpath, int *idx)
+{
+ pointselect *tmpptr = NULL;
+ genericptr *pgen;
+
+ if (idx) *idx = 0;
+
+ for (pgen = editpath->plist; pgen < editpath->plist + editpath->parts; pgen++) {
+ switch (ELEMENTTYPE(*pgen)) {
+ case POLYGON:
+ if (TOPOLY(pgen)->cycle != NULL) {
+ for (tmpptr = TOPOLY(pgen)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (tmpptr->flags & REFERENCE) return *pgen;
+ }
+ break;
+ case SPLINE:
+ if (TOSPLINE(pgen)->cycle != NULL) {
+ for (tmpptr = TOSPLINE(pgen)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (tmpptr->flags & REFERENCE) return *pgen;
+ }
+ break;
+ }
+ if (idx) (*idx)++;
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Return a pointer to the current reference point of an */
+/* edited element (polygon, spline, or path) */
+/*--------------------------------------------------------------*/
+
+pointselect *getrefpoint(genericptr genptr, XPoint **refpt)
+{
+ pointselect *tmpptr = NULL;
+ genericptr *pgen;
+
+ if (refpt) *refpt = NULL;
+ switch (genptr->type) {
+ case POLYGON:
+ if (((polyptr)genptr)->cycle != NULL) {
+ for (tmpptr = ((polyptr)genptr)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (!(tmpptr->flags & REFERENCE)) tmpptr = NULL;
+ else if (refpt) *refpt = ((polyptr)genptr)->points + tmpptr->number;
+ }
+ break;
+ case SPLINE:
+ if (((splineptr)genptr)->cycle != NULL) {
+ for (tmpptr = ((splineptr)genptr)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (!(tmpptr->flags & REFERENCE)) tmpptr = NULL;
+ else if (refpt) *refpt = &((splineptr)genptr)->ctrl[tmpptr->number];
+ }
+ break;
+ case PATH:
+ for (pgen = ((pathptr)genptr)->plist; pgen < ((pathptr)genptr)->plist +
+ ((pathptr)genptr)->parts; pgen++) {
+ if ((tmpptr = getrefpoint(*pgen, refpt)) != NULL)
+ return tmpptr;
+ }
+ break;
+ default:
+ tmpptr = NULL;
+ break;
+ }
+ return tmpptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Return next edit point on a polygon, arc, or spline. Do not */
+/* update the cycle of the element. */
+/*--------------------------------------------------------------*/
+
+int checkcycle(genericptr genptr, short dir)
+{
+ pointselect *tmpptr;
+ short tmppt, points;
+ genericptr *pgen;
+
+ switch (genptr->type) {
+ case POLYGON:
+ if (((polyptr)genptr)->cycle == NULL)
+ tmpptr = NULL;
+ else {
+ for (tmpptr = ((polyptr)genptr)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (!(tmpptr->flags & REFERENCE)) tmpptr = ((polyptr)genptr)->cycle;
+ }
+ tmppt = (tmpptr == NULL) ? -1 : tmpptr->number;
+ points = ((polyptr)genptr)->number;
+ break;
+ case SPLINE:
+ if (((splineptr)genptr)->cycle == NULL)
+ tmpptr = NULL;
+ else {
+ for (tmpptr = ((splineptr)genptr)->cycle;; tmpptr++) {
+ if (tmpptr->flags & REFERENCE) break;
+ if (tmpptr->flags & LASTENTRY) break;
+ }
+ if (!(tmpptr->flags & REFERENCE)) tmpptr = ((splineptr)genptr)->cycle;
+ }
+ tmppt = (tmpptr == NULL) ? -1 : tmpptr->number;
+ points = 4;
+ break;
+ case ARC:
+ tmpptr = ((arcptr)genptr)->cycle;
+ tmppt = (tmpptr == NULL) ? -1 : tmpptr->number;
+ points = 4;
+ break;
+ case PATH:
+ for (pgen = ((pathptr)genptr)->plist; pgen < ((pathptr)genptr)->plist +
+ ((pathptr)genptr)->parts; pgen++) {
+ if ((tmppt = checkcycle(*pgen, dir)) >= 0)
+ return tmppt;
+ }
+ break;
+ default:
+ tmppt = -1;
+ break;
+ }
+ if (tmppt >= 0) { /* Ignore nonexistent cycles */
+ tmppt += dir;
+ if (tmppt < 0) tmppt += points;
+ tmppt %= points;
+ }
+ return tmppt;
+}
+
+/*--------------------------------------------------------------*/
+/* Change to the next part of a path for editing */
+/* For now, |dir| is treated as 1 regardless of its value. */
+/*--------------------------------------------------------------*/
+
+void nextpathcycle(pathptr nextpath, short dir)
+{
+ genericptr ppart = getsubpart(nextpath, NULL);
+ genericptr *ggen;
+ XPoint *curpt;
+ polyptr thispoly;
+ splineptr thisspline;
+ pointselect *cptr;
+ short cycle, newcycle;
+
+ /* Simple cases---don't need to switch elements */
+
+ switch (ELEMENTTYPE(ppart)) {
+ case POLYGON:
+ thispoly = (polyptr)ppart;
+ cptr = thispoly->cycle;
+ if (cptr == NULL) return;
+ curpt = thispoly->points + cptr->number;
+ newcycle = checkcycle(ppart, dir);
+ advancecycle(&ppart, newcycle);
+ if (cptr->number < thispoly->number && cptr->number > 0) {
+ checkwarp(thispoly->points + cptr->number);
+ removeothercycles(nextpath, ppart);
+ updatepath(nextpath);
+ return;
+ }
+ break;
+ case SPLINE:
+ thisspline = (splineptr)ppart;
+ cptr = ((splineptr)ppart)->cycle;
+ if (cptr == NULL) return;
+ curpt = &thisspline->ctrl[cptr->number];
+ newcycle = checkcycle(ppart, dir);
+ advancecycle(&ppart, newcycle);
+ if (cptr->number < 4 && cptr->number > 0) {
+ checkwarp(&thisspline->ctrl[cptr->number]);
+ removeothercycles(nextpath, ppart);
+ updatepath(nextpath);
+ if (newcycle == 1 || newcycle == 2)
+ addanticycle(nextpath, thisspline, newcycle);
+ return;
+ }
+ break;
+ }
+
+ /* Moving on to the next element. . . */
+
+ /* If dir < 0, go to the penultimate cycle of the last part */
+ /* If dir > 0, go to the second cycle of the next part */
+
+ for (ggen = nextpath->plist; (*ggen != ppart) &&
+ (ggen < nextpath->plist + nextpath->parts); ggen++);
+
+ if (ggen == nextpath->plist + nextpath->parts) return; /* shouldn't happen! */
+
+ if (dir > 0)
+ ggen++;
+ else
+ ggen--;
+
+ if (ggen < nextpath->plist)
+ ggen = nextpath->plist + nextpath->parts - 1;
+ else if (ggen == nextpath->plist + nextpath->parts)
+ ggen = nextpath->plist;
+
+ removecycle((genericptr *)(&nextpath));
+
+ /* The next point to edit is the first point in the next segment */
+ /* that is not at the same position as the one we were last editing. */
+
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ thispoly = TOPOLY(ggen);
+ cycle = (dir > 0) ? 0 : thispoly->number - 1;
+ addcycle(ggen, cycle, 0);
+ makerefcycle(thispoly->cycle, cycle);
+ if ((thispoly->points + cycle)->x == curpt->x &&
+ (thispoly->points + cycle)->y == curpt->y) {
+ newcycle = checkcycle((genericptr)thispoly, 1);
+ advancecycle(ggen, newcycle);
+ cycle = newcycle;
+ }
+ checkwarp(thispoly->points + cycle);
+ break;
+ case SPLINE:
+ thisspline = TOSPLINE(ggen);
+ cycle = (dir > 0) ? 0 : 3;
+ addcycle(ggen, cycle, 0);
+ makerefcycle(thisspline->cycle, cycle);
+ if (thisspline->ctrl[cycle].x == curpt->x &&
+ thisspline->ctrl[cycle].y == curpt->y) {
+ newcycle = checkcycle((genericptr)thisspline, 1);
+ advancecycle(ggen, newcycle);
+ cycle = newcycle;
+ if (cycle == 1 || cycle == 2)
+ addanticycle(nextpath, thisspline, cycle);
+ }
+ checkwarp(&(thisspline->ctrl[cycle]));
+ break;
+ }
+ updatepath(nextpath);
+}
+
+/*--------------------------------------------------------------*/
+/* Change to next edit point on a polygon */
+/*--------------------------------------------------------------*/
+
+void nextpolycycle(polyptr *nextpoly, short dir)
+{
+ short newcycle;
+
+ newcycle = checkcycle((genericptr)(*nextpoly), dir);
+ advancecycle((genericptr *)nextpoly, newcycle);
+ findconstrained(*nextpoly);
+ printeditbindings();
+
+ newcycle = (*nextpoly)->cycle->number;
+ checkwarp((*nextpoly)->points + newcycle);
+}
+
+/*--------------------------------------------------------------*/
+/* Change to next edit cycle on a spline */
+/*--------------------------------------------------------------*/
+
+void nextsplinecycle(splineptr *nextspline, short dir)
+{
+ short newcycle;
+ newcycle = checkcycle((genericptr)(*nextspline), dir);
+ advancecycle((genericptr *)nextspline, newcycle);
+
+ if (newcycle == 1 || newcycle == 2)
+ Wprintf("Adjust control point");
+ else
+ Wprintf("Adjust endpoint position");
+
+ checkwarp(&(*nextspline)->ctrl[newcycle]);
+}
+
+/*--------------------------------------------------------------*/
+/* Warp pointer to the edit point on an arc. */
+/*--------------------------------------------------------------*/
+
+void warparccycle(arcptr nextarc, short cycle)
+{
+ XPoint curang;
+ double rad;
+
+ switch(cycle) {
+ case 0:
+ curang.x = nextarc->position.x + abs(nextarc->radius);
+ curang.y = nextarc->position.y;
+ if (abs(nextarc->radius) != nextarc->yaxis)
+ Wprintf("Adjust ellipse size");
+ else
+ Wprintf("Adjust arc radius");
+ break;
+ case 1:
+ rad = (double)(nextarc->angle1 * RADFAC);
+ curang.x = nextarc->position.x + abs(nextarc->radius) * cos(rad);
+ curang.y = nextarc->position.y + nextarc->yaxis * sin(rad);
+ Wprintf("Adjust arc endpoint");
+ break;
+ case 2:
+ rad = (double)(nextarc->angle2 * RADFAC);
+ curang.x = nextarc->position.x + abs(nextarc->radius) * cos(rad);
+ curang.y = nextarc->position.y + nextarc->yaxis * sin(rad);
+ Wprintf("Adjust arc endpoint");
+ break;
+ case 3:
+ curang.x = nextarc->position.x;
+ curang.y = nextarc->position.y + nextarc->yaxis;
+ Wprintf("Adjust ellipse minor axis");
+ break;
+ }
+ checkwarp(&curang);
+}
+
+/*--------------------------------------------------------------*/
+/* Change to next edit cycle on an arc */
+/*--------------------------------------------------------------*/
+
+void nextarccycle(arcptr *nextarc, short dir)
+{
+ short newcycle;
+
+ newcycle = checkcycle((genericptr)(*nextarc), dir);
+ advancecycle((genericptr *)nextarc, newcycle);
+ warparccycle(*nextarc, newcycle);
+}
+
+/*------------------------------------------------------*/
+/* Get a numerical response from the keyboard (0-9) */
+/*------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+short getkeynum()
+{
+ XEvent event;
+ XKeyEvent *keyevent = (XKeyEvent *)(&event);
+ KeySym keypressed;
+
+ for (;;) {
+ XNextEvent(dpy, &event);
+ if (event.type == KeyPress) break;
+ else xcDispatchEvent(&event);
+ }
+ XLookupString(keyevent, _STR, 150, &keypressed, NULL);
+ if (keypressed > XK_0 && keypressed <= XK_9)
+ return (short)(keypressed - XK_1);
+ else
+ return -1;
+}
+
+#endif
+
+/*--------------------------*/
+/* Register a "press" event */
+/*--------------------------*/
+
+#ifdef TCL_WRAPPER
+void makepress(ClientData clientdata)
+#else
+void makepress(XtPointer clientdata, xcIntervalId *id)
+#endif
+{
+ int keywstate = (int)((pointertype)clientdata);
+
+ /* Button/Key was pressed long enough to make a "press", not a "tap" */
+
+ areawin->time_id = 0;
+ pressmode = keywstate;
+ eventdispatch(keywstate | HOLD_MASK, areawin->save.x, areawin->save.y);
+}
+
+/*------------------------------------------------------*/
+/* Handle button events as if they were keyboard events */
+/*------------------------------------------------------*/
+
+void buttonhandler(xcWidget w, caddr_t clientdata, XButtonEvent *event)
+{
+ XKeyEvent *kevent = (XKeyEvent *)event;
+
+ if (event->type == ButtonPress)
+ kevent->type = KeyPress;
+ else
+ kevent->type = KeyRelease;
+
+ switch (event->button) {
+ case Button1:
+ kevent->state |= Button1Mask;
+ break;
+ case Button2:
+ kevent->state |= Button2Mask;
+ break;
+ case Button3:
+ kevent->state |= Button3Mask;
+ break;
+ case Button4:
+ kevent->state |= Button4Mask;
+ break;
+ case Button5:
+ kevent->state |= Button5Mask;
+ break;
+ }
+ keyhandler(w, clientdata, kevent);
+}
+
+/*--------------------------------------------------------------*/
+/* Edit operations specific to polygons (point manipulation) */
+/*--------------------------------------------------------------*/
+
+void poly_edit_op(int op)
+{
+ genericptr keygen = *(EDITPART);
+ polyptr lwire;
+ XPoint *lpoint;
+ short cycle;
+
+ if (IS_PATH(keygen))
+ keygen = getsubpart((pathptr)keygen, NULL);
+
+ switch(ELEMENTTYPE(keygen)) {
+ case POLYGON: {
+ lwire = (polyptr)keygen;
+
+ /* Remove a point from the polygon */
+ if (op == XCF_Edit_Delete) {
+ if (lwire->number < 3) return;
+ UDrawPolygon(lwire, xobjs.pagelist[areawin->page]->wirewidth);
+ if (lwire->number == 3 && !(lwire->style & UNCLOSED))
+ lwire->style |= UNCLOSED;
+ cycle = checkcycle((genericptr)lwire, 0);
+ lwire->number--;
+ for (lpoint = lwire->points + cycle; lpoint <
+ lwire->points + lwire->number; lpoint++)
+ *lpoint = *(lpoint + 1);
+ UDrawPolygon(lwire, xobjs.pagelist[areawin->page]->wirewidth);
+ nextpolycycle(&lwire, -1);
+ }
+
+ /* Add a point to the polygon */
+ else if (op == XCF_Edit_Insert || op == XCF_Edit_Append) {
+ UDrawPolygon(lwire, xobjs.pagelist[areawin->page]->wirewidth);
+ lwire->number++;
+ lwire->points = (XPoint *)realloc(lwire->points, lwire->number
+ * sizeof(XPoint));
+ cycle = checkcycle((genericptr)lwire, 0);
+ for (lpoint = lwire->points + lwire->number - 1; lpoint > lwire->
+ points + cycle; lpoint--)
+ *lpoint = *(lpoint - 1);
+ UDrawPolygon(lwire, xobjs.pagelist[areawin->page]->wirewidth);
+ if (op == XCF_Edit_Append)
+ nextpolycycle(&lwire, 1);
+ }
+
+ /* Parameterize the position of a polygon point */
+ else if (op == XCF_Edit_Param) {
+ cycle = checkcycle((genericptr)lwire, 0);
+ makenumericalp(&keygen, P_POSITION_X, NULL, cycle);
+ makenumericalp(&keygen, P_POSITION_Y, NULL, cycle);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Handle attachment of edited elements to nearby elements */
+/*----------------------------------------------------------------------*/
+
+void attach_to()
+{
+ /* Conditions: One element is selected, key "A" is pressed. */
+ /* Then there must exist a spline, polygon, arc, or label */
+ /* to attach to. */
+
+ if (areawin->selects <= 1) {
+ short *refsel;
+
+ if (areawin->attachto >= 0) {
+ areawin->attachto = -1; /* default value---no attachments */
+ Wprintf("Unconstrained moving");
+ }
+ else {
+ int select_prev;
+
+ select_prev = areawin->selects;
+ refsel = select_add_element(SPLINE|ARC|POLYGON|LABEL|OBJINST);
+ if ((refsel != NULL) && (areawin->selects > select_prev)) {
+
+ /* transfer refsel over to attachto */
+
+ areawin->attachto = *(refsel + areawin->selects - 1);
+ areawin->selects--;
+ if (areawin->selects == 0) freeselects();
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(SELTOCOLOR(refsel));
+ easydraw(areawin->attachto, DEFAULTCOLOR);
+
+ /* restore graphics state */
+ SetFunction(dpy, areawin->gc, areawin->gctype);
+ SetForeground(dpy, areawin->gc, areawin->gccolor);
+
+ Wprintf("Constrained attach");
+
+ /* Starting a new wire? */
+ if (eventmode == NORMAL_MODE) {
+ XPoint newpos, userpt;
+ userpt = UGetCursorPos();
+ findattach(&newpos, NULL, &userpt);
+ startwire(&newpos);
+ eventmode = WIRE_MODE;
+ areawin->attachto = -1;
+ }
+ }
+ else {
+ Wprintf("Nothing found to attach to");
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* This function returns TRUE if the indicated function is */
+/* compatible with the current eventmode; that is, whether */
+/* the function could ever be called from eventdispatch() */
+/* given the existing eventmode. */
+/* */
+/* Note that this function has to be carefully written or the */
+/* function dispatch mechanism can put xcircuit into a bad */
+/* state. */
+/*--------------------------------------------------------------*/
+
+Boolean compatible_function(int function)
+{
+ int r = FALSE;
+ char *funcname;
+
+ switch(function) {
+ case XCF_Text_Left: case XCF_Text_Right:
+ case XCF_Text_Home: case XCF_Text_End:
+ case XCF_Text_Return: case XCF_Text_Delete:
+ r = (eventmode == CATTEXT_MODE || eventmode == TEXT_MODE ||
+ eventmode == ETEXT_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Linebreak: case XCF_Halfspace:
+ case XCF_Quarterspace: case XCF_TabStop:
+ case XCF_TabForward: case XCF_TabBackward:
+ case XCF_Superscript: case XCF_Subscript:
+ case XCF_Normalscript: case XCF_Underline:
+ case XCF_Overline: case XCF_Font:
+ case XCF_Boldfont: case XCF_Italicfont:
+ case XCF_Normalfont: case XCF_ISO_Encoding:
+ case XCF_Special: case XCF_Text_Split:
+ case XCF_Text_Up: case XCF_Text_Down:
+ case XCF_Parameter:
+ r = (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Justify:
+ r = (eventmode == TEXT_MODE || eventmode == ETEXT_MODE ||
+ eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Edit_Delete: case XCF_Edit_Insert: case XCF_Edit_Append:
+ case XCF_Edit_Param:
+ r = (eventmode == EPOLY_MODE || eventmode == EPATH_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Edit_Next:
+ r = (eventmode == EPOLY_MODE || eventmode == EPATH_MODE ||
+ eventmode == EINST_MODE || eventmode == EARC_MODE ||
+ eventmode == ESPLINE_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Attach:
+ r = (eventmode == EPOLY_MODE || eventmode == EPATH_MODE ||
+ eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == WIRE_MODE || eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Rotate: case XCF_Flip_X:
+ case XCF_Flip_Y:
+ r = (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == NORMAL_MODE || eventmode == CATALOG_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Snap: case XCF_Swap:
+ r = (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Double_Snap: case XCF_Halve_Snap:
+ case XCF_SnapTo:
+ r = (eventmode == CATALOG_MODE || eventmode == CATTEXT_MODE ||
+ eventmode == ASSOC_MODE || eventmode == CATMOVE_MODE) ?
+ FALSE : TRUE;
+ break;
+
+ case XCF_Library_Pop:
+ r = (eventmode == CATALOG_MODE || eventmode == ASSOC_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Library_Edit: case XCF_Library_Delete:
+ case XCF_Library_Duplicate: case XCF_Library_Hide:
+ case XCF_Library_Virtual: case XCF_Library_Move:
+ case XCF_Library_Copy:
+ r = (eventmode == CATALOG_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Library_Directory:
+ r = (eventmode == CATALOG_MODE || eventmode == NORMAL_MODE ||
+ eventmode == ASSOC_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Next_Library:
+ r = (eventmode == CATALOG_MODE || eventmode == NORMAL_MODE ||
+ eventmode == ASSOC_MODE || eventmode == CATMOVE_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Select: case XCF_Exit:
+ r = (eventmode == CATALOG_MODE || eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Pop:
+ r = (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == CATALOG_MODE || eventmode == NORMAL_MODE ||
+ eventmode == ASSOC_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Push:
+ r = (eventmode == MOVE_MODE || eventmode == COPY_MODE ||
+ eventmode == CATALOG_MODE || eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_SelectBox: case XCF_Wire:
+ case XCF_Delete: case XCF_Rescale:
+ case XCF_Pin_Label: case XCF_Pin_Global:
+ case XCF_Info_Label: case XCF_Connectivity:
+ case XCF_Box: case XCF_Arc:
+ case XCF_Text: case XCF_Exchange:
+ case XCF_Copy: case XCF_Virtual:
+ case XCF_Page_Directory: case XCF_Join:
+ case XCF_Unjoin: case XCF_Spline:
+ case XCF_Edit: case XCF_Undo:
+ case XCF_Redo: case XCF_Select_Save:
+ case XCF_Unselect: case XCF_Dashed:
+ case XCF_Dotted: case XCF_Solid:
+ case XCF_Dot: case XCF_Write:
+ case XCF_Netlist: case XCF_Sim:
+ case XCF_SPICE: case XCF_SPICEflat:
+ case XCF_PCB: case XCF_Move:
+ r = (eventmode == NORMAL_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Nothing: case XCF_View:
+ case XCF_Redraw: case XCF_Zoom_In:
+ case XCF_Zoom_Out: case XCF_Pan:
+ case XCF_Page: case XCF_Help:
+ case XCF_Cancel: case XCF_Prompt:
+ r = TRUE;
+ break;
+
+ case XCF_Continue_Copy:
+ case XCF_Finish_Copy:
+ r = (eventmode == COPY_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Continue_Element:
+ case XCF_Finish_Element:
+ r = (eventmode == WIRE_MODE || eventmode == BOX_MODE ||
+ eventmode == ARC_MODE || eventmode == SPLINE_MODE ||
+ eventmode == EPATH_MODE || eventmode == EPOLY_MODE ||
+ eventmode == EARC_MODE || eventmode == ESPLINE_MODE ||
+ eventmode == MOVE_MODE || eventmode == CATMOVE_MODE ||
+ eventmode == EINST_MODE || eventmode == RESCALE_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Cancel_Last:
+ r = (eventmode == WIRE_MODE || eventmode == ARC_MODE ||
+ eventmode == SPLINE_MODE || eventmode == EPATH_MODE ||
+ eventmode == EPOLY_MODE || eventmode == EARC_MODE ||
+ eventmode == EINST_MODE || eventmode == ESPLINE_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ case XCF_Finish:
+ r = (eventmode == FONTCAT_MODE || eventmode == EFONTCAT_MODE ||
+ eventmode == ASSOC_MODE || eventmode == CATALOG_MODE ||
+ eventmode == CATTEXT_MODE || eventmode == MOVE_MODE ||
+ eventmode == RESCALE_MODE || eventmode == SELAREA_MODE ||
+ eventmode == PAN_MODE || eventmode == NORMAL_MODE ||
+ eventmode == CATMOVE_MODE) ?
+ TRUE : FALSE;
+ break;
+
+ default: /* Function type was not handled. */
+ funcname = func_to_string(function);
+ if (funcname == NULL)
+ Wprintf("Error: \"%s\" is not a known function!");
+ else
+ Wprintf("Error: Function type \"%s\" (%d) not handled by "
+ "compatible_function()", func_to_string(function),
+ function);
+ break;
+ }
+ return r;
+}
+
+/*----------------------------------------------------------------------*/
+/* Main event dispatch routine. Call one of the known routines based */
+/* on the key binding. Some handling is done by secondary dispatch */
+/* routines in other files; when this is done, the key binding is */
+/* determined here and the bound operation type passed to the secondary */
+/* dispatch routine. */
+/* */
+/* Return value: 0 if event was handled, -1 if not. */
+/*----------------------------------------------------------------------*/
+
+int eventdispatch(int keywstate, int x, int y)
+{
+ short value; /* For return values from boundfunction() */
+ int function; /* What function should be invoked */
+
+ /* Invalid key state returned from getkeysignature(); usually this */
+ /* means a modifier key pressed by itself. */
+
+ if (keywstate == -1) return -1;
+ function = boundfunction(areawin->area, keywstate, &value);
+
+ /* Check for ASCII or ISO-Latin1-9 characters in keywstate while in */
+ /* a text-entry state. Only the function XCF_Special is allowed in */
+ /* text-entry mode, because XCF_Special can be used to enter the */
+ /* character bound to the XCF_Special function. */
+
+ if (keywstate >= 32 && keywstate < 256) {
+ if (eventmode == CATTEXT_MODE || eventmode == TEXT_MODE ||
+ eventmode == ETEXT_MODE) {
+ if (function != XCF_Special)
+ return labeltext(keywstate, NULL);
+ else if (eventmode != CATTEXT_MODE) {
+ labelptr elabel = TOLABEL(EDITPART);
+ if (elabel->justify & LATEXLABEL)
+ return labeltext(keywstate, NULL);
+ }
+ }
+ }
+
+ if (function > -1)
+ return functiondispatch(function, value, x, y);
+ else {
+ char *keystring = key_to_string(keywstate);
+#ifdef HAVE_PYTHON
+ if (python_key_command(keywstate) < 0)
+#endif
+ Wprintf("Key \'%s\' is not bound to a macro", keystring);
+ free(keystring);
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Dispatch actions by function number. Note that the structure of */
+/* this function is closely tied to the routine compatible_function(). */
+/*----------------------------------------------------------------------*/
+
+int functiondispatch(int function, short value, int x, int y)
+{
+ int result = 0;
+
+ switch (eventmode) {
+ case MOVE_MODE:
+ case COPY_MODE:
+ snap(x, y, &areawin->save);
+ break;
+ case NORMAL_MODE:
+ window_to_user(x, y, &areawin->save);
+ break;
+ }
+
+ switch(function) {
+ case XCF_Page:
+ if (value < 0 || value > xobjs.pages)
+ Wprintf("Page %d out of range.", (int)value);
+ else
+ newpage(value - 1);
+ break;
+ case XCF_Justify:
+ rejustify(value);
+ break;
+ case XCF_Superscript:
+ labeltext(SUPERSCRIPT, (char *)1);
+ break;
+ case XCF_Subscript:
+ labeltext(SUBSCRIPT, (char *)1);
+ break;
+ case XCF_Normalscript:
+ labeltext(NORMALSCRIPT, (char *)1);
+ break;
+ case XCF_Font:
+ setfont(NULL, 1000, NULL);
+ break;
+ case XCF_Boldfont:
+ fontstyle(NULL, 1, NULL);
+ break;
+ case XCF_Italicfont:
+ fontstyle(NULL, 2, NULL);
+ break;
+ case XCF_Normalfont:
+ fontstyle(NULL, 0, NULL);
+ break;
+ case XCF_Underline:
+ labeltext(UNDERLINE, (char *)1);
+ break;
+ case XCF_Overline:
+ labeltext(OVERLINE, (char *)1);
+ break;
+ case XCF_ISO_Encoding:
+ fontencoding(NULL, 2, NULL);
+ break;
+ case XCF_Halfspace:
+ labeltext(HALFSPACE, (char *)1);
+ break;
+ case XCF_Quarterspace:
+ labeltext(QTRSPACE, (char *)1);
+ break;
+ case XCF_Special:
+ result = dospecial();
+ break;
+#ifndef TCL_WRAPPER
+ case XCF_Parameter:
+ insertparam();
+ break;
+#endif
+ case XCF_TabStop:
+ labeltext(TABSTOP, (char *)1);
+ break;
+ case XCF_TabForward:
+ labeltext(TABFORWARD, (char *)1);
+ break;
+ case XCF_TabBackward:
+ labeltext(TABBACKWARD, (char *)1);
+ break;
+ case XCF_Text_Return:
+ labeltext(TEXT_RETURN, (char *)1);
+ break;
+ case XCF_Text_Delete:
+ labeltext(TEXT_DELETE, (char *)1);
+ break;
+ case XCF_Text_Right:
+ labeltext(TEXT_RIGHT, (char *)1);
+ break;
+ case XCF_Text_Left:
+ labeltext(TEXT_LEFT, (char *)1);
+ break;
+ case XCF_Text_Up:
+ labeltext(TEXT_UP, (char *)1);
+ break;
+ case XCF_Text_Down:
+ labeltext(TEXT_DOWN, (char *)1);
+ break;
+ case XCF_Text_Split:
+ labeltext(TEXT_SPLIT, (char *)1);
+ break;
+ case XCF_Text_Home:
+ labeltext(TEXT_HOME, (char *)1);
+ break;
+ case XCF_Text_End:
+ labeltext(TEXT_END, (char *)1);
+ break;
+ case XCF_Linebreak:
+ labeltext(RETURN, (char *)1);
+ break;
+ case XCF_Edit_Param:
+ case XCF_Edit_Delete:
+ case XCF_Edit_Insert:
+ case XCF_Edit_Append:
+ poly_edit_op(function);
+ break;
+ case XCF_Edit_Next:
+ path_op(*(EDITPART), XCF_Continue_Element, x, y);
+ break;
+ case XCF_Attach:
+ attach_to();
+ break;
+ case XCF_Next_Library:
+ changecat();
+ break;
+ case XCF_Library_Directory:
+ startcatalog(NULL, LIBLIB, NULL);
+ break;
+ case XCF_Library_Edit:
+ window_to_user(x, y, &areawin->save);
+ unselect_all();
+ select_element(LABEL);
+ if (areawin->selects == 1)
+ edit(x, y);
+ break;
+ case XCF_Library_Delete:
+ catalog_op(XCF_Select, x, y);
+ catdelete();
+ break;
+ case XCF_Library_Duplicate:
+ catalog_op(XCF_Select, x, y);
+ copycat();
+ break;
+ case XCF_Library_Hide:
+ catalog_op(XCF_Select, x, y);
+ cathide();
+ break;
+ case XCF_Library_Virtual:
+ catalog_op(XCF_Select, x, y);
+ catvirtualcopy();
+ break;
+ case XCF_Page_Directory:
+ startcatalog(NULL, PAGELIB, NULL);
+ break;
+ case XCF_Library_Copy:
+ case XCF_Library_Pop:
+ catalog_op(function, x, y);
+ break;
+ case XCF_Virtual:
+ copyvirtual();
+ break;
+ case XCF_Help:
+ starthelp(NULL, NULL, NULL);
+ break;
+ case XCF_Redraw:
+ drawarea(NULL, NULL, NULL);
+ break;
+ case XCF_View:
+ zoomview(NULL, NULL, NULL);
+ break;
+ case XCF_Zoom_In:
+ zoominrefresh(x, y);
+ break;
+ case XCF_Zoom_Out:
+ zoomoutrefresh(x, y);
+ break;
+ case XCF_Pan:
+ panrefresh(value, x, y, 0.3);
+ break;
+ case XCF_Double_Snap:
+ setsnap(1);
+ break;
+ case XCF_Halve_Snap:
+ setsnap(-1);
+ break;
+ case XCF_Write:
+#ifdef TCL_WRAPPER
+ Tcl_Eval(xcinterp, "xcircuit::promptsavepage");
+#else
+ outputpopup(NULL, NULL, NULL);
+#endif
+ break;
+ case XCF_Rotate:
+ elementrotate(value, &areawin->save);
+ break;
+ case XCF_Flip_X:
+ elementflip(&areawin->save);
+ break;
+ case XCF_Flip_Y:
+ elementvflip(&areawin->save);
+ break;
+ case XCF_Snap:
+ snapelement();
+ break;
+ case XCF_SnapTo:
+ if (areawin->snapto) {
+ areawin->snapto = False;
+ Wprintf("Snap-to off");
+ }
+ else {
+ areawin->snapto = True;
+ Wprintf("Snap-to on");
+ }
+ break;
+ case XCF_Pop:
+ if (eventmode == CATALOG_MODE || eventmode == ASSOC_MODE) {
+ eventmode = NORMAL_MODE;
+ catreturn();
+ }
+ else
+ popobject(NULL, 0, NULL);
+ break;
+ case XCF_Push:
+ if (eventmode == CATALOG_MODE) {
+ /* Don't allow push from library directory */
+ if ((areawin->topinstance != xobjs.libtop[LIBLIB])
+ && (areawin->topinstance != xobjs.libtop[PAGELIB])) {
+ window_to_user(x, y, &areawin->save);
+ eventmode = NORMAL_MODE;
+ pushobject(NULL);
+ }
+ }
+ else
+ pushobject(NULL);
+ break;
+ case XCF_Delete:
+ deletebutton(x, y);
+ break;
+ case XCF_Select:
+ if (eventmode == CATALOG_MODE)
+ catalog_op(function, x, y);
+ else
+ select_add_element(ALL_TYPES);
+ break;
+ case XCF_Box:
+ boxbutton(x, y);
+ break;
+ case XCF_Arc:
+ arcbutton(x, y);
+ break;
+ case XCF_Text:
+ eventmode = TEXT_MODE;
+ textbutton(NORMAL, x, y);
+ break;
+ case XCF_Exchange:
+ exchange();
+ break;
+ case XCF_Library_Move:
+ /* Don't allow from library directory. Then fall through to XCF_Move */
+ if (areawin->topinstance == xobjs.libtop[LIBLIB]) break;
+ case XCF_Move:
+ if (areawin->selects == 0) {
+ was_preselected = FALSE;
+ if (eventmode == CATALOG_MODE)
+ catalog_op(XCF_Select, x, y);
+ else
+ select_element(ALL_TYPES);
+ }
+ else was_preselected = TRUE;
+
+ if (areawin->selects > 0) {
+ eventmode = (eventmode == CATALOG_MODE) ? CATMOVE_MODE : MOVE_MODE;
+ u2u_snap(&areawin->save);
+ areawin->origin = areawin->save;
+ reset_cycles();
+ select_connected_pins();
+ XDefineCursor(dpy, areawin->window, ARROW);
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, (Tk_EventProc *)xctk_drag,
+ NULL);
+#endif
+ }
+ break;
+ case XCF_Join:
+ join();
+ break;
+ case XCF_Unjoin:
+ unjoin();
+ break;
+ case XCF_Spline:
+ splinebutton(x, y);
+ break;
+ case XCF_Edit:
+ edit(x, y);
+ break;
+ case XCF_Undo:
+ undo_action();
+ break;
+ case XCF_Redo:
+ redo_action();
+ break;
+ case XCF_Select_Save:
+#ifdef TCL_WRAPPER
+ Tcl_Eval(xcinterp, "xcircuit::promptmakeobject");
+#else
+ selectsave(NULL, NULL, NULL);
+#endif
+ break;
+ case XCF_Unselect:
+ select_add_element(-ALL_TYPES);
+ break;
+ case XCF_Dashed:
+ setelementstyle(NULL, DASHED, NOBORDER | DOTTED | DASHED);
+ break;
+ case XCF_Dotted:
+ setelementstyle(NULL, DOTTED, NOBORDER | DOTTED | DASHED);
+ break;
+ case XCF_Solid:
+ setelementstyle(NULL, NORMAL, NOBORDER | DOTTED | DASHED);
+ break;
+ case XCF_Prompt:
+ docommand();
+ break;
+ case XCF_Dot:
+ snap(x, y, &areawin->save);
+ drawdot(areawin->save.x, areawin->save.y);
+ drawarea(NULL, NULL, NULL);
+ break;
+ case XCF_Wire:
+ u2u_snap(&areawin->save);
+ startwire(&areawin->save);
+ eventmode = WIRE_MODE;
+ break;
+ case XCF_Nothing:
+ DoNothing(NULL, NULL, NULL);
+ break;
+ case XCF_Exit:
+ quitcheck(areawin->area, NULL, NULL);
+ break;
+ case XCF_Netlist:
+ callwritenet(NULL, 0, NULL);
+ break;
+ case XCF_Swap:
+ swapschem(0, -1, NULL);
+ break;
+ case XCF_Pin_Label:
+ eventmode = TEXT_MODE;
+ textbutton(LOCAL, x, y);
+ break;
+ case XCF_Pin_Global:
+ eventmode = TEXT_MODE;
+ textbutton(GLOBAL, x, y);
+ break;
+ case XCF_Info_Label:
+ eventmode = TEXT_MODE;
+ textbutton(INFO, x, y);
+ break;
+ case XCF_Rescale:
+ if (checkselect(LABEL | OBJINST | GRAPHIC) == TRUE) {
+ eventmode = RESCALE_MODE;
+ UDrawRescaleBox(&areawin->save);
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcAddEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ }
+ break;
+ case XCF_SelectBox:
+ startselect();
+ break;
+ case XCF_Connectivity:
+ connectivity(NULL, NULL, NULL);
+ break;
+ case XCF_Copy:
+ case XCF_Continue_Copy:
+ case XCF_Finish_Copy:
+ copy_op(function, x, y);
+ break;
+ case XCF_Continue_Element:
+ if (eventmode == CATMOVE_MODE || eventmode == MOVE_MODE ||
+ eventmode == RESCALE_MODE)
+ finish_op(XCF_Finish, x, y);
+ else
+ continue_op(function, x, y);
+ break;
+ case XCF_Finish_Element:
+ case XCF_Cancel_Last:
+ case XCF_Cancel:
+ finish_op(function, x, y);
+ break;
+ case XCF_Finish:
+ if (eventmode == CATALOG_MODE || eventmode == ASSOC_MODE)
+ catalog_op(XCF_Library_Pop, x, y);
+ else
+ finish_op(function, x, y);
+ break;
+ case XCF_Sim:
+ writenet(topobject, "flatsim", "sim");
+ break;
+ case XCF_SPICE:
+ writenet(topobject, "spice", "spc");
+ break;
+ case XCF_PCB:
+ writenet(topobject, "pcb", "pcbnet");
+ break;
+ case XCF_SPICEflat:
+ writenet(topobject, "flatspice", "fspc");
+ break;
+ case XCF_Graphic:
+ Wprintf("Action not handled");
+ result = -1;
+ break;
+ case XCF_Text_Delete_Param:
+ Wprintf("Action not handled");
+ result = -1;
+ break;
+ case XCF_ChangeStyle:
+ Wprintf("Action not handled");
+ result = -1;
+ break;
+ }
+
+ /* Ensure that we do not get stuck in suspend mode */
+ /* by removing the suspend state whenever a key is */
+ /* pressed. */
+
+ if (xobjs.suspend == 1) {
+ xobjs.suspend = -1;
+ refresh(NULL, NULL, NULL);
+ }
+ else if (xobjs.suspend != 2)
+ xobjs.suspend = -1;
+
+ return result;
+}
+
+/*------------------------------------------------------*/
+/* Get a canonical signature for a button/key event */
+/*------------------------------------------------------*/
+
+int getkeysignature(XKeyEvent *event)
+{
+ KeySym keypressed;
+ int keywstate; /* KeySym with prepended state information */
+
+#ifdef _MSC_VER
+ if (event->keycode == 0 && event->state == 0)
+ return -1;
+#endif
+ XLookupString(event, _STR, 150, &keypressed, NULL);
+
+ /* Ignore Shift, Control, Caps Lock, and Meta (Alt) keys */
+ /* when pressed alone. */
+
+ if (keypressed == XK_Control_L || keypressed == XK_Control_R ||
+ keypressed == XK_Alt_L || keypressed == XK_Alt_R ||
+ keypressed == XK_Caps_Lock || keypressed == XK_Shift_L ||
+ keypressed == XK_Shift_R)
+ return -1;
+
+ /* Only keep key state information pertaining to Shift, Caps Lock, */
+ /* Control, and Alt (Meta) */
+
+ keywstate = (keypressed & 0xffff);
+
+ /* Convert codes outside the character (0 - 255) range but within */
+ /* the ISO-Latin1,...,9 encoding scheme (256-5120). X11 has unique */
+ /* keysyms for each character, but the ISO-Latin encodings define */
+ /* mappings to the 8-bit (256) character set. */
+
+ if (keywstate >= 256 && keywstate < 5120)
+ keywstate = XKeysymToKeycode(dpy, (KeySym)keywstate);
+
+ /* ASCII values already come upper/lowercase; we only want to register */
+ /* a Shift key if it's a non-ASCII key or another modifier is in effect */
+
+ keywstate |= (((LockMask | ControlMask | Mod1Mask) & event->state) << 16);
+ if (keywstate > 255) keywstate |= ((ShiftMask & event->state) << 16);
+
+ /* Treat button events and key events in the same way by setting */
+ /* a key state for buttons */
+
+ if (keypressed == 0)
+ keywstate |= (((Button1Mask | Button2Mask | Button3Mask | Button4Mask |
+ Button5Mask | ShiftMask)
+ & event->state) << 16);
+
+ return keywstate;
+}
+
+/*------------------------*/
+/* Handle keyboard inputs */
+/*------------------------*/
+
+void keyhandler(xcWidget w, caddr_t clientdata, XKeyEvent *event)
+{
+ int keywstate; /* KeySym with prepended state information */
+ int j, func;
+
+#ifdef TCL_WRAPPER
+ if (popups > 0) return;
+#else
+ if (popups > 0 && help_up == 0) return;
+#endif
+
+ if ((event->type == KeyRelease) || (event->type == ButtonRelease)) {
+
+ /* Register a "tap" event if a key or button was released */
+ /* while a timeout event is pending. */
+
+ if (areawin->time_id != 0) {
+ xcRemoveTimeOut(areawin->time_id);
+ areawin->time_id = 0;
+ keywstate = getkeysignature(event);
+ eventdispatch(keywstate, areawin->save.x, areawin->save.y);
+ }
+ else {
+ keywstate = getkeysignature(event);
+ if ((pressmode != 0) && (keywstate == pressmode)) {
+ /* Events that require hold & drag (namely, MOVE_MODE) */
+ /* must be resolved here. Call finish_op() to ensure */
+ /* that we restore xcircuit to a state of sanity. */
+
+ finish_op(XCF_Finish, event->x, event->y);
+ pressmode = 0;
+ }
+ return; /* Ignore all other release events */
+ }
+ }
+
+ /* Check if any bindings match key/button "hold". If so, then start */
+ /* the timer and wait for key release or timeout. */
+
+ else {
+ keywstate = getkeysignature(event);
+ if ((keywstate != -1) && (xobjs.hold == TRUE)) {
+
+ /* Establish whether a HOLD modifier binding would apply in */
+ /* the current eventmode. If so, set the HOLD timer. */
+
+ j = 0;
+ func = boundfunction(areawin->area, keywstate | HOLD_MASK, NULL);
+ if (func != -1) {
+ areawin->save.x = event->x;
+ areawin->save.y = event->y;
+ areawin->time_id = xcAddTimeOut(app, PRESSTIME,
+ makepress, (ClientData)((pointertype)keywstate));
+ return;
+ }
+
+ }
+ eventdispatch(keywstate, event->x, event->y);
+ }
+}
+
+/*--------------------------------*/
+/* Set snap spacing from keyboard */
+/*--------------------------------*/
+
+void setsnap(short direction)
+{
+ float oldsnap = xobjs.pagelist[areawin->page]->snapspace;
+ char buffer[50];
+
+ if (direction > 0) xobjs.pagelist[areawin->page]->snapspace *= 2;
+ else {
+ if (oldsnap >= 2.0)
+ xobjs.pagelist[areawin->page]->snapspace /= 2;
+ else {
+ measurestr(xobjs.pagelist[areawin->page]->snapspace, buffer);
+ Wprintf("Snap space at minimum value of %s", buffer);
+ }
+ }
+ if (xobjs.pagelist[areawin->page]->snapspace != oldsnap) {
+ measurestr(xobjs.pagelist[areawin->page]->snapspace, buffer);
+ Wprintf("Snap spacing set to %s", buffer);
+ drawarea(NULL, NULL, NULL);
+ }
+}
+
+/*-----------------------------------------*/
+/* Reposition an object onto the snap grid */
+/*-----------------------------------------*/
+
+void snapelement()
+{
+ short *selectobj;
+ Boolean preselected;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (!checkselect(ALL_TYPES)) return;
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ easydraw(*selectobj, DOFORALL);
+ switch(SELECTTYPE(selectobj)) {
+ case OBJINST: {
+ objinstptr snapobj = SELTOOBJINST(selectobj);
+
+ u2u_snap(&snapobj->position);
+ } break;
+ case GRAPHIC: {
+ graphicptr snapg = SELTOGRAPHIC(selectobj);
+
+ u2u_snap(&snapg->position);
+ } break;
+ case LABEL: {
+ labelptr snaplabel = SELTOLABEL(selectobj);
+
+ u2u_snap(&snaplabel->position);
+ } break;
+ case POLYGON: {
+ polyptr snappoly = SELTOPOLY(selectobj);
+ pointlist snappoint;
+
+ for (snappoint = snappoly->points; snappoint < snappoly->points +
+ snappoly->number; snappoint++)
+ u2u_snap(snappoint);
+ } break;
+ case ARC: {
+ arcptr snaparc = SELTOARC(selectobj);
+
+ u2u_snap(&snaparc->position);
+ if (areawin->snapto) {
+ snaparc->radius = (snaparc->radius /
+ xobjs.pagelist[areawin->page]->snapspace) *
+ xobjs.pagelist[areawin->page]->snapspace;
+ snaparc->yaxis = (snaparc->yaxis /
+ xobjs.pagelist[areawin->page]->snapspace) *
+ xobjs.pagelist[areawin->page]->snapspace;
+ }
+ calcarc(snaparc);
+ } break;
+ case SPLINE: {
+ splineptr snapspline = SELTOSPLINE(selectobj);
+ short i;
+
+ for (i = 0; i < 4; i++)
+ u2u_snap(&snapspline->ctrl[i]);
+ calcspline(snapspline);
+ } break;
+ }
+ if (preselected || (eventmode != NORMAL_MODE)) {
+ SetForeground(dpy, areawin->gc, SELECTCOLOR);
+ easydraw(*selectobj, DOFORALL);
+ }
+ }
+ select_invalidate_netlist();
+ if (eventmode == NORMAL_MODE)
+ if (!preselected)
+ unselect_all();
+}
+
+/*----------------------------------------------*/
+/* Routines to print the cursor position */
+/*----------------------------------------------*/
+
+/*----------------------------------------------*/
+/* fast integer power-of-10 routine */
+/*----------------------------------------------*/
+
+int ipow10(int a)
+{
+ int i;
+ char istr[12];
+
+ switch (a) {
+ case 0: return 1; break;
+ case 1: return 10; break;
+ case 2: return 100; break;
+ case 3: return 1000; break;
+ default:
+ istr[0] = '1';
+ for (i = 1; i < a + 1; i++) istr[i] = '0';
+ istr[i] = '\0';
+ return atoi(istr);
+ break;
+ }
+}
+
+/*--------------------------------------------------*/
+/* find greatest common factor between two integers */
+/*--------------------------------------------------*/
+
+int calcgcf(int a, int b)
+{
+ register int mod;
+
+ if ((mod = a % b) == 0) return (b);
+ else return (calcgcf(b, mod));
+}
+
+/*--------------------------------------------------------------*/
+/* generate a fraction from a float, if possible */
+/* fraction returned as a string (must be allocated beforehand) */
+/*--------------------------------------------------------------*/
+
+void fraccalc(float xyval, char *fstr)
+{
+ short i, t, rept;
+ int ip, mant, divisor, denom, numer, rpart;
+ double fp;
+ char num[10], *nptr = &num[2], *sptr;
+
+ ip = (int)xyval;
+ fp = fabs(xyval - ip);
+
+ /* write fractional part and grab mantissa as integer */
+
+ sprintf(num, "%1.7f", fp);
+ num[8] = '\0'; /* no rounding up! */
+ sscanf(nptr, "%d", &mant);
+
+ if (mant != 0) { /* search for repeating substrings */
+ for (i = 1; i <= 3; i++) {
+ rept = 1;
+ nptr = &num[8] - i;
+ while ((sptr = nptr - rept * i) >= &num[2]) {
+ for (t = 0; t < i; t++)
+ if (*(sptr + t) != *(nptr + t)) break;
+ if (t != i) break;
+ else rept++;
+ }
+ if (rept > 1) break;
+ }
+ nptr = &num[8] - i;
+ sscanf(nptr, "%d", &rpart); /* rpart is repeating part of mantissa */
+ if (i > 3 || rpart == 0) { /* no repeat */
+ divisor = calcgcf(1000000, mant);
+ denom = 1000000 / divisor;
+ }
+ else { /* repeat */
+ int z, p, fd;
+
+ *nptr = '\0';
+ sscanf(&num[2], "%d", &z);
+ p = ipow10(i) - 1;
+ mant = z * p + rpart;
+ fd = ipow10(nptr - &num[2]) * p;
+
+ divisor = calcgcf(fd, mant);
+ denom = fd / divisor;
+ }
+ numer = mant / divisor;
+ if (denom > 1024)
+ sprintf(fstr, "%5.3f", xyval);
+ else if (ip == 0)
+ sprintf(fstr, "%hd/%hd", (xyval > 0) ? numer : -numer, denom);
+ else
+ sprintf(fstr, "%hd %hd/%hd", ip, numer, denom);
+ }
+ else sprintf(fstr, "%hd", ip);
+}
+
+/*------------------------------------------------------------------------------*/
+/* Print the position of the cursor in the upper right-hand message window */
+/*------------------------------------------------------------------------------*/
+
+void printpos(short xval, short yval)
+{
+ float f1, f2;
+ float oscale, iscale = (float)xobjs.pagelist[areawin->page]->drawingscale.y /
+ (float)xobjs.pagelist[areawin->page]->drawingscale.x;
+ int llen, lwid;
+ u_char wlflag = 0;
+ XPoint *tpoint, *npoint;
+ char *sptr;
+ short cycle;
+
+ /* For polygons, print the length (last line of a wire or polygon) or */
+ /* length and width (box only) */
+
+ if (eventmode == BOX_MODE || eventmode == EPOLY_MODE || eventmode == WIRE_MODE) {
+ polyptr lwire = (eventmode == BOX_MODE) ? TOPOLY(ENDPART) : TOPOLY(EDITPART);
+ if ((eventmode == EPOLY_MODE) && (lwire->number > 2)) {
+ /* sanity check on edit cycle */
+ cycle = lwire->cycle->number;
+ if (cycle < 0 || cycle >= lwire->number) {
+ advancecycle((genericptr *)(&lwire), 0);
+ cycle = 0;
+ }
+ tpoint = lwire->points + cycle;
+ npoint = lwire->points + checkcycle((genericptr)lwire, 1);
+ llen = wirelength(tpoint, npoint);
+ npoint = lwire->points + checkcycle((genericptr)lwire, -1);
+ lwid = wirelength(tpoint, npoint);
+ wlflag = 3;
+ if (lwire->style & UNCLOSED) { /* unclosed polys */
+ if (cycle == 0)
+ wlflag = 1;
+ else if (cycle == lwire->number - 1) {
+ wlflag = 1;
+ llen = lwid;
+ }
+ }
+ if ((npoint->y - tpoint->y) == 0) { /* swap width and length */
+ int tmp = lwid;
+ lwid = llen;
+ llen = tmp;
+ }
+ }
+ else if (eventmode == BOX_MODE) {
+ tpoint = lwire->points;
+ npoint = lwire->points + 1;
+ llen = wirelength(tpoint, npoint);
+ npoint = lwire->points + 3;
+ lwid = wirelength(tpoint, npoint);
+ if ((npoint->y - tpoint->y) == 0) { /* swap width and length */
+ int tmp = lwid;
+ lwid = llen;
+ llen = tmp;
+ }
+ wlflag = 3;
+ }
+ else {
+ tpoint = lwire->points + lwire->number - 1;
+ llen = wirelength(tpoint - 1, tpoint);
+ wlflag = 1;
+ }
+ }
+ else if (eventmode == ARC_MODE || eventmode == EARC_MODE) {
+ arcptr larc = (eventmode == ARC_MODE) ? TOARC(ENDPART) : TOARC(EDITPART);
+ llen = larc->radius;
+ if (abs(larc->radius) != larc->yaxis) {
+ lwid = larc->yaxis;
+ wlflag = 3;
+ }
+ else
+ wlflag = 1;
+ }
+
+ switch (xobjs.pagelist[areawin->page]->coordstyle) {
+ case INTERNAL:
+ sprintf(_STR, "%g, %g", xval * iscale, yval * iscale);
+ sptr = _STR + strlen(_STR);
+ if (wlflag) {
+ if (wlflag & 2)
+ sprintf(sptr, " (%g x %g)", llen * iscale, lwid * iscale);
+ else
+ sprintf(sptr, " (length %g)", llen * iscale);
+ }
+ break;
+ case DEC_INCH:
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ f1 = ((float)(xval) * iscale * oscale) / 72.0;
+ f2 = ((float)(yval) * iscale * oscale) / 72.0;
+ sprintf(_STR, "%5.3f, %5.3f in", f1, f2);
+ sptr = _STR + strlen(_STR);
+ if (wlflag) {
+ f1 = ((float)(llen) * iscale * oscale) / 72.0;
+ if (wlflag & 2) {
+ f2 = ((float)(lwid) * iscale * oscale) / 72.0;
+ sprintf(sptr, " (%5.3f x %5.3f in)", f1, f2);
+ }
+ else
+ sprintf(sptr, " (length %5.3f in)", f1);
+ }
+ break;
+ case FRAC_INCH: {
+ char fstr1[30], fstr2[30];
+
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ fraccalc((((float)(xval) * iscale * oscale) / 72.0), fstr1);
+ fraccalc((((float)(yval) * iscale * oscale) / 72.0), fstr2);
+ sprintf(_STR, "%s, %s in", fstr1, fstr2);
+ sptr = _STR + strlen(_STR);
+ if (wlflag) {
+ fraccalc((((float)(llen) * iscale * oscale) / 72.0), fstr1);
+ if (wlflag & 2) {
+ fraccalc((((float)(lwid) * iscale * oscale) / 72.0), fstr2);
+ sprintf(sptr, " (%s x %s in)", fstr1, fstr2);
+ }
+ else
+ sprintf(sptr, " (length %s in)", fstr1);
+ }
+ } break;
+ case CM:
+ oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
+ f1 = ((float)(xval) * iscale * oscale) / IN_CM_CONVERT;
+ f2 = ((float)(yval) * iscale * oscale) / IN_CM_CONVERT;
+ sprintf(_STR, "%5.3f, %5.3f cm", f1, f2);
+ sptr = _STR + strlen(_STR);
+ if (wlflag) {
+ f1 = ((float)(llen) * iscale * oscale) / IN_CM_CONVERT;
+ if (wlflag & 2) {
+ f2 = ((float)(lwid) * iscale * oscale) / IN_CM_CONVERT;
+ sprintf(sptr, " (%5.3f x %5.3f cm)", f1, f2);
+ }
+ else
+ sprintf(sptr, " (length %5.3f cm)", f1);
+ }
+ break;
+ }
+ W1printf(_STR);
+}
+
+/*---------------------------------------------------*/
+/* Find nearest point of intersection of the cursor */
+/* position to a wire and move there. */
+/*---------------------------------------------------*/
+
+void findwirex(XPoint *endpt1, XPoint *endpt2, XPoint *userpt,
+ XPoint *newpos, int *rot)
+{
+ long xsq, ysq, zsq;
+ float frac;
+
+ xsq = sqwirelen(endpt1, endpt2);
+ ysq = sqwirelen(endpt1, userpt);
+ zsq = sqwirelen(endpt2, userpt);
+ frac = 0.5 + (float)(ysq - zsq) / (float)(xsq << 1);
+ if (frac > 1) frac = 1;
+ else if (frac < 0) frac = 0;
+ newpos->x = endpt1->x + (int)((endpt2->x - endpt1->x) * frac);
+ newpos->y = endpt1->y + (int)((endpt2->y - endpt1->y) * frac);
+
+ *rot = 180 + (int)(INVRFAC * atan2((double)(endpt1->x -
+ endpt2->x), (double)(endpt1->y - endpt2->y)));
+
+ /* make adjustment for nearest-integer calculation */
+ /* ((*rot)++, (*rot)-- works if (360 / RSTEPS >= 2)) */ /* ? */
+
+ if (*rot > 0)
+ (*rot)++;
+ else if (*rot < 0)
+ (*rot)--;
+}
+
+/*----------------------------------------------------------------*/
+/* Find the closest point of attachment from the pointer position */
+/* to the "attachto" element. */
+/*----------------------------------------------------------------*/
+
+void findattach(XPoint *newpos, int *rot, XPoint *userpt)
+{
+ XPoint *endpt1, *endpt2;
+ float frac;
+ double tmpang;
+ int locrot = 0;
+
+ if (rot) locrot = *rot;
+
+ /* find point of intersection and slope */
+
+ if (SELECTTYPE(&areawin->attachto) == ARC) {
+ arcptr aarc = SELTOARC(&areawin->attachto);
+ float tmpdeg;
+ tmpang = atan2((double)(userpt->y - aarc->position.y) * (double)
+ (abs(aarc->radius)), (double)(userpt->x - aarc->position.x) *
+ (double)aarc->yaxis);
+
+ /* don't follow the arc beyond its endpoints */
+
+ tmpdeg = (float)(tmpang * INVRFAC);
+ if (tmpdeg < 0) tmpdeg += 360;
+ if (((aarc->angle2 > 360) && (tmpdeg > aarc->angle2 - 360) &&
+ (tmpdeg < aarc->angle1)) ||
+ ((aarc->angle1 < 0) && (tmpdeg > aarc->angle2) &&
+ (tmpdeg < aarc->angle1 + 360)) ||
+ ((aarc->angle1 >= 0) && (aarc->angle2 <= 360) && ((tmpdeg
+ > aarc->angle2) || (tmpdeg < aarc->angle1)))) {
+ float testd1 = aarc->angle1 - tmpdeg;
+ float testd2 = tmpdeg - aarc->angle2;
+ if (testd1 < 0) testd1 += 360;
+ if (testd2 < 0) testd2 += 360;
+
+ /* if arc is closed, attach to the line between the endpoints */
+
+ if (!(aarc->style & UNCLOSED)) {
+ XPoint end1, end2;
+ tmpang = (double) aarc->angle1 / INVRFAC;
+ end1.x = aarc->position.x + abs(aarc->radius) * cos(tmpang);
+ end1.y = aarc->position.y + aarc->yaxis * sin(tmpang);
+ tmpang = (double) aarc->angle2 / INVRFAC;
+ end2.x = aarc->position.x + abs(aarc->radius) * cos(tmpang);
+ end2.y = aarc->position.y + aarc->yaxis * sin(tmpang);
+ findwirex(&end1, &end2, userpt, newpos, &locrot);
+ if (rot) *rot = locrot;
+ return;
+ }
+ else
+ tmpang = (double)((testd1 < testd2) ? aarc->angle1 : aarc->angle2)
+ / INVRFAC;
+ }
+
+ /* get position in user coordinates nearest to the intersect pt */
+
+ newpos->x = aarc->position.x + abs(aarc->radius) * cos(tmpang);
+ newpos->y = aarc->position.y + aarc->yaxis * sin(tmpang);
+
+ /* rotation of object is normal to the curve of the ellipse */
+
+ if (rot) {
+ *rot = 90 - (int)(INVRFAC * tmpang);
+ if (*rot < 0) *rot += 360;
+ }
+ }
+ else if (SELECTTYPE(&areawin->attachto) == SPLINE) {
+ splineptr aspline = SELTOSPLINE(&areawin->attachto);
+ frac = findsplinemin(aspline, userpt);
+ findsplinepos(aspline, frac, newpos, &locrot);
+ if (rot) *rot = locrot;
+ }
+ else if (SELECTTYPE(&areawin->attachto) == OBJINST) {
+
+ objinstptr ainst = SELTOOBJINST(&areawin->attachto);
+ objectptr aobj = ainst->thisobject;
+ genericptr *ggen;
+ long testdist, mindist = 1e8;
+ XPoint mdpoint;
+
+ /* In case instance has no pin labels, we will attach to */
+ /* the instance's own origin. */
+
+ mdpoint.x = mdpoint.y = 0;
+ ReferencePosition(ainst, &mdpoint, newpos);
+
+ /* Find the nearest pin label in the object instance and attach to it */
+ for (ggen = aobj->plist; ggen < aobj->plist + aobj->parts; ggen++) {
+ if (ELEMENTTYPE(*ggen) == LABEL) {
+ labelptr alab = TOLABEL(ggen);
+ if (alab->pin == LOCAL || alab->pin == GLOBAL) {
+ ReferencePosition(ainst, &alab->position, &mdpoint);
+ testdist = sqwirelen(&mdpoint, userpt);
+ if (testdist < mindist) {
+ mindist = testdist;
+ *newpos = mdpoint;
+ }
+ }
+ }
+ }
+ }
+ else if (SELECTTYPE(&areawin->attachto) == LABEL) {
+ /* Only one choice: Attach to the label position */
+ labelptr alabel = SELTOLABEL(&areawin->attachto);
+ newpos->x = alabel->position.x;
+ newpos->y = alabel->position.y;
+ }
+ else if (SELECTTYPE(&areawin->attachto) == POLYGON) {
+ polyptr apoly = SELTOPOLY(&areawin->attachto);
+ XPoint *testpt, *minpt, *nxtpt;
+ long mindist = 1e8, testdist;
+ minpt = nxtpt = apoly->points; /* so variables aren't uninitialized */
+ for (testpt = apoly->points; testpt < apoly->points +
+ apoly->number - 1; testpt++) {
+ testdist = finddist(testpt, testpt + 1, userpt);
+ if (testdist < mindist) {
+ mindist = testdist;
+ minpt = testpt;
+ nxtpt = testpt + 1;
+ }
+ }
+ if (!(apoly->style & UNCLOSED)) {
+ testdist = finddist(testpt, apoly->points, userpt);
+ if (testdist < mindist) {
+ mindist = testdist;
+ minpt = testpt;
+ nxtpt = apoly->points;
+ }
+ }
+ endpt1 = minpt;
+ endpt2 = nxtpt;
+ findwirex(endpt1, endpt2, userpt, newpos, &locrot);
+ if (rot) *rot = locrot;
+ }
+}
+
+/*--------------------------------------------*/
+/* Find closest point in a path to the cursor */
+/*--------------------------------------------*/
+
+XPoint *pathclosepoint(pathptr dragpath, XPoint *newpos)
+{
+ XPoint *rpoint;
+ genericptr *cpoint;
+ short mpoint;
+ int mdist = 1000000, tdist;
+
+ for (cpoint = dragpath->plist; cpoint < dragpath->plist + dragpath->parts;
+ cpoint++) {
+ switch(ELEMENTTYPE(*cpoint)) {
+ case ARC:
+ tdist = wirelength(&(TOARC(cpoint)->position), newpos);
+ if (tdist < mdist) {
+ mdist = tdist;
+ rpoint = &(TOARC(cpoint)->position);
+ }
+ break;
+ case POLYGON:
+ mpoint = closepoint(TOPOLY(cpoint), newpos);
+ tdist = wirelength(TOPOLY(cpoint)->points + mpoint, newpos);
+ if (tdist < mdist) {
+ mdist = tdist;
+ rpoint = TOPOLY(cpoint)->points + mpoint;
+ }
+ break;
+ case SPLINE:
+ tdist = wirelength(&(TOSPLINE(cpoint)->ctrl[0]), newpos);
+ if (tdist < mdist) {
+ mdist = tdist;
+ rpoint = &(TOSPLINE(cpoint)->ctrl[0]);
+ }
+ tdist = wirelength(&(TOSPLINE(cpoint)->ctrl[3]), newpos);
+ if (tdist < mdist) {
+ mdist = tdist;
+ rpoint = &(TOSPLINE(cpoint)->ctrl[3]);
+ }
+ break;
+ }
+ }
+ return rpoint;
+}
+
+/*-------------------------------------------*/
+/* Drag a selected element around the screen */
+/*-------------------------------------------*/
+
+void drag(int x, int y)
+{
+ XEvent again;
+ Boolean eventcheck = False;
+ XPoint userpt;
+ short deltax, deltay;
+ int locx, locy;
+
+ locx = x;
+ locy = y;
+
+ /* flush out multiple pointermotion events from the event queue */
+ /* use only the last motion event */
+ while (XCheckWindowEvent(dpy, areawin->window, PointerMotionMask |
+ Button1MotionMask, &again) == True) eventcheck = True;
+ if (eventcheck) {
+ XButtonEvent *event = (XButtonEvent *)(&again);
+ locx = (int)event->x;
+ locy = (int)event->y;
+ }
+
+ /* Determine if this event is supposed to be handled by */
+ /* trackselarea(), or whether we should not be here at all */
+ /* (button press and mouse movement in an unsupported mode) */
+
+ if (eventmode == SELAREA_MODE) {
+ trackselarea();
+ return;
+ }
+ else if (eventmode == RESCALE_MODE) {
+ trackrescale();
+ return;
+ }
+ else if (eventmode == PAN_MODE) {
+ trackpan(locx, locy);
+ return;
+ }
+ else if (eventmode != CATMOVE_MODE && eventmode != MOVE_MODE
+ && eventmode != COPY_MODE)
+ return;
+
+ snap(locx, locy, &userpt);
+ deltax = userpt.x - areawin->save.x;
+ deltay = userpt.y - areawin->save.y;
+ if (deltax == 0 && deltay == 0) return;
+
+ areawin->save.x = userpt.x;
+ areawin->save.y = userpt.y;
+
+ /* set up the graphics state for moving a selected object */
+
+ XSetXORFg(SELECTCOLOR, BACKGROUND);
+ SetFunction(dpy, areawin->gc, GXxor);
+
+ placeselects(deltax, deltay, &userpt);
+
+ /* restore graphics state */
+
+ SetForeground(dpy, areawin->gc, areawin->gccolor);
+ SetFunction(dpy, areawin->gc, areawin->gctype);
+
+ /* print the position and other useful measurements */
+
+ printpos(userpt.x, userpt.y);
+}
+
+/*------------------------------------------------------*/
+/* Wrapper for drag() for xlib callback compatibility. */
+/*------------------------------------------------------*/
+
+void xlib_drag(xcWidget w, caddr_t clientdata, XEvent *event)
+{
+ XButtonEvent *bevent = (XButtonEvent *)event;
+ drag(bevent->x, bevent->y);
+}
+
+/*----------------------------------------------*/
+/* Rotate an element of a path */
+/*----------------------------------------------*/
+
+void elemrotate(genericptr *genobj, short direction, XPoint *position)
+{
+ XPoint negpt, *newpts = (XPoint *)NULL;
+
+ negpt.x = -position->x;
+ negpt.y = -position->y;
+
+ switch(ELEMENTTYPE(*genobj)) {
+ case(ARC):{
+ arcptr rotatearc = TOARC(genobj);
+ rotatearc->angle1 -= (float)(direction);
+ rotatearc->angle2 -= (float)(direction);
+ if (rotatearc->angle1 >= 360) {
+ rotatearc->angle1 -= 360;
+ rotatearc->angle2 -= 360;
+ }
+ else if (rotatearc->angle2 <= 0) {
+ rotatearc->angle1 += 360;
+ rotatearc->angle2 += 360;
+ }
+ newpts = (XPoint *)malloc(sizeof(XPoint));
+ UTransformPoints(&rotatearc->position, newpts, 1, negpt, 1.0, 0);
+ UTransformPoints(newpts, &rotatearc->position, 1, *position,
+ 1.0, direction);
+ calcarc(rotatearc);
+ }break;
+
+ case(SPLINE):{
+ splineptr rotatespline = TOSPLINE(genobj);
+ newpts = (XPoint *)malloc(4 * sizeof(XPoint));
+ UTransformPoints(rotatespline->ctrl, newpts, 4, negpt, 1.0, 0);
+ UTransformPoints(newpts, rotatespline->ctrl, 4, *position,
+ 1.0, direction);
+ calcspline(rotatespline);
+ }break;
+
+ case(POLYGON):{
+ polyptr rotatepoly = TOPOLY(genobj);
+ newpts = (XPoint *)malloc(rotatepoly->number * sizeof(XPoint));
+ UTransformPoints(rotatepoly->points, newpts, rotatepoly->number,
+ negpt, 1.0, 0);
+ UTransformPoints(newpts, rotatepoly->points, rotatepoly->number,
+ *position, 1.0, direction);
+ }break;
+ }
+ if (newpts) free(newpts);
+}
+
+/*------------------------------------------------------*/
+/* Rotate an element or group of elements */
+/* Objects and labels, if selected singly, rotate */
+/* about their position point. All other elements, */
+/* and groups, rotate about the cursor point. */
+/*------------------------------------------------------*/
+
+void elementrotate(short direction, XPoint *position)
+{
+ short *selectobj; /* , ld; (jdk) */
+ Boolean single = False;
+ Boolean need_refresh = False;
+ Boolean preselected;
+ XPoint newpt, negpt;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (!checkselect(ALL_TYPES)) return;
+ if (areawin->selects == 1) single = True;
+
+ negpt.x = -position->x;
+ negpt.y = -position->y;
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+
+ /* erase the element */
+ if (!need_refresh) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ easydraw(*selectobj, DOFORALL);
+ }
+
+ switch(SELECTTYPE(selectobj)) {
+
+ case(OBJINST):{
+ objinstptr rotateobj = SELTOOBJINST(selectobj);
+
+ if (is_library(topobject) >= 0 && !is_virtual(rotateobj)) break;
+ rotateobj->rotation += direction;
+ while (rotateobj->rotation >= 360) rotateobj->rotation -= 360;
+ while (rotateobj->rotation <= 0) rotateobj->rotation += 360;
+ if (!single) {
+ UTransformPoints(&rotateobj->position, &newpt, 1, negpt, 1.0, 0);
+ UTransformPoints(&newpt, &rotateobj->position, 1, *position,
+ 1.0, direction);
+ }
+ }break;
+
+ case(LABEL):{
+ labelptr rotatetext = SELTOLABEL(selectobj);
+
+ rotatetext->rotation += direction;
+ while (rotatetext->rotation >= 360) rotatetext->rotation -= 360;
+ while (rotatetext->rotation <= 0) rotatetext->rotation += 360;
+ if (!single) {
+ UTransformPoints(&rotatetext->position, &newpt, 1, negpt, 1.0, 0);
+ UTransformPoints(&newpt, &rotatetext->position, 1, *position,
+ 1.0, direction);
+ }
+ }break;
+
+ case(GRAPHIC):{
+ graphicptr rotateg = SELTOGRAPHIC(selectobj);
+
+ rotateg->rotation += direction;
+ while (rotateg->rotation >= 360) rotateg->rotation -= 360;
+ while (rotateg->rotation <= 0) rotateg->rotation += 360;
+ rotateg->valid = FALSE;
+ if (!single) {
+ UTransformPoints(&rotateg->position, &newpt, 1, negpt, 1.0, 0);
+ UTransformPoints(&newpt, &rotateg->position, 1, *position,
+ 1.0, direction);
+ }
+ need_refresh = True;
+ }break;
+
+ case POLYGON: case ARC: case SPLINE:{
+ genericptr *genpart = topobject->plist + *selectobj;
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ *genpart);
+ elemrotate(genpart, direction, position);
+ }break;
+
+ case PATH:{
+ genericptr *genpart;
+ pathptr rotatepath = SELTOPATH(selectobj);
+
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ rotatepath);
+ for (genpart = rotatepath->plist; genpart < rotatepath->plist
+ + rotatepath->parts; genpart++)
+ elemrotate(genpart, direction, position);
+ }break;
+ }
+
+ /* redisplay the element */
+ if (preselected || ((eventmode != NORMAL_MODE) && !need_refresh)) {
+ SetForeground(dpy, areawin->gc, SELECTCOLOR);
+ easydraw(*selectobj, DOFORALL);
+ }
+ }
+
+ /* This takes care of all selected instances and labels in one go, */
+ /* because we only need to know the origin and amount of rotation. */
+
+ if (eventmode != COPY_MODE)
+ register_for_undo(XCF_Rotate, UNDO_MORE, areawin->topinstance,
+ (eventmode == MOVE_MODE) ? &areawin->origin : position,
+ (int)direction);
+
+ /* New rule (6/15/07) to be applied generally: If objects were */
+ /* selected prior to calling elementrotate() and similar functions, */
+ /* leave them selected upon exit. Otherwise, deselect them. */
+
+ if (eventmode == NORMAL_MODE || eventmode == CATALOG_MODE)
+ if (!preselected)
+ unselect_all();
+
+ if (eventmode == CATALOG_MODE) {
+ int libnum;
+ if ((libnum = is_library(topobject)) >= 0) {
+ composelib(libnum + LIBRARY);
+ need_refresh = TRUE;
+ }
+ }
+ else {
+ pwriteback(areawin->topinstance);
+ calcbbox(areawin->topinstance);
+ }
+
+ if (need_refresh) drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------*/
+/* Rescale the current edit element to the */
+/* dimensions of the rescale box. */
+/*----------------------------------------------*/
+
+void elementrescale(float newscale)
+{
+ short *selectobj;
+ labelptr sclab;
+ objinstptr scinst;
+ graphicptr scgraph;
+ float oldsize;
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ switch (SELECTTYPE(selectobj)) {
+ case LABEL:
+ sclab = SELTOLABEL(selectobj);
+ oldsize = sclab->scale;
+ sclab->scale = newscale;
+ break;
+ case OBJINST:
+ scinst = SELTOOBJINST(selectobj);
+ oldsize = scinst->scale;
+ scinst->scale = newscale;
+ break;
+ case GRAPHIC:
+ scgraph = SELTOGRAPHIC(selectobj);
+ oldsize = scgraph->scale;
+ scgraph->scale = newscale;
+ break;
+ }
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(selectobj), (double)oldsize);
+ }
+ calcbbox(areawin->topinstance);
+}
+
+/*-------------------------------------------------*/
+/* Edit an element in an element-dependent fashion */
+/*-------------------------------------------------*/
+
+void edit(int x, int y)
+{
+ short *selectobj, saveselects;
+ Boolean preselected = False;
+
+ if (areawin->selects == 0) {
+ short savemode = eventmode;
+ eventmode = PENDING_MODE;
+ selectobj = select_element(ALL_TYPES);
+ eventmode = savemode;
+ }
+ else {
+ preselected = True;
+ selectobj = areawin->selectlist;
+ }
+ if (areawin->selects == 0)
+ return;
+ else if (areawin->selects != 1) { /* Multiple object edit */
+ int seltype, selnum;
+ short *selectlist, selrefno;
+
+ /* Find the closest part to use as a reference */
+ selnum = areawin->selects;
+ selectlist = areawin->selectlist;
+ areawin->selects = 0;
+ areawin->selectlist = NULL;
+ selectobj = select_element(ALL_TYPES);
+ if (selectobj != NULL)
+ selrefno = *selectobj;
+ else
+ selrefno = -1;
+ freeselects();
+ areawin->selects = selnum;
+ areawin->selectlist = selectlist;
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ if (*selectobj == selrefno) break;
+ }
+ if (selectobj == areawin->selectlist + areawin->selects) {
+ Wprintf("Put cursor close to the reference element.");
+ return;
+ }
+
+ /* Shuffle the reference element to the beginning of the select list */
+ *selectobj = *(areawin->selectlist);
+ *(areawin->selectlist) = selrefno;
+ selectobj = areawin->selectlist;
+ }
+
+ switch(SELECTTYPE(selectobj)) {
+ case LABEL: {
+ labelptr *lastlabel = (labelptr *)EDITPART;
+ short curfont;
+ XPoint tmppt;
+ TextExtents tmpext;
+
+ /* save the old string, including parameters */
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ *lastlabel);
+
+ /* fill any NULL instance parameters with the default value */
+ copyparams(areawin->topinstance, areawin->topinstance);
+
+ /* place text cursor line at point nearest the cursor */
+ /* unless textend is set. . . */
+
+ if (areawin->textend == 0) {
+ window_to_user(x, y, &areawin->save);
+ InvTransformPoints(&areawin->save, &tmppt, 1, (*lastlabel)->position,
+ (*lastlabel)->scale, (*lastlabel)->rotation);
+ tmpext = ULength(*lastlabel, areawin->topinstance, 0, NULL);
+ tmppt.x += ((*lastlabel)->justify & NOTLEFT ?
+ ((*lastlabel)->justify & RIGHT ? tmpext.maxwidth
+ : tmpext.maxwidth >> 1) : 0);
+ tmppt.y += ((*lastlabel)->justify & NOTBOTTOM ?
+ ((*lastlabel)->justify & TOP ? tmpext.ascent :
+ (tmpext.ascent + tmpext.base) >> 1) : tmpext.base);
+ if ((*lastlabel)->pin)
+ pinadjust((*lastlabel)->justify, &tmppt.x, NULL, -1);
+
+ // Where tbreak is passed to ULength, the character position,
+ // not the dimension, is held in tmpext.width field.
+ tmpext = ULength(*lastlabel, areawin->topinstance, 0, &tmppt);
+ areawin->textpos = tmpext.width;
+ }
+
+ /* find current font */
+
+ curfont = findcurfont(areawin->textpos, (*lastlabel)->string,
+ areawin->topinstance);
+
+ /* change menu buttons accordingly */
+
+ setfontmarks(curfont, (*lastlabel)->justify);
+
+ if (eventmode == CATALOG_MODE) {
+ /* CATTEXT_MODE may show an otherwise hidden library namespace */
+ undrawtext(*lastlabel);
+ eventmode = CATTEXT_MODE;
+ redrawtext(*lastlabel);
+ }
+ else eventmode = ETEXT_MODE;
+
+ UDrawTLine(*lastlabel);
+ XDefineCursor(dpy, areawin->window, TEXTPTR);
+
+ /* write the text at the bottom */
+
+ charreport(*lastlabel);
+
+ } break;
+
+ case POLYGON: case ARC: case SPLINE: case PATH:
+ window_to_user(x, y, &areawin->save);
+ /* Redraw without drawing selections */
+ saveselects = areawin->selects;
+ selectobj = areawin->selectlist;
+ areawin->selects = 0;
+ areawin->selectlist = NULL;
+ drawarea(NULL, NULL, NULL);
+ areawin->selectlist = selectobj;
+ areawin->selects = saveselects;
+
+ pathedit(*(EDITPART));
+ break;
+
+ case OBJINST: case GRAPHIC:
+ if (areawin->selects == 1)
+ unselect_all();
+ return;
+ }
+ XDefineCursor (dpy, areawin->window, EDCURSOR);
+}
+
+/*----------------------------------------------------------------------*/
+/* edit() routine for path-type elements (polygons, splines, arcs, and */
+/* paths) */
+/*----------------------------------------------------------------------*/
+
+void pathedit(genericptr editpart)
+{
+ splineptr lastspline = NULL;
+ pathptr lastpath;
+ polyptr lastpoly = NULL;
+ arcptr lastarc;
+ XPoint *savept;
+ short *eselect;
+ int cycle;
+ Boolean havecycle;
+
+ /* Find and set constrained edit points on all elements. Register */
+ /* each element with the undo mechanism. */
+
+ for (eselect = areawin->selectlist; eselect < areawin->selectlist +
+ areawin->selects; eselect++) {
+ switch (SELECTTYPE(eselect)) {
+ case POLYGON:
+ findconstrained(SELTOPOLY(eselect));
+ /* fall through */
+ default:
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(eselect));
+ break;
+ }
+ }
+
+ switch(ELEMENTTYPE(editpart)) {
+ case PATH: {
+ genericptr *ggen, *savegen = NULL;
+ int mincycle, dist, mindist = 1e6;
+
+ lastpath = (pathptr)editpart;
+ havecycle = (checkcycle(editpart, 0) >= 0) ? True : False;
+
+ /* determine which point of the path is closest to the cursor */
+ for (ggen = lastpath->plist; ggen < lastpath->plist + lastpath->parts;
+ ggen++) {
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ lastpoly = TOPOLY(ggen);
+ cycle = closepoint(lastpoly, &areawin->save);
+ dist = wirelength(lastpoly->points + cycle, &areawin->save);
+ break;
+ case SPLINE:
+ lastspline = TOSPLINE(ggen);
+ cycle = (wirelength(&lastspline->ctrl[0],
+ &areawin->save) < wirelength(&lastspline->ctrl[3],
+ &areawin->save)) ? 0 : 3;
+ dist = wirelength(&lastspline->ctrl[cycle], &areawin->save);
+ break;
+ }
+ if (dist < mindist) {
+ mindist = dist;
+ mincycle = cycle;
+ savegen = ggen;
+ }
+ }
+ if (savegen == NULL) return; /* something went terribly wrong */
+ switch (ELEMENTTYPE(*savegen)) {
+ case POLYGON:
+ lastpoly = TOPOLY(savegen);
+ addcycle(savegen, mincycle, 0);
+ savept = lastpoly->points + mincycle;
+ makerefcycle(lastpoly->cycle, mincycle);
+ findconstrained(lastpoly);
+ break;
+ case SPLINE:
+ lastspline = TOSPLINE(savegen);
+ addcycle(savegen, mincycle, 0);
+ savept = &lastspline->ctrl[mincycle];
+ makerefcycle(lastspline->cycle, mincycle);
+ break;
+ }
+ updatepath(lastpath);
+ if (!havecycle)
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ (genericptr)lastpath);
+ patheditpush(lastpath);
+ areawin->origin = areawin->save;
+ checkwarp(savept);
+
+ /* Draw edit lines on all splines in the path */
+ for (ggen = lastpath->plist; ggen < lastpath->plist + lastpath->parts;
+ ggen++) {
+ if (ELEMENTTYPE(*ggen) == SPLINE) {
+ lastspline = TOSPLINE(ggen);
+ UDrawXLine(lastspline->ctrl[0], lastspline->ctrl[1]);
+ UDrawXLine(lastspline->ctrl[3], lastspline->ctrl[2]);
+ }
+ }
+ XcSetXORFg((lastpoly) ? lastpoly->color : lastspline->color, BACKGROUND);
+ XcSetFunction(GXxor);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = EPATH_MODE;
+ printpos(savept->x, savept->y);
+
+ } break;
+ case POLYGON: {
+
+ lastpoly = (polyptr)editpart;
+
+ /* Determine which point of polygon is closest to cursor */
+ cycle = closepoint(lastpoly, &areawin->save);
+ havecycle = (lastpoly->cycle == NULL) ? False : True;
+ addcycle(&editpart, cycle, 0);
+ savept = lastpoly->points + cycle;
+ makerefcycle(lastpoly->cycle, cycle);
+ if (!havecycle) {
+ findconstrained(lastpoly);
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ (genericptr)lastpoly);
+ }
+
+ /* Push onto the editstack */
+ polyeditpush(lastpoly);
+
+ /* remember our postion for pointer restore */
+ areawin->origin = areawin->save;
+
+ checkwarp(savept);
+
+ XcSetXORFg(lastpoly->color, BACKGROUND);
+ XcSetFunction(GXxor);
+
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = EPOLY_MODE;
+ printeditbindings();
+ printpos(savept->x, savept->y);
+ } break;
+ case SPLINE: {
+ XPoint *curpt;
+
+ lastspline = (splineptr)editpart;
+
+ /* find which point is closest to the cursor */
+
+ cycle = (wirelength(&lastspline->ctrl[0],
+ &areawin->save) < wirelength(&lastspline->ctrl[3],
+ &areawin->save)) ? 0 : 3;
+ havecycle = (lastspline->cycle == NULL) ? False : True;
+ addcycle(&editpart, cycle, 0);
+ makerefcycle(lastspline->cycle, cycle);
+ curpt = &lastspline->ctrl[cycle];
+ if (!havecycle)
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance,
+ (genericptr)lastspline);
+
+ /* Push onto the editstack */
+ splineeditpush(lastspline);
+
+ /* remember our postion for pointer restore */
+ areawin->origin = areawin->save;
+
+ checkwarp(curpt);
+
+ UDrawXLine(lastspline->ctrl[0], lastspline->ctrl[1]);
+ UDrawXLine(lastspline->ctrl[3], lastspline->ctrl[2]);
+ XcSetXORFg(lastspline->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = ESPLINE_MODE;
+ } break;
+ case ARC: {
+ XPoint curpt;
+ float tmpratio, tlen;
+
+ lastarc = (arcptr)editpart;
+
+ /* find a part of the arc close to the pointer */
+
+ tlen = (float)wirelength(&areawin->save, &(lastarc->position));
+ tmpratio = (float)(abs(lastarc->radius)) / tlen;
+ curpt.x = lastarc->position.x + tmpratio * (areawin->save.x
+ - lastarc->position.x);
+ tmpratio = (float)lastarc->yaxis / tlen;
+ curpt.y = lastarc->position.y + tmpratio * (areawin->save.y
+ - lastarc->position.y);
+ addcycle(&editpart, 0, 0);
+ saveratio = (double)(lastarc->yaxis) / (double)(abs(lastarc->radius));
+
+ /* Push onto the editstack */
+ arceditpush(lastarc);
+ areawin->origin = areawin->save;
+
+ checkwarp(&curpt);
+
+ UDrawXLine(curpt, lastarc->position);
+ areawin->save.x = curpt.x; /* for redrawing dotted edit line */
+ areawin->save.y = curpt.y;
+ XcSetXORFg(lastarc->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ xcAddEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackarc, NULL);
+ eventmode = EARC_MODE;
+ printpos(curpt.x, curpt.y);
+ } break;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Raise an element to the top of the list */
+/*------------------------------------------------------*/
+
+void xc_top(short *selectno, short *orderlist)
+{
+ short i;
+ genericptr *raiseobj, *genobj, temp;
+
+ raiseobj = topobject->plist + *selectno;
+ temp = *raiseobj;
+ i = *selectno;
+ for (genobj = topobject->plist + *selectno; genobj <
+ topobject->plist + topobject->parts - 1; genobj++) {
+ *genobj = *(genobj + 1);
+ *(orderlist + i) = *(orderlist + i + 1);
+ i++;
+ }
+ *(topobject->plist + topobject->parts - 1) = temp;
+ *(orderlist + topobject->parts - 1) = *selectno;
+ *selectno = topobject->parts - 1;
+}
+
+/*------------------------------------------------------*/
+/* Lower an element to the bottom of the list */
+/*------------------------------------------------------*/
+
+
+void xc_bottom(short *selectno, short *orderlist)
+{
+ short i;
+ genericptr *lowerobj, *genobj, temp;
+
+ lowerobj = topobject->plist + *selectno;
+ temp = *lowerobj;
+ i = *selectno;
+ for (genobj = topobject->plist + *selectno;
+ genobj > topobject->plist; genobj--) {
+ *genobj = *(genobj - 1);
+ *(orderlist + i) = *(orderlist + i - 1);
+ i--;
+ }
+ *genobj = temp;
+ *orderlist = *selectno;
+ *selectno = 0;
+}
+
+/*--------------------------------------------------------------*/
+/* Raise all selected elements by one position in the list */
+/*--------------------------------------------------------------*/
+
+void xc_raise()
+{
+ short *sel, topsel, maxsel, *topidx, limit, *orderlist, i;
+ genericptr *raiseobj, temp;
+
+ orderlist = (short *)malloc(topobject->parts * sizeof(short));
+ for (i = 0; i < topobject->parts; i++) *(orderlist + i) = i;
+
+ /* Find topmost element in the select list */
+ maxsel = -1;
+ for (sel = areawin->selectlist; sel < areawin->selectlist + areawin->selects;
+ sel++) {
+ if (*sel > maxsel) {
+ maxsel = *sel;
+ topidx = sel;
+ }
+ }
+ if (maxsel == -1) return; /* Error condition */
+
+ topsel = maxsel;
+ limit = topobject->parts - 1;
+ while (1) {
+
+ /* Exchange the topmost element with the one above it */
+ if (topsel < limit) {
+ raiseobj = topobject->plist + topsel;
+ temp = *raiseobj;
+ *raiseobj = *(raiseobj + 1);
+ *(raiseobj + 1) = temp;
+ (*topidx)++;
+ i = *(orderlist + topsel);
+ *(orderlist + topsel) = *(orderlist + topsel + 1);
+ *(orderlist + topsel + 1) = i;
+ }
+ else
+ limit = topsel - 1;
+
+ /* Find next topmost element */
+ topsel = -1;
+ for (sel = areawin->selectlist; sel < areawin->selectlist + areawin->selects;
+ sel++) {
+ if (*sel < maxsel) {
+ if (*sel > topsel) {
+ topsel = *sel;
+ topidx = sel;
+ }
+ }
+ }
+ if (topsel == -1) break; /* No more elements to raise */
+ maxsel = topsel;
+ }
+ register_for_undo(XCF_Reorder, UNDO_MORE, areawin->topinstance, orderlist,
+ topobject->parts);
+}
+
+/*--------------------------------------------------------------*/
+/* Lower all selected elements by one position in the list */
+/*--------------------------------------------------------------*/
+
+void xc_lower()
+{
+ short *sel, botsel, minsel, *botidx, limit, *orderlist, i;
+ genericptr *lowerobj, temp;
+
+ orderlist = (short *)malloc(topobject->parts * sizeof(short));
+ for (i = 0; i < topobject->parts; i++) *(orderlist + i) = i;
+
+ /* Find bottommost element in the select list */
+ minsel = topobject->parts;
+ for (sel = areawin->selectlist; sel < areawin->selectlist + areawin->selects;
+ sel++) {
+ if (*sel < minsel) {
+ minsel = *sel;
+ botidx = sel;
+ }
+ }
+ if (minsel == topobject->parts) return; /* Error condition */
+
+ botsel = minsel;
+ limit = 0;
+ while (1) {
+
+ /* Exchange the topmost element with the one below it */
+ if (botsel > limit) {
+ lowerobj = topobject->plist + botsel;
+ temp = *lowerobj;
+ *lowerobj = *(lowerobj - 1);
+ *(lowerobj - 1) = temp;
+ (*botidx)--;
+ i = *(orderlist + botsel);
+ *(orderlist + botsel) = *(orderlist + botsel - 1);
+ *(orderlist + botsel - 1) = i;
+ }
+ else
+ limit = botsel + 1;
+
+ /* Find next topmost element */
+ botsel = topobject->parts;
+ for (sel = areawin->selectlist; sel < areawin->selectlist + areawin->selects;
+ sel++) {
+ if (*sel > minsel) {
+ if (*sel < botsel) {
+ botsel = *sel;
+ botidx = sel;
+ }
+ }
+ }
+ if (botsel == topobject->parts) break; /* No more elements to raise */
+ minsel = botsel;
+ }
+ register_for_undo(XCF_Reorder, UNDO_MORE, areawin->topinstance, orderlist,
+ topobject->parts);
+}
+
+/*------------------------------------------------------*/
+/* Generate a virtual copy of an object instance in the */
+/* user library. This is like the library virtual copy */
+/* except that it allows the user to generate a library */
+/* copy of an existing instance, without having to make */
+/* a copy of the master library instance and edit it. */
+/* copyvirtual() also allows the library virtual */
+/* instance to take on a specific rotation or flip */
+/* value, which cannot be done with the library virtual */
+/* copy function. */
+/*------------------------------------------------------*/
+
+void copyvirtual()
+{
+ short *selectno, created = 0;
+ objinstptr vcpobj, libinst;
+
+ for (selectno = areawin->selectlist; selectno < areawin->selectlist +
+ areawin->selects; selectno++) {
+ if (SELECTTYPE(selectno) == OBJINST) {
+ vcpobj = SELTOOBJINST(selectno);
+ libinst = addtoinstlist(USERLIB - LIBRARY, vcpobj->thisobject, TRUE);
+ instcopy(libinst, vcpobj);
+ created++;
+ }
+ }
+ if (created == 0) {
+ Wprintf("No object instances selected for virtual copy!");
+ }
+ else {
+ unselect_all();
+ composelib(USERLIB);
+ }
+}
+
+/*------------------------------------------------------*/
+/* Exchange the list position (drawing order) of two */
+/* elements, or move the position of one element to the */
+/* top or bottom. */
+/*------------------------------------------------------*/
+
+void exchange()
+{
+ short *selectno, *orderlist, i;
+ genericptr *exchobj, *exchobj2, temp;
+ Boolean preselected;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (!checkselect(ALL_TYPES)) {
+ Wprintf("Select 1 or 2 objects");
+ return;
+ }
+
+ selectno = areawin->selectlist;
+ orderlist = (short *)malloc(topobject->parts * sizeof(short));
+ for (i = 0; i < topobject->parts; i++) *(orderlist + i) = i;
+
+ if (areawin->selects == 1) { /* lower if on top; raise otherwise */
+ if (*selectno == topobject->parts - 1)
+ xc_bottom(selectno, orderlist);
+ else
+ xc_top(selectno, orderlist);
+ }
+ else { /* exchange the two objects */
+ exchobj = topobject->plist + *selectno;
+ exchobj2 = topobject->plist + *(selectno + 1);
+
+ temp = *exchobj;
+ *exchobj = *exchobj2;
+ *exchobj2 = temp;
+
+ i = *(orderlist + *selectno);
+ *(orderlist + *selectno) = *(orderlist + *(selectno + 1));
+ *(orderlist + *(selectno + 1)) = i;
+ }
+ register_for_undo(XCF_Reorder, UNDO_MORE, areawin->topinstance,
+ orderlist, topobject->parts);
+
+ incr_changes(topobject);
+ if (!preselected)
+ clearselects();
+ drawarea(NULL, NULL, NULL);
+}
+
+/*--------------------------------------------------------*/
+/* Flip an element horizontally (POLYGON, ARC, or SPLINE) */
+/*--------------------------------------------------------*/
+
+void elhflip(genericptr *genobj, short x)
+{
+ switch(ELEMENTTYPE(*genobj)) {
+ case POLYGON:{
+ polyptr flippoly = TOPOLY(genobj);
+ pointlist ppoint;
+ for (ppoint = flippoly->points; ppoint < flippoly->points +
+ flippoly->number; ppoint++)
+ ppoint->x = (x << 1) - ppoint->x;
+ }break;
+
+ case ARC:{
+ arcptr fliparc = TOARC(genobj);
+ float tmpang = 180 - fliparc->angle1;
+ fliparc->angle1 = 180 - fliparc->angle2;
+ fliparc->angle2 = tmpang;
+ if (fliparc->angle2 < 0) {
+ fliparc->angle1 += 360;
+ fliparc->angle2 += 360;
+ }
+ fliparc->radius = -fliparc->radius;
+ fliparc->position.x = (x << 1) - fliparc->position.x;
+ calcarc(fliparc);
+ }break;
+
+ case SPLINE:{
+ splineptr flipspline = TOSPLINE(genobj);
+ int i;
+ for (i = 0; i < 4; i++)
+ flipspline->ctrl[i].x = (x << 1) - flipspline->ctrl[i].x;
+ calcspline(flipspline);
+ }break;
+ }
+}
+
+/*--------------------------------------------------------*/
+/* Flip an element vertically (POLYGON, ARC, or SPLINE) */
+/*--------------------------------------------------------*/
+
+void elvflip(genericptr *genobj, short y)
+{
+ switch(ELEMENTTYPE(*genobj)) {
+
+ case POLYGON:{
+ polyptr flippoly = TOPOLY(genobj);
+ pointlist ppoint;
+
+ for (ppoint = flippoly->points; ppoint < flippoly->points +
+ flippoly->number; ppoint++)
+ ppoint->y = (y << 1) - ppoint->y;
+ }break;
+
+ case ARC:{
+ arcptr fliparc = TOARC(genobj);
+ float tmpang = 360 - fliparc->angle1;
+ fliparc->angle1 = 360 - fliparc->angle2;
+ fliparc->angle2 = tmpang;
+ if (fliparc->angle1 >= 360) {
+ fliparc->angle1 -= 360;
+ fliparc->angle2 -= 360;
+ }
+ fliparc->radius = -fliparc->radius;
+ fliparc->position.y = (y << 1) - fliparc->position.y;
+ calcarc(fliparc);
+ }break;
+
+ case SPLINE:{
+ splineptr flipspline = TOSPLINE(genobj);
+ int i;
+ for (i = 0; i < 4; i++)
+ flipspline->ctrl[i].y = (y << 1) - flipspline->ctrl[i].y;
+ calcspline(flipspline);
+ }break;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Horizontally flip an element */
+/*------------------------------------------------------*/
+
+void elementflip(XPoint *position)
+{
+ short *selectobj;
+ Boolean single = False;
+ Boolean preselected;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (!checkselect(ALL_TYPES)) return;
+ if (areawin->selects == 1) single = True;
+
+ if (eventmode != COPY_MODE)
+ register_for_undo(XCF_Flip_X, UNDO_MORE, areawin->topinstance,
+ (eventmode == MOVE_MODE) ? &areawin->origin : position);
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+
+ /* erase the object */
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ easydraw(*selectobj, DOFORALL);
+
+ switch(SELECTTYPE(selectobj)) {
+ case LABEL:{
+ labelptr fliplab = SELTOLABEL(selectobj);
+ if ((fliplab->justify & (RIGHT | NOTLEFT)) != NOTLEFT)
+ fliplab->justify ^= (RIGHT | NOTLEFT);
+ if (!single)
+ fliplab->position.x = (position->x << 1) - fliplab->position.x;
+ }break;
+ case GRAPHIC:{
+ graphicptr flipg = SELTOGRAPHIC(selectobj);
+ flipg->scale = -flipg->scale;
+ flipg->valid = FALSE;
+ if (!single)
+ flipg->position.x = (position->x << 1) - flipg->position.x;
+ }break;
+ case OBJINST:{
+ objinstptr flipobj = SELTOOBJINST(selectobj);
+ if (is_library(topobject) >= 0 && !is_virtual(flipobj)) break;
+ flipobj->scale = -flipobj->scale;
+ if (!single)
+ flipobj->position.x = (position->x << 1) - flipobj->position.x;
+ }break;
+ case POLYGON: case ARC: case SPLINE:
+ elhflip(topobject->plist + *selectobj, position->x);
+ break;
+ case PATH:{
+ genericptr *genpart;
+ pathptr flippath = SELTOPATH(selectobj);
+
+ for (genpart = flippath->plist; genpart < flippath->plist
+ + flippath->parts; genpart++)
+ elhflip(genpart, position->x);
+ }break;
+ }
+
+ if (preselected || (eventmode != NORMAL_MODE)) {
+ SetForeground(dpy, areawin->gc, SELECTCOLOR);
+ easydraw(*selectobj, DOFORALL);
+ }
+ }
+ select_invalidate_netlist();
+ if (eventmode == NORMAL_MODE || eventmode == CATALOG_MODE)
+ if (!preselected)
+ unselect_all();
+
+ if (eventmode == NORMAL_MODE)
+ incr_changes(topobject);
+ if (eventmode == CATALOG_MODE) {
+ int libnum;
+ if ((libnum = is_library(topobject)) >= 0) {
+ composelib(libnum + LIBRARY);
+ drawarea(NULL, NULL, NULL);
+ }
+ }
+ else {
+ pwriteback(areawin->topinstance);
+ calcbbox(areawin->topinstance);
+ }
+}
+
+/*----------------------------------------------*/
+/* Vertically flip an element */
+/*----------------------------------------------*/
+
+void elementvflip(XPoint *position)
+{
+ short *selectobj;
+ /*short fsign; (jdk) */
+ Boolean preselected;
+ Boolean single = False;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (!checkselect(ALL_TYPES)) return;
+ if (areawin->selects == 1) single = True;
+
+ if (eventmode != COPY_MODE)
+ register_for_undo(XCF_Flip_Y, UNDO_MORE, areawin->topinstance,
+ (eventmode == MOVE_MODE) ? &areawin->origin : position);
+
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+
+ /* erase the object */
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ easydraw(*selectobj, DOFORALL);
+
+ switch(SELECTTYPE(selectobj)) {
+ case(LABEL):{
+ labelptr fliplab = SELTOLABEL(selectobj);
+ if ((fliplab->justify & (TOP | NOTBOTTOM)) != NOTBOTTOM)
+ fliplab->justify ^= (TOP | NOTBOTTOM);
+ if (!single)
+ fliplab->position.y = (position->y << 1) - fliplab->position.y;
+ } break;
+ case(OBJINST):{
+ objinstptr flipobj = SELTOOBJINST(selectobj);
+
+ if (is_library(topobject) >= 0 && !is_virtual(flipobj)) break;
+ flipobj->scale = -(flipobj->scale);
+ flipobj->rotation += 180;
+ while (flipobj->rotation >= 360) flipobj->rotation -= 360;
+ if (!single)
+ flipobj->position.y = (position->y << 1) - flipobj->position.y;
+ }break;
+ case(GRAPHIC):{
+ graphicptr flipg = SELTOGRAPHIC(selectobj);
+
+ flipg->scale = -(flipg->scale);
+ flipg->rotation += 180;
+ while (flipg->rotation >= 360) flipg->rotation -= 360;
+ if (!single)
+ flipg->position.y = (position->y << 1) - flipg->position.y;
+ }break;
+ case POLYGON: case ARC: case SPLINE:
+ elvflip(topobject->plist + *selectobj, position->y);
+ break;
+ case PATH:{
+ genericptr *genpart;
+ pathptr flippath = SELTOPATH(selectobj);
+
+ for (genpart = flippath->plist; genpart < flippath->plist
+ + flippath->parts; genpart++)
+ elvflip(genpart, position->y);
+ }break;
+ }
+ if (preselected || (eventmode != NORMAL_MODE)) {
+ SetForeground(dpy, areawin->gc, SELECTCOLOR);
+ easydraw(*selectobj, DOFORALL);
+ }
+ }
+ select_invalidate_netlist();
+ if (eventmode == NORMAL_MODE || eventmode == CATALOG_MODE)
+ if (!preselected)
+ unselect_all();
+ if (eventmode == NORMAL_MODE) {
+ incr_changes(topobject);
+ }
+ if (eventmode == CATALOG_MODE) {
+ int libnum;
+ if ((libnum = is_library(topobject)) >= 0) {
+ composelib(libnum + LIBRARY);
+ drawarea(NULL, NULL, NULL);
+ }
+ }
+ else {
+ pwriteback(areawin->topinstance);
+ calcbbox(areawin->topinstance);
+ }
+}
+
+/*----------------------------------------*/
+/* ButtonPress handler during delete mode */
+/*----------------------------------------*/
+
+void deletebutton(int x, int y)
+{
+ if (checkselect(ALL_TYPES)) {
+ standard_element_delete(ERASE);
+ calcbbox(areawin->topinstance);
+ }
+ setoptionmenu(); /* Return GUI check/radio boxes to default */
+}
+
+/*----------------------------------------------------------------------*/
+/* Process of element deletion. Remove one element from the indicated */
+/* object. */
+/*----------------------------------------------------------------------*/
+
+void delete_one_element(objinstptr thisinstance, genericptr thiselement)
+{
+ objectptr thisobject;
+ genericptr *genobj;
+ Boolean pinchange = False;
+
+ thisobject = thisinstance->thisobject;
+
+ /* The netlist contains pointers to elements which no longer */
+ /* exist on the page, so we should remove them from the netlist. */
+
+ if (RemoveFromNetlist(thisobject, thiselement)) pinchange = True;
+ for (genobj = thisobject->plist; genobj < thisobject->plist
+ + thisobject->parts; genobj++)
+ if (*genobj == thiselement)
+ break;
+
+ if (genobj == thisobject->plist + thisobject->parts) return;
+
+ for (++genobj; genobj < thisobject->plist + thisobject->parts; genobj++)
+ *(genobj - 1) = *genobj;
+ thisobject->parts--;
+
+ if (pinchange) setobjecttype(thisobject);
+ incr_changes(thisobject);
+ calcbbox(thisinstance);
+ invalidate_netlist(thisobject);
+ /* freenetlist(thisobject); */
+}
+
+/*----------------------------------------------------------------------*/
+/* Process of element deletion. Remove everything in the selection */
+/* list from the indicated object, and return a new object containing */
+/* only the deleted elements. */
+/* */
+/* if drawmode is DRAW, we erase the objects as we remove them. */
+/* */
+/* Note that if "slist" is areawin->selectlist, it is freed by this */
+/* routine (calls freeselects()), but not otherwise. */
+/*----------------------------------------------------------------------*/
+
+objectptr delete_element(objinstptr thisinstance, short *slist, int selects,
+ short drawmode)
+{
+ short *selectobj;
+ objectptr delobj, thisobject;
+ genericptr *genobj;
+ Boolean pinchange = False;
+
+ if (slist == NULL || selects == 0) return NULL;
+
+ thisobject = thisinstance->thisobject;
+
+ delobj = (objectptr) malloc(sizeof(object));
+ initmem(delobj);
+
+ if (drawmode) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ }
+
+ for (selectobj = slist; selectobj < slist + selects; selectobj++) {
+ genobj = thisobject->plist + *selectobj;
+ if (drawmode) easydraw(*selectobj, DOFORALL);
+ PLIST_INCR(delobj);
+ *(delobj->plist + delobj->parts) = *genobj;
+ delobj->parts++;
+
+ /* The netlist contains pointers to elements which no longer */
+ /* exist on the page, so we should remove them from the netlist. */
+
+ if (RemoveFromNetlist(thisobject, *genobj)) pinchange = True;
+ for (++genobj; genobj < thisobject->plist + thisobject->parts; genobj++)
+ *(genobj - 1) = *genobj;
+ thisobject->parts--;
+ reviseselect(slist, selects, selectobj);
+ }
+ if (pinchange) setobjecttype(thisobject);
+
+ if (slist == areawin->selectlist)
+ freeselects();
+
+ calcbbox(thisinstance);
+ /* freenetlist(thisobject); */
+
+ if (drawmode) {
+ SetForeground(dpy, areawin->gc, FOREGROUND);
+ drawarea(NULL, NULL, NULL);
+ }
+ return delobj;
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrapper for delete_element(). Remember this deletion for the undo */
+/* function. */
+/*----------------------------------------------------------------------*/
+
+void standard_element_delete(short drawmode)
+{
+ objectptr delobj;
+
+// register_for_undo(XCF_Select, UNDO_MORE, areawin->topinstance,
+// areawin->selectlist, areawin->selects);
+ select_invalidate_netlist();
+ delobj = delete_element(areawin->topinstance, areawin->selectlist,
+ areawin->selects, drawmode);
+ register_for_undo(XCF_Delete, UNDO_DONE, areawin->topinstance,
+ delobj, (int)drawmode);
+ incr_changes(topobject); /* Treat as one change */
+}
+
+/*----------------------------------------------------------------------*/
+/* Another wrapper for delete_element(), in which we do not save the */
+/* deletion as an undo event. However, the returned object is saved */
+/* on areawin->editstack, so that the objects can be grabbed. This */
+/* allows objects to be carried across pages and through the hierarchy. */
+/*----------------------------------------------------------------------*/
+
+void delete_for_xfer(short drawmode, short *slist, int selects)
+{
+ if (selects > 0) {
+ reset(areawin->editstack, DESTROY);
+ areawin->editstack = delete_element(areawin->topinstance,
+ slist, selects, drawmode);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Yet another wrapper for delete_element(), in which we destroy the */
+/* object returned and free all associated memory. */
+/*----------------------------------------------------------------------*/
+
+void delete_noundo(short drawmode)
+{
+ objectptr delobj;
+
+ select_invalidate_netlist();
+ delobj = delete_element(areawin->topinstance, areawin->selectlist,
+ areawin->selects, drawmode);
+
+ if (delobj != NULL) reset(delobj, DESTROY);
+}
+
+/*----------------------------------------------------------------------*/
+/* Undelete last deleted elements and return a selectlist of the */
+/* elements. If "olist" is non-NULL, then the undeleted elements are */
+/* placed into the object of thisinstance in the order given by olist, */
+/* and a copy of olist is returned. If "olist" is NULL, then the */
+/* undeleted elements are placed at the end of thisinstance->thisobject */
+/* ->plist, and a new selection list is returned. If "olist" is non- */
+/* NULL, then the size of olist had better match the number of objects */
+/* in delobj! It is up to the calling routine to check this. */
+/*----------------------------------------------------------------------*/
+
+short *xc_undelete(objinstptr thisinstance, objectptr delobj, short mode,
+ short *olist)
+{
+ objectptr thisobject;
+ genericptr *regen;
+ short *slist, count, i; /* position; (jdk) */
+
+ thisobject = thisinstance->thisobject;
+ slist = (short *)malloc(delobj->parts * sizeof(short));
+ count = 0;
+
+ if (mode) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ }
+
+ for (regen = delobj->plist; regen < delobj->plist + delobj->parts; regen++) {
+ PLIST_INCR(thisobject);
+ if (olist == NULL) {
+ *(slist + count) = thisobject->parts;
+ *(topobject->plist + topobject->parts) = *regen;
+ }
+ else {
+ *(slist + count) = *(olist + count);
+ for (i = thisobject->parts; i > *(olist + count); i--)
+ *(thisobject->plist + i) = *(thisobject->plist + i - 1);
+ *(thisobject->plist + i) = *regen;
+ }
+ thisobject->parts++;
+ if (mode) {
+ XTopSetForeground((*regen)->color);
+ easydraw(*(slist + count), DEFAULTCOLOR);
+ }
+ count++;
+
+ /* If the element has passed parameters (eparam), then we have to */
+ /* check if the key exists in the new parent object. If not, */
+ /* delete the parameter. */
+
+ if ((*regen)->passed) {
+ eparamptr nextepp, epp = (*regen)->passed;
+ while (epp != NULL) {
+ nextepp = epp->next;
+ if (!match_param(thisobject, epp->key)) {
+ if (epp == (*regen)->passed) (*regen)->passed = nextepp;
+ free_element_param(*regen, epp);
+ }
+ epp = nextepp;
+ }
+ }
+
+ /* Likewise, string parameters must be checked in labels because */
+ /* they act like element parameters. */
+
+ if (IS_LABEL(*regen)) {
+ labelptr glab = TOLABEL(regen);
+ stringpart *gstr, *lastpart = NULL;
+ for (gstr = glab->string; gstr != NULL; gstr = lastpart->nextpart) {
+ if (gstr->type == PARAM_START) {
+ if (!match_param(thisobject, gstr->data.string)) {
+ free(gstr->data.string);
+ if (lastpart)
+ lastpart->nextpart = gstr->nextpart;
+ else
+ glab->string = gstr->nextpart;
+ free(gstr);
+ gstr = (lastpart) ? lastpart : glab->string;
+ }
+ }
+ lastpart = gstr;
+ }
+ }
+ }
+ incr_changes(thisobject); /* treat as one change */
+ calcbbox(thisinstance);
+
+ /* flush the delete buffer but don't delete the elements */
+ reset(delobj, SAVE);
+
+ if (delobj != areawin->editstack) free(delobj);
+
+ return slist;
+}
+
+/*----------------------------*/
+/* select save object handler */
+/*----------------------------*/
+
+void printname(objectptr curobject)
+{
+ char editstr[10], pagestr[10];
+ short ispage;
+
+#ifndef TCL_WRAPPER
+ Arg wargs[1];
+ Dimension swidth, swidth2, sarea;
+ char tmpname[256];
+ char *sptr = tmpname;
+#endif
+
+ /* print full string to make message widget proper size */
+
+ strcpy(editstr, ((ispage = is_page(curobject)) >= 0) ? "Editing: " : "");
+ strcpy(editstr, (is_library(curobject) >= 0) ? "Library: " : "");
+ if (strstr(curobject->name, "Page") == NULL && (ispage >= 0))
+ sprintf(pagestr, " (p. %d)", areawin->page + 1);
+ else
+ pagestr[0] = '\0';
+ W2printf("%s%s%s", editstr, curobject->name, pagestr);
+
+ /* Tcl doesn't update width changes immediately. . . what to do? */
+ /* (i.e., Tk_Width(message2) gives the original width) */
+#ifndef TCL_WRAPPER
+
+ XtSetArg(wargs[0], XtNwidth, &sarea);
+ XtGetValues(message2, wargs, 1);
+
+ /* in the remote case that the string is longer than message widget, */
+ /* truncate the string and denote the truncation with an ellipsis (...) */
+
+ strcpy(tmpname, curobject->name);
+ swidth2 = XTextWidth(appdata.xcfont, editstr, strlen(editstr));
+ swidth = XTextWidth(appdata.xcfont, tmpname, strlen(tmpname));
+
+ if ((swidth + swidth2) > sarea) {
+ char *ip;
+ while ((swidth + swidth2) > sarea) {
+ sptr++;
+ swidth = XTextWidth(appdata.xcfont, sptr, strlen(sptr));
+ }
+ for(ip = sptr; ip < sptr + 3 && *ip != '\0'; ip++) *ip = '.';
+
+ W2printf("Editing: %s", sptr);
+ }
+#endif
+}
+
+/*--------------------------------------------------------------*/
+/* Make sure that a string does not conflict with postscript */
+/* names (commands and definitions found in xcircps2.pro). */
+/* */
+/* Return value is NULL if no change was made. Otherwise, the */
+/* return value is an allocated string. */
+/*--------------------------------------------------------------*/
+
+char *checkvalidname(char *teststring, objectptr newobj)
+{
+ int i, j;
+ short dupl; /* flag a duplicate string */
+ objectptr *libobj;
+ char *sptr, *pptr, *cptr;
+ aliasptr aref;
+ slistptr sref;
+
+ /* Try not to allocate memory unless necessary */
+
+ sptr = teststring;
+ pptr = sptr;
+
+ do {
+ dupl = 0;
+ if (newobj != NULL) {
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ libobj = xobjs.userlibs[i].library + j;
+
+ if (*libobj == newobj) continue;
+ if (!strcmp(pptr, (*libobj)->name)) {
+
+ /* Prepend an underscore to the object name. If the */
+ /* object has no technology, create a null technology */
+ /* name. Otherwise, the technology remains the same */
+ /* but the object name gets the prepended underscore. */
+
+ if ((cptr = strstr(pptr, "::")) == NULL) {
+ pptr = (char *)malloc(strlen((*libobj)->name) + 3);
+ sprintf(pptr, "::_%s", (*libobj)->name);
+ }
+ else {
+ int offset = cptr - pptr + 2;
+ if (pptr == sptr)
+ pptr = (char *)malloc(strlen((*libobj)->name) + 2);
+ else
+ pptr = (char *)realloc(pptr, strlen((*libobj)->name) + 2);
+ sprintf(pptr, "%s", (*libobj)->name);
+ sprintf(pptr + offset, "_%s", (*libobj)->name + offset);
+ }
+ dupl = 1;
+ }
+ }
+ }
+
+ /* If we're in the middle of a file load, the name cannot be */
+ /* the same as an alias, either. */
+
+ if (aliastop != NULL) {
+ for (aref = aliastop; aref != NULL; aref = aref->next) {
+ for (sref = aref->aliases; sref != NULL; sref = sref->next) {
+ if (!strcmp(pptr, sref->alias)) {
+ if (pptr == sptr)
+ pptr = (char *)malloc(strlen(sref->alias) + 2);
+ else
+ pptr = (char *)realloc(pptr, strlen(sref->alias) + 2);
+ sprintf(pptr, "_%s", sref->alias);
+ dupl = 1;
+ }
+ }
+ }
+ }
+ }
+
+ } while (dupl == 1);
+
+ return (pptr == sptr) ? NULL : pptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Make sure that name for new object does not conflict with */
+/* existing object definitions */
+/* */
+/* Return: True if name required change, False otherwise */
+/*--------------------------------------------------------------*/
+
+Boolean checkname(objectptr newobj)
+{
+ char *pptr;
+
+ /* Check for empty string */
+ if (strlen(newobj->name) == 0) {
+ Wprintf("Blank object name changed to default");
+ sprintf(newobj->name, "user_object");
+ }
+
+ pptr = checkvalidname(newobj->name, newobj);
+
+ /* Change name if necessary to avoid naming conflicts */
+ if (pptr == NULL) {
+ Wprintf("Created new object %s", newobj->name);
+ return False;
+ }
+ else {
+ Wprintf("Changed name from %s to %s to avoid conflict with "
+ "existing object", newobj->name, pptr);
+ strncpy(newobj->name, pptr, 79);
+ free(pptr);
+ }
+ return True;
+}
+
+/*------------------------------------------------------------*/
+/* Find the object "dot" in the builtin library, if it exists */
+/*------------------------------------------------------------*/
+
+objectptr finddot()
+{
+ objectptr dotobj;
+ short i, j;
+ char *name, *pptr;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ dotobj = *(xobjs.userlibs[i].library + j);
+ name = dotobj->name;
+ if ((pptr = strstr(name, "::")) != NULL) name = pptr + 2;
+ if (!strcmp(name, "dot")) {
+ return dotobj;
+ }
+ }
+ }
+ return (objectptr)NULL;
+}
+
+/*--------------------------------------*/
+/* Add value origin to all points */
+/*--------------------------------------*/
+
+void movepoints(genericptr *ssgen, short deltax, short deltay)
+{
+ switch(ELEMENTTYPE(*ssgen)) {
+ case ARC:{
+ fpointlist sspoints;
+ TOARC(ssgen)->position.x += deltax;
+ TOARC(ssgen)->position.y += deltay;
+ for (sspoints = TOARC(ssgen)->points; sspoints < TOARC(ssgen)->points +
+ TOARC(ssgen)->number; sspoints++) {
+ sspoints->x += deltax;
+ sspoints->y += deltay;
+ }
+ }break;
+
+ case POLYGON:{
+ pointlist sspoints;
+ for (sspoints = TOPOLY(ssgen)->points; sspoints < TOPOLY(ssgen)->points +
+ TOPOLY(ssgen)->number; sspoints++) {
+ sspoints->x += deltax;
+ sspoints->y += deltay;
+ }
+ }break;
+
+ case SPLINE:{
+ fpointlist sspoints;
+ short j;
+ for (sspoints = TOSPLINE(ssgen)->points; sspoints <
+ TOSPLINE(ssgen)->points + INTSEGS; sspoints++) {
+ sspoints->x += deltax;
+ sspoints->y += deltay;
+ }
+ for (j = 0; j < 4; j++) {
+ TOSPLINE(ssgen)->ctrl[j].x += deltax;
+ TOSPLINE(ssgen)->ctrl[j].y += deltay;
+ }
+ }break;
+ case OBJINST:
+ TOOBJINST(ssgen)->position.x += deltax;
+ TOOBJINST(ssgen)->position.y += deltay;
+ break;
+ case GRAPHIC:
+ TOGRAPHIC(ssgen)->position.x += deltax;
+ TOGRAPHIC(ssgen)->position.y += deltay;
+ break;
+ case LABEL:
+ TOLABEL(ssgen)->position.x += deltax;
+ TOLABEL(ssgen)->position.y += deltay;
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Add value origin to all edited points, according to edit flags */
+/*----------------------------------------------------------------------*/
+
+void editpoints(genericptr *ssgen, short deltax, short deltay)
+{
+ pathptr editpath;
+ polyptr editpoly;
+ splineptr editspline;
+ short cycle, cpoint;
+ pointselect *cptr;
+ XPoint *curpt;
+ genericptr *ggen;
+
+ switch(ELEMENTTYPE(*ssgen)) {
+ case POLYGON:
+ editpoly = TOPOLY(ssgen);
+ if (editpoly->cycle == NULL)
+ movepoints(ssgen, deltax, deltay);
+ else {
+ for (cptr = editpoly->cycle;; cptr++) {
+ cycle = cptr->number;
+ curpt = editpoly->points + cycle;
+ if (cptr->flags & EDITX) curpt->x += deltax;
+ if (cptr->flags & EDITY) curpt->y += deltay;
+ if (cptr->flags & LASTENTRY) break;
+ }
+ }
+ exprsub(*ssgen);
+ break;
+
+ case SPLINE:
+ editspline = TOSPLINE(ssgen);
+ if (editspline->cycle == NULL)
+ movepoints(ssgen, deltax, deltay);
+ else {
+ for (cptr = editspline->cycle;; cptr++) {
+ cycle = cptr->number;
+ if (cycle == 0 || cycle == 3) {
+ cpoint = (cycle == 0) ? 1 : 2;
+ if (cptr->flags & EDITX) editspline->ctrl[cpoint].x += deltax;
+ if (cptr->flags & EDITY) editspline->ctrl[cpoint].y += deltay;
+ }
+ if (cptr->flags & EDITX) editspline->ctrl[cycle].x += deltax;
+ if (cptr->flags & EDITY) editspline->ctrl[cycle].y += deltay;
+ if (cptr->flags & ANTIXY) {
+ editspline->ctrl[cycle].x -= deltax;
+ editspline->ctrl[cycle].y -= deltay;
+ }
+ if (cptr->flags & LASTENTRY) break;
+ }
+ }
+ exprsub(*ssgen);
+ calcspline(editspline);
+ break;
+
+ case PATH:
+ editpath = TOPATH(ssgen);
+ if (checkcycle(*ssgen, 0) < 0) {
+ for (ggen = editpath->plist; ggen < editpath->plist + editpath->parts;
+ ggen++)
+ movepoints(ggen, deltax, deltay);
+ }
+ else {
+ for (ggen = editpath->plist; ggen < editpath->plist + editpath->parts;
+ ggen++) {
+ if (checkcycle(*ggen, 0) >= 0)
+ editpoints(ggen, deltax, deltay);
+ }
+ }
+ break;
+
+ default:
+ movepoints(ssgen, deltax, deltay);
+ exprsub(*ssgen);
+ break;
+ }
+}
+
+#ifndef TCL_WRAPPER
+
+void xlib_makeobject(xcWidget w, caddr_t nulldata)
+{
+ domakeobject(-1, (char *)_STR2, FALSE);
+}
+
+#endif /* !TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Set the name for a new user-defined object and make the */
+/* object. If "forceempty" is true, we allow creation of a new */
+/* object with no elements (normally would be used only from a */
+/* script, where an object is being constructed automatically). */
+/*--------------------------------------------------------------*/
+
+objinstptr domakeobject(int libnum, char *name, Boolean forceempty)
+{
+ objectptr *newobj;
+ objinstptr *newinst;
+ genericptr *ssgen;
+ oparamptr ops, newop;
+ eparamptr epp, newepp;
+ stringpart *sptr;
+ XPoint origin;
+ short loclibnum = libnum;
+
+ if (libnum == -1) loclibnum = USERLIB - LIBRARY;
+
+ /* make room for new entry in library list */
+
+ xobjs.userlibs[loclibnum].library = (objectptr *)
+ realloc(xobjs.userlibs[loclibnum].library,
+ (xobjs.userlibs[loclibnum].number + 1) * sizeof(objectptr));
+
+ newobj = xobjs.userlibs[loclibnum].library + xobjs.userlibs[loclibnum].number;
+
+ *newobj = delete_element(areawin->topinstance, areawin->selectlist,
+ areawin->selects, NORMAL);
+
+ if (*newobj == NULL) {
+ objectptr initobj;
+
+ if (!forceempty) return NULL;
+
+ /* Create a new (empty) object */
+
+ initobj = (objectptr) malloc(sizeof(object));
+ initmem(initobj);
+ *newobj = initobj;
+ }
+
+ invalidate_netlist(topobject);
+ xobjs.userlibs[loclibnum].number++;
+
+ /* Create the instance of this object so we can compute a bounding box */
+
+ NEW_OBJINST(newinst, topobject);
+ instancedefaults(*newinst, *newobj, 0, 0);
+ calcbbox(*newinst);
+
+ /* find closest snap point to bbox center and make this the obj. center */
+
+ if (areawin->center) {
+ origin.x = (*newobj)->bbox.lowerleft.x + (*newobj)->bbox.width / 2;
+ origin.y = (*newobj)->bbox.lowerleft.y + (*newobj)->bbox.height / 2;
+ }
+ else {
+ origin.x = origin.y = 0;
+ }
+ u2u_snap(&origin);
+ instancedefaults(*newinst, *newobj, origin.x, origin.y);
+
+ for (ssgen = (*newobj)->plist; ssgen < (*newobj)->plist + (*newobj)->parts;
+ ssgen++) {
+ switch(ELEMENTTYPE(*ssgen)) {
+
+ case(OBJINST):
+ TOOBJINST(ssgen)->position.x -= origin.x;
+ TOOBJINST(ssgen)->position.y -= origin.y;
+ break;
+
+ case(GRAPHIC):
+ TOGRAPHIC(ssgen)->position.x -= origin.x;
+ TOGRAPHIC(ssgen)->position.y -= origin.y;
+ break;
+
+ case(LABEL):
+ TOLABEL(ssgen)->position.x -= origin.x;
+ TOLABEL(ssgen)->position.y -= origin.y;
+ break;
+
+ case(PATH):{
+ genericptr *pathlist;
+ for (pathlist = TOPATH(ssgen)->plist; pathlist < TOPATH(ssgen)->plist
+ + TOPATH(ssgen)->parts; pathlist++) {
+ movepoints(pathlist, -origin.x, -origin.y);
+ }
+ }break;
+
+ default:
+ movepoints(ssgen, -origin.x, -origin.y);
+ break;
+ }
+ }
+
+ for (ssgen = (*newobj)->plist; ssgen < (*newobj)->plist + (*newobj)->parts;
+ ssgen++) {
+ for (epp = (*ssgen)->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ newop = copyparameter(ops);
+ newop->next = (*newobj)->params;
+ (*newobj)->params = newop;
+
+ /* Generate an indirect parameter reference from child to parent */
+ newepp = make_new_eparam(epp->key);
+ newepp->flags |= P_INDIRECT;
+ newepp->pdata.refkey = strdup(epp->key);
+ newepp->next = (*newinst)->passed;
+ (*newinst)->passed = newepp;
+ }
+ if (IS_LABEL(*ssgen)) {
+ /* Also need to check for substring parameters in labels */
+ for (sptr = TOLABEL(ssgen)->string; sptr != NULL; sptr = sptr->nextpart) {
+ if (sptr->type == PARAM_START) {
+ ops = match_param(topobject, sptr->data.string);
+ newop = copyparameter(ops);
+ newop->next = (*newobj)->params;
+ (*newobj)->params = newop;
+
+ /* Generate an indirect parameter reference from child to parent */
+ newepp = make_new_eparam(sptr->data.string);
+ newepp->flags |= P_INDIRECT;
+ newepp->pdata.refkey = strdup(sptr->data.string);
+ newepp->next = (*newinst)->passed;
+ (*newinst)->passed = newepp;
+ }
+ }
+ }
+ }
+
+ /* any parameters in the top-level object that used by the selected */
+ /* elements must be copied into the new object. */
+
+ /* put new object back into place */
+
+ (*newobj)->hidden = False;
+ (*newobj)->schemtype = SYMBOL;
+
+ calcbbox(*newinst);
+ incr_changes(*newobj);
+
+ /* (netlist invalidation was taken care of by delete_element() */
+ /* Also, incr_changes(topobject) was done by delete_element()) */
+
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground((*newinst)->color);
+ UDrawObject(*newinst, SINGLE, (*newinst)->color,
+ xobjs.pagelist[areawin->page]->wirewidth, NULL);
+
+
+ /* Copy name into object and check for conflicts */
+
+ strcpy((*newobj)->name, name);
+ checkname(*newobj);
+
+ /* register the technology and mark the technology as not saved */
+ AddObjectTechnology(*newobj);
+
+ /* generate library instance for this object (bounding box */
+ /* should be default, so don't do calcbbox() on it) */
+
+ addtoinstlist(loclibnum, *newobj, FALSE);
+
+ /* recompile the user catalog and reset view bounds */
+
+ composelib(loclibnum + LIBRARY);
+ centerview(xobjs.libtop[loclibnum + LIBRARY]);
+
+ return *newinst;
+}
+
+#ifndef TCL_WRAPPER
+
+/*-------------------------------------------*/
+/* Make a user object from selected elements */
+/*-------------------------------------------*/
+
+void selectsave(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *popdata = (buttonsave *)malloc(sizeof(buttonsave));
+
+ if (areawin->selects == 0) return; /* nothing was selected */
+
+ /* Get a name for the new object */
+
+ eventmode = NORMAL_MODE;
+ popdata->dataptr = NULL;
+ popdata->button = NULL; /* indicates that no button is assc'd w/ the popup */
+ popupprompt(w, "Enter name for new object:", "\0", xlib_makeobject, popdata, NULL);
+}
+
+#endif
+
+/*-----------------------------*/
+/* Edit-stack support routines */
+/*-----------------------------*/
+
+void arceditpush(arcptr lastarc)
+{
+ arcptr *newarc;
+
+ NEW_ARC(newarc, areawin->editstack);
+ arccopy(*newarc, lastarc);
+ copycycles(&((*newarc)->cycle), &(lastarc->cycle));
+}
+
+/*--------------------------------------*/
+
+void splineeditpush(splineptr lastspline)
+{
+ splineptr *newspline;
+
+ NEW_SPLINE(newspline, areawin->editstack);
+ splinecopy(*newspline, lastspline);
+}
+
+/*--------------------------------------*/
+
+void polyeditpush(polyptr lastpoly)
+{
+ polyptr *newpoly;
+
+ NEW_POLY(newpoly, areawin->editstack);
+ polycopy(*newpoly, lastpoly);
+}
+
+/*--------------------------------------*/
+
+void patheditpush(pathptr lastpath)
+{
+ pathptr *newpath;
+
+ NEW_PATH(newpath, areawin->editstack);
+ pathcopy(*newpath, lastpath);
+}
+
+/*-----------------------------*/
+/* Copying support routines */
+/*-----------------------------*/
+
+pointlist copypoints(pointlist points, int number)
+{
+ pointlist rpoints, cpoints, newpoints;
+
+ rpoints = (pointlist) malloc(number * sizeof(XPoint));
+ for (newpoints = rpoints, cpoints = points;
+ newpoints < rpoints + number;
+ newpoints++, cpoints++) {
+ newpoints->x = cpoints->x;
+ newpoints->y = cpoints->y;
+ }
+ return rpoints;
+}
+
+/*------------------------------------------*/
+
+void graphiccopy(graphicptr newg, graphicptr copyg)
+{
+ Imagedata *iptr;
+ int i;
+
+ newg->source = copyg->source;
+ newg->position.x = copyg->position.x;
+ newg->position.y = copyg->position.y;
+ newg->rotation = copyg->rotation;
+ newg->scale = copyg->scale;
+ newg->color = copyg->color;
+ newg->passed = NULL;
+ copyalleparams((genericptr)newg, (genericptr)copyg);
+ newg->valid = FALSE;
+ newg->target = NULL;
+ newg->clipmask = (Pixmap)NULL;
+
+ /* Update the refcount of the source image */
+ for (i = 0; i < xobjs.images; i++) {
+ iptr = xobjs.imagelist + i;
+ if (iptr->image == newg->source) {
+ iptr->refcount++;
+ break;
+ }
+ }
+}
+
+/*------------------------------------------*/
+
+void labelcopy(labelptr newtext, labelptr copytext)
+{
+ newtext->string = stringcopy(copytext->string);
+ newtext->position.x = copytext->position.x;
+ newtext->position.y = copytext->position.y;
+ newtext->rotation = copytext->rotation;
+ newtext->scale = copytext->scale;
+ newtext->justify = copytext->justify;
+ newtext->color = copytext->color;
+ newtext->passed = NULL;
+ newtext->cycle = NULL;
+ copyalleparams((genericptr)newtext, (genericptr)copytext);
+ newtext->pin = copytext->pin;
+}
+
+/*------------------------------------------*/
+
+void arccopy(arcptr newarc, arcptr copyarc)
+{
+ newarc->style = copyarc->style;
+ newarc->color = copyarc->color;
+ newarc->position.x = copyarc->position.x;
+ newarc->position.y = copyarc->position.y;
+ newarc->radius = copyarc->radius;
+ newarc->yaxis = copyarc->yaxis;
+ newarc->angle1 = copyarc->angle1;
+ newarc->angle2 = copyarc->angle2;
+ newarc->width = copyarc->width;
+ newarc->passed = NULL;
+ newarc->cycle = NULL;
+ copyalleparams((genericptr)newarc, (genericptr)copyarc);
+ calcarc(newarc);
+}
+
+/*------------------------------------------*/
+
+void polycopy(polyptr newpoly, polyptr copypoly)
+{
+ newpoly->style = copypoly->style;
+ newpoly->color = copypoly->color;
+ newpoly->width = copypoly->width;
+ newpoly->number = copypoly->number;
+ copycycles(&(newpoly->cycle), &(copypoly->cycle));
+ newpoly->points = copypoints(copypoly->points, copypoly->number);
+
+ newpoly->passed = NULL;
+ copyalleparams((genericptr)newpoly, (genericptr)copypoly);
+}
+
+/*------------------------------------------*/
+
+void splinecopy(splineptr newspline, splineptr copyspline)
+{
+ short i;
+
+ newspline->style = copyspline->style;
+ newspline->color = copyspline->color;
+ newspline->width = copyspline->width;
+ copycycles(&(newspline->cycle), &(copyspline->cycle));
+ for (i = 0; i < 4; i++) {
+ newspline->ctrl[i].x = copyspline->ctrl[i].x;
+ newspline->ctrl[i].y = copyspline->ctrl[i].y;
+ }
+ for (i = 0; i < INTSEGS; i++) {
+ newspline->points[i].x = copyspline->points[i].x;
+ newspline->points[i].y = copyspline->points[i].y;
+ }
+ newspline->passed = NULL;
+ copyalleparams((genericptr)newspline, (genericptr)copyspline);
+}
+
+/*----------------------------------------------*/
+/* Copy a path */
+/*----------------------------------------------*/
+
+void pathcopy(pathptr newpath, pathptr copypath)
+{
+ genericptr *ggen;
+ splineptr *newspline, copyspline;
+ polyptr *newpoly, copypoly;
+
+ newpath->style = copypath->style;
+ newpath->color = copypath->color;
+ newpath->width = copypath->width;
+ newpath->parts = 0;
+ newpath->passed = NULL;
+ copyalleparams((genericptr)newpath, (genericptr)copypath);
+ newpath->plist = (genericptr *)malloc(copypath->parts * sizeof(genericptr));
+
+ for (ggen = copypath->plist; ggen < copypath->plist + copypath->parts; ggen++) {
+ switch (ELEMENTTYPE(*ggen)) {
+ case POLYGON:
+ copypoly = TOPOLY(ggen);
+ NEW_POLY(newpoly, newpath);
+ polycopy(*newpoly, copypoly);
+ break;
+ case SPLINE:
+ copyspline = TOSPLINE(ggen);
+ NEW_SPLINE(newspline, newpath);
+ splinecopy(*newspline, copyspline);
+ break;
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Copy an object instance */
+/*--------------------------------------------------------------*/
+
+void instcopy(objinstptr newobj, objinstptr copyobj)
+{
+ newobj->position.x = copyobj->position.x;
+ newobj->position.y = copyobj->position.y;
+ newobj->rotation = copyobj->rotation;
+ newobj->scale = copyobj->scale;
+ newobj->style = copyobj->style;
+ newobj->thisobject = copyobj->thisobject;
+ newobj->color = copyobj->color;
+ newobj->bbox.lowerleft.x = copyobj->bbox.lowerleft.x;
+ newobj->bbox.lowerleft.y = copyobj->bbox.lowerleft.y;
+ newobj->bbox.width = copyobj->bbox.width;
+ newobj->bbox.height = copyobj->bbox.height;
+
+ newobj->passed = NULL;
+ copyalleparams((genericptr)newobj, (genericptr)copyobj);
+
+ newobj->params = NULL;
+ copyparams(newobj, copyobj);
+
+ /* If the parameters are the same, the bounding box should be, too. */
+ if (copyobj->schembbox != NULL) {
+ newobj->schembbox = (BBox *)malloc(sizeof(BBox));
+ newobj->schembbox->lowerleft.x = copyobj->schembbox->lowerleft.x;
+ newobj->schembbox->lowerleft.y = copyobj->schembbox->lowerleft.y;
+ newobj->schembbox->width = copyobj->schembbox->width;
+ newobj->schembbox->height = copyobj->schembbox->height;
+ }
+ else
+ newobj->schembbox = NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* The method for removing objects from a list is to add the */
+/* value REMOVE_TAG to the type of each object needing to be */
+/* removed, and then calling this routine. */
+/*--------------------------------------------------------------*/
+
+void delete_tagged(objinstptr thisinst) {
+ Boolean tagged = True;
+ objectptr thisobject, delobj;
+ genericptr *pgen;
+ short *sobj, stmp;
+
+ thisobject = thisinst->thisobject;
+
+ while (tagged) {
+ tagged = False;
+ for (stmp = 0; stmp < thisobject->parts; stmp++) {
+ pgen = thisobject->plist + stmp;
+ if ((*pgen)->type & REMOVE_TAG) {
+ (*pgen)->type &= (~REMOVE_TAG);
+ tagged = True;
+
+ delobj = delete_element(thisinst, &stmp, 1, 0);
+ register_for_undo(XCF_Delete, UNDO_MORE, thisinst, delobj, 0);
+
+ /* If we destroy elements in the current window, we need to */
+ /* make sure that the selection list is updated appropriately. */
+
+ if ((thisobject == topobject) && (areawin->selects > 0)) {
+ for (sobj = areawin->selectlist; sobj < areawin->selectlist +
+ areawin->selects; sobj++)
+ if (*sobj > stmp) (*sobj)--;
+ }
+
+ /* Also ensure that this element is not referenced in any */
+ /* netlist. If it is, remove it and mark the netlist as */
+ /* invalid. */
+
+ remove_netlist_element(thisobject, *pgen);
+ }
+ }
+ }
+ undo_finish_series();
+}
+
+/*-----------------------------------------------------------------*/
+/* For copying: Check if an object is about to be placed directly */
+/* on top of the same object. If so, delete the one underneath. */
+/*-----------------------------------------------------------------*/
+
+void checkoverlap()
+{
+ short *sobj, *cobj;
+ genericptr *sgen, *pgen;
+ Boolean tagged = False;
+
+ /* Work through the select list */
+
+ for (sobj = areawin->selectlist; sobj < areawin->selectlist +
+ areawin->selects; sobj++) {
+ sgen = topobject->plist + (*sobj);
+
+ /* For each object being copied, compare it against every object */
+ /* on the current page (except self). Flag if it's the same. */
+
+ for (pgen = topobject->plist; pgen < topobject->plist + topobject->parts;
+ pgen++) {
+ if (pgen == sgen) continue;
+ if (compare_single(sgen, pgen)) {
+ /* Make sure that this object is not part of the selection, */
+ /* else chaos will reign. */
+ for (cobj = areawin->selectlist; cobj < areawin->selectlist +
+ areawin->selects; cobj++) {
+ if (pgen == topobject->plist + (*cobj)) break;
+ }
+ /* Tag it for future deletion and prevent further compares */
+ if (cobj == areawin->selectlist + areawin->selects) {
+ tagged = True;
+ (*pgen)->type |= REMOVE_TAG;
+ }
+ }
+ }
+ }
+ if (tagged) {
+ /* Delete the tagged elements */
+ Wprintf("Duplicate object deleted");
+ delete_tagged(areawin->topinstance);
+ incr_changes(topobject);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Direct placement of elements. Assumes that the selectlist */
+/* contains all the elements to be positioned. "deltax" and */
+/* "deltay" are relative x and y positions to move the */
+/* elements. */
+/*--------------------------------------------------------------*/
+
+void placeselects(short deltax, short deltay, XPoint *userpt)
+{
+ short *dragselect;
+ XPoint newpos, *ppt;
+ int rot;
+ short closest, cycle;
+ Boolean doattach;
+ genericptr *pgen;
+ polyptr cpoly;
+ pointselect *cptr;
+
+ doattach = ((userpt == NULL) || (areawin->attachto < 0)) ? FALSE : TRUE;
+
+ /* under attachto condition, keep element attached to */
+ /* the attachto element. */
+
+ if (doattach) findattach(&newpos, &rot, userpt);
+
+ areawin->clipped = -1; /* Prevent clipping */
+ for (dragselect = areawin->selectlist; dragselect < areawin->selectlist
+ + areawin->selects; dragselect++) {
+
+ switch(SELECTTYPE(dragselect)) {
+ case OBJINST: {
+ objinstptr draginst = SELTOOBJINST(dragselect);
+
+ UDrawObject(draginst, SINGLE, DOFORALL,
+ xobjs.pagelist[areawin->page]->wirewidth, NULL);
+ if (doattach) {
+ draginst->position.x = newpos.x;
+ draginst->position.y = newpos.y;
+ while (rot >= 360) rot -= 360;
+ while (rot < 0) rot += 360;
+ draginst->rotation = rot;
+ }
+ else {
+ draginst->position.x += deltax;
+ draginst->position.y += deltay;
+ }
+ UDrawObject(draginst, SINGLE, DOFORALL,
+ xobjs.pagelist[areawin->page]->wirewidth, NULL);
+
+ } break;
+ case GRAPHIC: {
+ graphicptr dragg = SELTOGRAPHIC(dragselect);
+ UDrawGraphic(dragg);
+ dragg->position.x += deltax;
+ dragg->position.y += deltay;
+ UDrawGraphic(dragg);
+ } break;
+ case LABEL: {
+ labelptr draglabel = SELTOLABEL(dragselect);
+ UDrawString(draglabel, DOFORALL, areawin->topinstance);
+ if (draglabel->pin == False)
+ UDrawX(draglabel);
+ if (doattach) {
+ draglabel->position.x = newpos.x;
+ draglabel->position.y = newpos.y;
+ draglabel->rotation = rot;
+ }
+ else {
+ draglabel->position.x += deltax;
+ draglabel->position.y += deltay;
+ }
+ UDrawString(draglabel, DOFORALL, areawin->topinstance);
+ if (draglabel->pin == False)
+ UDrawX(draglabel);
+ } break;
+ case PATH: {
+ pathptr dragpath = SELTOPATH(dragselect);
+ genericptr *pathlist;
+
+ UDrawPath(dragpath, xobjs.pagelist[areawin->page]->wirewidth);
+ if (doattach) {
+ XPoint *pdelta = pathclosepoint(dragpath, &newpos);
+ deltax = newpos.x - pdelta->x;
+ deltay = newpos.y - pdelta->y;
+ }
+ for (pathlist = dragpath->plist; pathlist < dragpath->plist
+ + dragpath->parts; pathlist++) {
+ movepoints(pathlist, deltax, deltay);
+ }
+ UDrawPath(dragpath, xobjs.pagelist[areawin->page]->wirewidth);
+ } break;
+ case POLYGON: {
+ polyptr dragpoly = SELTOPOLY(dragselect);
+ pointlist dragpoints;
+
+ // if (dragpoly->cycle != NULL) continue;
+ UDrawPolygon(dragpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ if (doattach) {
+ closest = closepoint(dragpoly, &newpos);
+ deltax = newpos.x - dragpoly->points[closest].x;
+ deltay = newpos.y - dragpoly->points[closest].y;
+ }
+ for (dragpoints = dragpoly->points; dragpoints < dragpoly->points
+ + dragpoly->number; dragpoints++) {
+ dragpoints->x += deltax;
+ dragpoints->y += deltay;
+ }
+ UDrawPolygon(dragpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ } break;
+ case SPLINE: {
+ splineptr dragspline = SELTOSPLINE(dragselect);
+ short j;
+ fpointlist dragpoints;
+
+ // if (dragspline->cycle != NULL) continue;
+ UDrawSpline(dragspline, xobjs.pagelist[areawin->page]->wirewidth);
+ if (doattach) {
+ closest = (wirelength(&dragspline->ctrl[0], &newpos)
+ > wirelength(&dragspline->ctrl[3], &newpos)) ? 3 : 0;
+ deltax = newpos.x - dragspline->ctrl[closest].x;
+ deltay = newpos.y - dragspline->ctrl[closest].y;
+ }
+ for (dragpoints = dragspline->points; dragpoints < dragspline->
+ points + INTSEGS; dragpoints++) {
+ dragpoints->x += deltax;
+ dragpoints->y += deltay;
+ }
+ for (j = 0; j < 4; j++) {
+ dragspline->ctrl[j].x += deltax;
+ dragspline->ctrl[j].y += deltay;
+ }
+ UDrawSpline(dragspline, xobjs.pagelist[areawin->page]->wirewidth);
+ } break;
+ case ARC: {
+ arcptr dragarc = SELTOARC(dragselect);
+ fpointlist dragpoints;
+
+ UDrawArc(dragarc, xobjs.pagelist[areawin->page]->wirewidth);
+ if (doattach) {
+ deltax = newpos.x - dragarc->position.x;
+ deltay = newpos.y - dragarc->position.y;
+ }
+ dragarc->position.x += deltax;
+ dragarc->position.y += deltay;
+ for (dragpoints = dragarc->points; dragpoints < dragarc->
+ points + dragarc->number; dragpoints++) {
+ dragpoints->x += deltax;
+ dragpoints->y += deltay;
+ }
+ UDrawArc(dragarc, xobjs.pagelist[areawin->page]->wirewidth);
+ } break;
+ }
+ }
+
+ if (areawin->pinattach) {
+ for (pgen = topobject->plist; pgen < topobject->plist +
+ topobject->parts; pgen++) {
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ cpoly = TOPOLY(pgen);
+ if (cpoly->cycle != NULL) {
+ ppt = cpoly->points + cpoly->cycle->number;
+ UDrawPolygon(cpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ newpos.x = ppt->x + deltax;
+ newpos.y = ppt->y + deltay;
+ if (areawin->manhatn)
+ manhattanize(&newpos, cpoly, cpoly->cycle->number, FALSE);
+ ppt->x = newpos.x;
+ ppt->y = newpos.y;
+ UDrawPolygon(cpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ }
+ }
+ }
+ areawin->clipped = 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Copy handler. Assumes that the selectlist contains the elements */
+/* to be copied, and that the initial position of the copy is held */
+/* in areawin->save. */
+/*----------------------------------------------------------------------*/
+
+void createcopies()
+{
+ short *selectobj;
+
+ if (!checkselect_draw(ALL_TYPES, True)) return;
+ u2u_snap(&areawin->save);
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+
+ /* Cycles will not be used for copy mode: remove them */
+ removecycle(topobject->plist + (*selectobj));
+
+ switch(SELECTTYPE(selectobj)) {
+ case LABEL: { /* copy label */
+ labelptr copytext = SELTOLABEL(selectobj);
+ labelptr *newtext;
+
+ NEW_LABEL(newtext, topobject);
+ labelcopy(*newtext, copytext);
+ } break;
+ case OBJINST: { /* copy object instance */
+ objinstptr copyobj = SELTOOBJINST(selectobj);
+ objinstptr *newobj;
+ NEW_OBJINST(newobj, topobject);
+ instcopy(*newobj, copyobj);
+ } break;
+ case GRAPHIC: { /* copy graphic instance */
+ graphicptr copyg = SELTOGRAPHIC(selectobj);
+ graphicptr *newg;
+ NEW_GRAPHIC(newg, topobject);
+ graphiccopy(*newg, copyg);
+ } break;
+ case PATH: { /* copy path */
+ pathptr copypath = SELTOPATH(selectobj);
+ pathptr *newpath;
+ NEW_PATH(newpath, topobject);
+ pathcopy(*newpath, copypath);
+ } break;
+ case ARC: { /* copy arc */
+ arcptr copyarc = SELTOARC(selectobj);
+ arcptr *newarc;
+ NEW_ARC(newarc, topobject);
+ arccopy(*newarc, copyarc);
+ } break;
+ case POLYGON: { /* copy polygons */
+ polyptr copypoly = SELTOPOLY(selectobj);
+ polyptr *newpoly;
+ NEW_POLY(newpoly, topobject);
+ polycopy(*newpoly, copypoly);
+ } break;
+ case SPLINE: { /* copy spline */
+ splineptr copyspline = SELTOSPLINE(selectobj);
+ splineptr *newspline;
+ NEW_SPLINE(newspline, topobject);
+ splinecopy(*newspline, copyspline);
+ } break;
+ }
+
+ /* change selection from the old to the new object */
+
+ *selectobj = topobject->parts - 1;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Function which initiates interactive placement of copied */
+/* elements. */
+/*--------------------------------------------------------------*/
+
+void copydrag()
+{
+ short *selectobj;
+
+ if (areawin->selects > 0) {
+ /* Put all selected objects into the "select" color */
+
+ SetFunction(dpy, areawin->gc, GXxor);
+ for (selectobj = areawin->selectlist; selectobj < areawin->selectlist
+ + areawin->selects; selectobj++) {
+ XSetXORFg(SELTOCOLOR(selectobj), BACKGROUND);
+ easydraw(*selectobj, DOFORALL);
+ }
+
+ if (eventmode == NORMAL_MODE) {
+ XDefineCursor(dpy, areawin->window, COPYCURSOR);
+ eventmode = COPY_MODE;
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ XtAddEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False, (XtEventHandler)xlib_drag,
+ NULL);
+#endif
+ }
+ select_invalidate_netlist();
+ }
+}
+
+/*-----------------------------------------------------------*/
+/* Copy handler for copying from a button push or key event. */
+/*-----------------------------------------------------------*/
+
+void copy_op(int op, int x, int y)
+{
+ short *csel;
+
+ if (op == XCF_Copy) {
+ window_to_user(x, y, &areawin->save);
+ createcopies(); /* This function does all the hard work */
+ copydrag(); /* Start interactive placement */
+ }
+ else {
+ eventmode = NORMAL_MODE;
+ areawin->attachto = -1;
+ W3printf("");
+#ifdef TCL_WRAPPER
+ xcRemoveEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False, (xcEventHandler)xctk_drag,
+ NULL);
+#else
+ xcRemoveEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+ u2u_snap(&areawin->save);
+ if (op == XCF_Cancel) {
+ delete_noundo(NORMAL);
+
+ /* Redraw the screen so that an object directly under */
+ /* the delete object won't get painted black */
+
+ drawarea(NULL, NULL, NULL);
+ }
+ else if (op == XCF_Finish_Copy) {
+ /* If selected objects are the only ones on the page, */
+ /* then do a full bbox calculation. */
+ if (topobject->parts == areawin->selects)
+ calcbbox(areawin->topinstance);
+ else
+ calcbboxselect();
+ checkoverlap();
+ register_for_undo(XCF_Copy, UNDO_MORE, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+ unselect_all();
+ incr_changes(topobject);
+ }
+ else { /* XCF_Continue_Copy */
+ SetFunction(dpy, areawin->gc, GXcopy);
+ SetForeground(dpy, areawin->gc, SELECTCOLOR);
+ for (csel = areawin->selectlist; csel < areawin->selectlist +
+ areawin->selects; csel++)
+ easydraw(*csel, DOFORALL);
+ if (topobject->parts == areawin->selects)
+ calcbbox(areawin->topinstance);
+ else
+ calcbboxselect();
+ checkoverlap();
+ register_for_undo(XCF_Copy, UNDO_DONE, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+ createcopies();
+ copydrag(); /* Start interactive placement again */
+ incr_changes(topobject);
+ }
+ }
+}
+
+/*----------------------------------------------*/
+/* Check for more than one button being pressed */
+/*----------------------------------------------*/
+
+Boolean checkmultiple(XButtonEvent *event)
+{
+ int state = Button1Mask | Button2Mask | Button3Mask |
+ Button4Mask | Button5Mask;
+ state &= event->state;
+ /* ((x - 1) & x) is always non-zero if x has more than one bit set */
+ return (((state - 1) & state) == 0) ? False : True;
+}
+
+/*----------------------------------------------------------------------*/
+/* Operation continuation---dependent upon the ongoing operation. */
+/* This operation only pertains to a few event modes for which */
+/* continuation of action makes sense---drawing wires (polygons), and */
+/* editing polygons, arcs, splines, and paths. */
+/*----------------------------------------------------------------------*/
+
+void continue_op(int op, int x, int y)
+{
+ XPoint ppos;
+
+ if (eventmode != EARC_MODE && eventmode != ARC_MODE) {
+ window_to_user(x, y, &areawin->save);
+ }
+ snap(x, y, &ppos);
+ printpos(ppos.x, ppos.y);
+
+ switch(eventmode) {
+ case(COPY_MODE):
+ copy_op(op, x, y);
+ break;
+ case(WIRE_MODE):
+ wire_op(op, x, y);
+ break;
+ case(EPATH_MODE): case(EPOLY_MODE): case (ARC_MODE):
+ case(EARC_MODE): case(SPLINE_MODE): case(ESPLINE_MODE):
+ path_op(*(EDITPART), op, x, y);
+ break;
+ case(EINST_MODE):
+ inst_op(*(EDITPART), op, x, y);
+ break;
+ case(BOX_MODE):
+ finish_op(XCF_Finish_Element, x, y);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Finish or cancel an operation. This forces a return to */
+/* "normal" mode, with whatever other side effects are caused */
+/* by the operation. */
+/*--------------------------------------------------------------*/
+
+void finish_op(int op, int x, int y)
+{
+ labelptr curlabel;
+ int libnum;
+ XPoint snappt, boxpts[4];
+ float fscale;
+
+ if (eventmode != EARC_MODE && eventmode != ARC_MODE) {
+ window_to_user(x, y, &areawin->save);
+ }
+ switch(eventmode) {
+ case(EPATH_MODE): case(BOX_MODE): case(EPOLY_MODE): case (ARC_MODE):
+ case(EARC_MODE): case(SPLINE_MODE): case(ESPLINE_MODE):
+ path_op(*(EDITPART), op, x, y);
+ break;
+
+ case(EINST_MODE):
+ inst_op(*(EDITPART), op, x, y);
+ break;
+
+ case (FONTCAT_MODE):
+ case (EFONTCAT_MODE):
+ fontcat_op(op, x, y);
+ eventmode = (eventmode == FONTCAT_MODE) ? TEXT_MODE : ETEXT_MODE;
+ XDefineCursor (dpy, areawin->window, TEXTPTR);
+ break;
+
+ case(ASSOC_MODE):
+ case(CATALOG_MODE):
+ catalog_op(op, x, y);
+ break;
+
+ case(WIRE_MODE):
+ wire_op(op, x, y);
+ break;
+
+ case(COPY_MODE):
+ copy_op(op, x, y);
+ break;
+
+ case(TEXT_MODE):
+ curlabel = TOLABEL(EDITPART);
+ UDrawTLine(curlabel);
+ if (op == XCF_Cancel) {
+ redrawtext(curlabel);
+ freelabel(curlabel->string);
+ free(curlabel);
+ topobject->parts--;
+ curlabel = NULL;
+ }
+ else {
+ singlebbox(EDITPART);
+ incr_changes(topobject);
+ select_invalidate_netlist();
+ }
+ setdefaultfontmarks();
+ eventmode = NORMAL_MODE;
+ break;
+
+ case(ETEXT_MODE): case(CATTEXT_MODE):
+ curlabel = TOLABEL(EDITPART);
+ UDrawTLine(curlabel);
+ if (op == XCF_Cancel) {
+ /* restore the original text */
+ undrawtext(curlabel);
+ undo_finish_series();
+ undo_action();
+ if (eventmode == CATTEXT_MODE) eventmode = CATALOG_MODE;
+ redrawtext(curlabel);
+ W3printf("");
+ setdefaultfontmarks();
+ }
+ else textreturn(); /* Generate "return" key character */
+ areawin->textend = 0;
+ break;
+
+ case(CATMOVE_MODE):
+ u2u_snap(&areawin->save);
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcRemoveEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, FALSE, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ if (op == XCF_Cancel) {
+ /* Just regenerate the library where we started */
+ if (areawin->selects >= 1) {
+ objinstptr selinst = SELTOOBJINST(areawin->selectlist);
+ libnum = libfindobject(selinst->thisobject, NULL);
+ if (libnum >= 0)
+ composelib(libnum + LIBRARY);
+ }
+ }
+ else {
+ catmove(x, y);
+ }
+ clearselects();
+ eventmode = CATALOG_MODE;
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+ break;
+
+ case(MOVE_MODE):
+ u2u_snap(&areawin->save);
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcRemoveEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, FALSE, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ if (op == XCF_Cancel) {
+ /* If we came from the library with an object instance, in */
+ /* MOVE_MODE, then "cancel" should delete the element. */
+ /* Otherwise, put the position of the element back to what */
+ /* it was before we started the move. The difference is */
+ /* indicated by the value of areawin->editpart. */
+
+ if ((areawin->selects > 0) && (*areawin->selectlist == topobject->parts))
+ delete_noundo(NORMAL);
+ else
+ placeselects(areawin->origin.x - areawin->save.x,
+ areawin->origin.y - areawin->save.y, NULL);
+ clearselects();
+ drawarea(NULL, NULL, NULL);
+ }
+ else {
+ if (areawin->selects > 0) {
+ register_for_undo(XCF_Move,
+ // (was_preselected) ? UNDO_DONE : UNDO_MORE,
+ UNDO_MORE,
+ areawin->topinstance,
+ (int)(areawin->save.x - areawin->origin.x),
+ (int)(areawin->save.y - areawin->origin.y));
+ pwriteback(areawin->topinstance);
+ incr_changes(topobject);
+ select_invalidate_netlist();
+ unselect_all(); // The way it used to be. . .
+ }
+ W3printf("");
+ /* full calc needed: move may shrink bbox */
+ calcbbox(areawin->topinstance);
+ checkoverlap();
+ // if (!was_preselected) clearselects();
+ }
+ areawin->attachto = -1;
+ break;
+
+ case(RESCALE_MODE):
+
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcRemoveEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, FALSE, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ if (op != XCF_Cancel) {
+ fscale = UDrawRescaleBox(&areawin->save);
+ if (fscale != 0.0) elementrescale(fscale);
+ }
+ eventmode = NORMAL_MODE;
+ break;
+
+ case(SELAREA_MODE):
+ UDrawBox(areawin->origin, areawin->save);
+
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcRemoveEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, FALSE, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ /* Zero-width boxes act like a normal selection. Otherwise, */
+ /* proceed with the area select. */
+
+ if ((areawin->origin.x == areawin->save.x) &&
+ (areawin->origin.y == areawin->save.y))
+ select_add_element(ALL_TYPES);
+ else {
+ boxpts[0] = areawin->origin;
+ boxpts[1].x = areawin->save.x;
+ boxpts[1].y = areawin->origin.y;
+ boxpts[2] = areawin->save;
+ boxpts[3].x = areawin->origin.x;
+ boxpts[3].y = areawin->save.y;
+ selectarea(topobject, boxpts, 0);
+ }
+ break;
+
+ case(PAN_MODE):
+ u2u_snap(&areawin->save);
+
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#else
+ xcRemoveEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+ if (op != XCF_Cancel)
+ panbutton((u_int) 5, (areawin->width >> 1) - (x - areawin->origin.x),
+ (areawin->height >> 1) - (y - areawin->origin.y), 0);
+ break;
+ }
+
+ /* Remove any selections */
+ if ((eventmode == SELAREA_MODE) || (eventmode == PAN_MODE)
+ || (eventmode == MOVE_MODE))
+ eventmode = NORMAL_MODE;
+ else if (eventmode != MOVE_MODE && eventmode != EPATH_MODE &&
+ eventmode != EPOLY_MODE && eventmode != ARC_MODE &&
+ eventmode != EARC_MODE && eventmode != SPLINE_MODE &&
+ eventmode != ESPLINE_MODE && eventmode != WIRE_MODE &&
+ eventmode != ETEXT_MODE && eventmode != TEXT_MODE) {
+ unselect_all();
+ }
+
+ if (eventmode == NORMAL_MODE) {
+
+ /* Return any highlighted networks to normal */
+ highlightnetlist(topobject, areawin->topinstance, 0);
+
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+
+#ifdef DOUBLEBUFFER
+ drawarea(NULL, NULL, NULL);
+#endif
+ }
+
+ snap(x, y, &snappt);
+ printpos(snappt.x, snappt.y);
+}
+
+/*--------------------------------------------------------------*/
+/* Edit operations for instances. This is used to allow */
+/* numeric parameters to be adjusted from the hierarchical */
+/* level above, shielding the the unparameterized parts from */
+/* change. */
+/*--------------------------------------------------------------*/
+
+void inst_op(genericptr editpart, int op, int x, int y)
+{
+}
+
+/*--------------------------------------------------------------*/
+/* Operations for path components */
+/*--------------------------------------------------------------*/
+
+void path_op(genericptr editpart, int op, int x, int y)
+{
+ polyptr newpoly;
+ splineptr newspline;
+ genericptr *ggen;
+ Boolean donecycles = False;
+ XPoint *refpt, *cptr;
+
+ /* Don't allow point cycling in a multi-part edit. */
+ /* Allowing it is just confusing. Instead, we treat */
+ /* button 1 (cycle) like button 2 (finish). */
+ if (op == XCF_Continue_Element && areawin->selects > 1)
+ op = XCF_Finish_Element;
+
+ switch(ELEMENTTYPE(editpart)) {
+ case (PATH): {
+ pathptr newpath = (pathptr)editpart;
+ short dotrack = True;
+ pathptr editpath;
+
+ areawin->attachto = -1;
+
+ if (op != XCF_Continue_Element) {
+ dotrack = False;
+ UDrawPath(newpath, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ if (op == XCF_Continue_Element) {
+ nextpathcycle(newpath, 1);
+ patheditpush(newpath);
+ }
+ else if (op == XCF_Finish_Element) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newpath->color);
+ UDrawPath(newpath, xobjs.pagelist[areawin->page]->wirewidth);
+ incr_changes(topobject);
+ }
+ else { /* restore previous path from edit stack */
+ free_single((genericptr)newpath);
+ if (areawin->editstack->parts > 0) {
+ if (op == XCF_Cancel) {
+ editpath = TOPATH(areawin->editstack->plist);
+ pathcopy(newpath, editpath);
+ reset(areawin->editstack, NORMAL);
+ }
+ else {
+ editpath = TOPATH(areawin->editstack->plist +
+ areawin->editstack->parts - 1);
+ pathcopy(newpath, editpath);
+ free_single((genericptr)editpath);
+ free(editpath);
+ areawin->editstack->parts--;
+ }
+ if (areawin->editstack->parts > 0) {
+ dotrack = True;
+ nextpathcycle(newpath, 1);
+ }
+ else {
+ XPoint warppt;
+
+ XcSetFunction(GXcopy);
+ XcTopSetForeground(newpath->color);
+ user_to_window(areawin->origin, &warppt);
+ warppointer(warppt.x, warppt.y);
+ }
+ UDrawPath(newpath, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else {
+ topobject->parts--;
+ free_single((genericptr)newpath);
+ free(newpath);
+ }
+ }
+ pwriteback(areawin->topinstance);
+
+ if (!dotrack) {
+ /* Free the editstack */
+ reset(areawin->editstack, NORMAL);
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = NORMAL_MODE;
+ donecycles = True;
+ }
+ } break;
+
+ case (POLYGON): {
+ if (eventmode == BOX_MODE) {
+ polyptr newbox;
+
+ newbox = (polyptr)editpart;
+ UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth);
+
+ /* prevent length and/or width zero boxes */
+ if (newbox->points->x != (newbox->points + 2)->x && (newbox->points
+ + 1)->y != (newbox->points + 3)->y) {
+ if (op != XCF_Cancel) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newbox->color);
+ UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth);
+ incr_changes(topobject);
+ if (!nonnetwork(newbox)) invalidate_netlist(topobject);
+ register_for_undo(XCF_Box, UNDO_MORE, areawin->topinstance,
+ newbox);
+ }
+ else {
+ free_single((genericptr)newbox);
+ free(newbox);
+ topobject->parts--;
+ }
+ }
+ else {
+ free_single((genericptr)newbox);
+ free(newbox);
+ topobject->parts--;
+ }
+
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackbox, NULL);
+ eventmode = NORMAL_MODE;
+ }
+ else { /* EPOLY_MODE */
+ polyptr editpoly;
+ short dotrack = True;
+
+ newpoly = (polyptr)editpart;
+ areawin->attachto = -1;
+
+ if (op != XCF_Continue_Element) {
+ dotrack = False;
+ UDrawPolygon(newpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+
+ if (op == XCF_Continue_Element) {
+ nextpolycycle(&newpoly, 1);
+ polyeditpush(newpoly);
+ }
+ else if (op == XCF_Finish_Element) {
+
+ /* Check for degenerate polygons (all points the same). */
+ int i;
+ for (i = 1; i < newpoly->number; i++)
+ if ((newpoly->points[i].x != newpoly->points[i - 1].x) ||
+ (newpoly->points[i].y != newpoly->points[i - 1].y))
+ break;
+ if (i == newpoly->number) {
+ /* Remove this polygon with the standard delete */
+ /* method (saves polygon on undo stack). */
+ newpoly->type |= REMOVE_TAG;
+ delete_tagged(areawin->topinstance);
+ }
+ else {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newpoly->color);
+ UDrawPolygon(newpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ if (!nonnetwork(newpoly)) invalidate_netlist(topobject);
+ incr_changes(topobject);
+ }
+ }
+ else {
+ XPoint warppt;
+ free_single((genericptr)newpoly);
+ if (areawin->editstack->parts > 0) {
+ if (op == XCF_Cancel) {
+ editpoly = TOPOLY(areawin->editstack->plist);
+ polycopy(newpoly, editpoly);
+ reset(areawin->editstack, NORMAL);
+ }
+ else {
+ editpoly = TOPOLY(areawin->editstack->plist +
+ areawin->editstack->parts - 1);
+ polycopy(newpoly, editpoly);
+ free_single((genericptr)editpoly);
+ free(editpoly);
+ areawin->editstack->parts--;
+ }
+ if (areawin->editstack->parts > 0) {
+ dotrack = True;
+ nextpolycycle(&newpoly, -1);
+ }
+ else {
+ XcSetFunction(GXcopy);
+ XcTopSetForeground(newpoly->color);
+ user_to_window(areawin->origin, &warppt);
+ warppointer(warppt.x, warppt.y);
+ }
+ UDrawPolygon(newpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else {
+ topobject->parts--;
+ free(newpoly);
+ }
+ }
+ pwriteback(areawin->topinstance);
+
+ if (!dotrack) {
+ /* Free the editstack */
+ reset(areawin->editstack, NORMAL);
+
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = NORMAL_MODE;
+ donecycles = True;
+ }
+ }
+ } break;
+
+ case (ARC): {
+ arcptr newarc, editarc;
+ short dotrack = True;
+
+ newarc = (arcptr)editpart;
+
+ if (op != XCF_Continue_Element) {
+ dotrack = False;
+ UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth);
+ UDrawXLine(areawin->save, newarc->position);
+ }
+
+ if (op == XCF_Continue_Element) {
+ nextarccycle(&newarc, 1);
+ arceditpush(newarc);
+ }
+
+ else if (op == XCF_Finish_Element) {
+ dotrack = False;
+
+ if (newarc->radius != 0 && newarc->yaxis != 0 &&
+ (newarc->angle1 != newarc->angle2)) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newarc->color);
+ incr_changes(topobject);
+ if (eventmode == ARC_MODE) {
+ register_for_undo(XCF_Arc, UNDO_MORE, areawin->topinstance,
+ newarc);
+ }
+ UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth);
+
+ }
+ else {
+
+ /* Remove the record if the radius is zero. If we were */
+ /* creating the arc, just delete it; it's as if it */
+ /* never existed. If we were editing an arc, use the */
+ /* standard delete method (saves arc on undo stack). */
+
+ if (eventmode == ARC_MODE) {
+ free_single((genericptr)newarc);
+ free(newarc);
+ topobject->parts--;
+ }
+ else {
+ newarc->type |= REMOVE_TAG;
+ delete_tagged(areawin->topinstance);
+ }
+ }
+ }
+ else { /* Cancel: restore previous arc from edit stack */
+ free_single((genericptr)newarc);
+ if (areawin->editstack->parts > 0) {
+ if (op == XCF_Cancel) {
+ editarc = TOARC(areawin->editstack->plist);
+ arccopy(newarc, editarc);
+ copycycles(&(newarc->cycle), &(editarc->cycle));
+ reset(areawin->editstack, NORMAL);
+ }
+ else {
+ editarc = TOARC(areawin->editstack->plist +
+ areawin->editstack->parts - 1);
+ arccopy(newarc, editarc);
+ copycycles(&(newarc->cycle), &(editarc->cycle));
+ free_single((genericptr)editarc);
+ free(editarc);
+ areawin->editstack->parts--;
+ }
+ if (areawin->editstack->parts > 0) {
+ dotrack = True;
+ nextarccycle(&newarc, -1);
+ UDrawXLine(areawin->save, newarc->position);
+ }
+ else {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newarc->color);
+ if (eventmode != ARC_MODE) {
+ XPoint warppt;
+ user_to_window(areawin->origin, &warppt);
+ warppointer(warppt.x, warppt.y);
+ }
+ }
+ UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else
+ topobject->parts--;
+ }
+ pwriteback(areawin->topinstance);
+
+ if (!dotrack) {
+ /* Free the editstack */
+ reset(areawin->editstack, NORMAL);
+
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackarc, NULL);
+ eventmode = NORMAL_MODE;
+ }
+ } break;
+
+ case (SPLINE): {
+ splineptr editspline;
+ short dotrack = True;
+
+ newspline = (splineptr)editpart;
+
+ if (op != XCF_Continue_Element) {
+ UDrawSpline(newspline, xobjs.pagelist[areawin->page]->wirewidth);
+ dotrack = False;
+ }
+
+ if (op == XCF_Continue_Element) {
+ /* Note: we work backwards through spline control points. */
+ /* The reason is that when creating a spline, the sudden */
+ /* move from the endpoint to the startpoint (forward */
+ /* direction) is more disorienting than moving from the */
+ /* endpoint to the endpoint's control point. */
+
+ nextsplinecycle(&newspline, -1);
+ splineeditpush(newspline);
+ }
+
+ /* unlikely but possible to create zero-length splines */
+ else if (newspline->ctrl[0].x != newspline->ctrl[3].x ||
+ newspline->ctrl[0].x != newspline->ctrl[1].x ||
+ newspline->ctrl[0].x != newspline->ctrl[2].x ||
+ newspline->ctrl[0].y != newspline->ctrl[3].y ||
+ newspline->ctrl[0].y != newspline->ctrl[1].y ||
+ newspline->ctrl[0].y != newspline->ctrl[2].y) {
+ if (op == XCF_Finish_Element) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newspline->color);
+ incr_changes(topobject);
+ if (eventmode == SPLINE_MODE) {
+ register_for_undo(XCF_Spline, UNDO_MORE, areawin->topinstance,
+ newspline);
+ }
+ UDrawSpline(newspline, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else { /* restore previous spline from edit stack */
+ free_single((genericptr)newspline);
+ if (areawin->editstack->parts > 0) {
+ if (op == XCF_Cancel) {
+ editspline = TOSPLINE(areawin->editstack->plist);
+ splinecopy(newspline, editspline);
+ reset(areawin->editstack, NORMAL);
+ }
+ else {
+ editspline = TOSPLINE(areawin->editstack->plist +
+ areawin->editstack->parts - 1);
+ splinecopy(newspline, editspline);
+ free_single((genericptr)editspline);
+ free(editspline);
+ areawin->editstack->parts--;
+ }
+ if (areawin->editstack->parts > 0) {
+ dotrack = True;
+ nextsplinecycle(&newspline, 1);
+ UDrawSpline(newspline, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(newspline->color);
+ if (eventmode != SPLINE_MODE) {
+ XPoint warppt;
+ user_to_window(areawin->origin, &warppt);
+ warppointer(warppt.x, warppt.y);
+ }
+ UDrawSpline(newspline, xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ }
+ else
+ topobject->parts--;
+ }
+ }
+ else {
+ free_single((genericptr)newspline);
+ free(newspline);
+ topobject->parts--;
+ }
+ pwriteback(areawin->topinstance);
+
+ if (!dotrack) {
+ /* Free the editstack */
+ reset(areawin->editstack, NORMAL);
+
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)trackelement, NULL);
+ eventmode = NORMAL_MODE;
+ donecycles = True;
+ }
+ } break;
+ }
+ calcbbox(areawin->topinstance);
+
+ /* Multiple-element edit: Some items may have been moved as */
+ /* opposed to edited, and should be registered here. To do */
+ /* this correctly, we must first unselect the edited items, */
+ /* then register the move for the remaining items. */
+
+ if (donecycles) {
+ short *eselect, cycle, *sellist, *newsel, selects;
+ Boolean fullmove = False;
+
+ for (eselect = areawin->selectlist; eselect < areawin->selectlist +
+ areawin->selects; eselect++) {
+ cycle = checkcycle(SELTOGENERIC(eselect), 0);
+ if (cycle < 0) {
+ fullmove = True; /* At least 1 object moved */
+ break;
+ }
+ }
+
+ /* Remove all (remaining) cycles */
+ for (eselect = areawin->selectlist; eselect < areawin->selectlist +
+ areawin->selects; eselect++)
+ removecycle(SELTOGENERICPTR(eselect));
+
+ /* Remove edits from the undo stack when canceling */
+ if (op == XCF_Cancel || op == XCF_Cancel_Last) {
+ if (xobjs.undostack && (xobjs.undostack->type == XCF_Edit)) {
+ undo_finish_series();
+ undo_action();
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------*/
+/* Recalculate values for a drawing-area widget resizing */
+/*-------------------------------------------------------*/
+
+void resizearea(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+#ifndef TCL_WRAPPER
+ Arg wargs[2];
+#endif
+ XEvent discard;
+ int savewidth = areawin->width, saveheight = areawin->height;
+ XCWindowData *thiswin;
+ XGCValues values;
+
+ if ((dpy != NULL) && xcIsRealized(areawin->area)) {
+
+#ifdef TCL_WRAPPER
+ areawin->width = Tk_Width(w);
+ areawin->height = Tk_Height(w);
+#else
+ XtSetArg(wargs[0], XtNwidth, &areawin->width);
+ XtSetArg(wargs[1], XtNheight, &areawin->height);
+ XtGetValues(areawin->area, wargs, 2);
+#endif
+
+ if (areawin->width != savewidth || areawin->height != saveheight) {
+
+ int maxwidth = 0, maxheight = 0;
+ for (thiswin = xobjs.windowlist; thiswin != NULL; thiswin = thiswin->next) {
+ if (thiswin->width > maxwidth) maxwidth = thiswin->width;
+ if (thiswin->height > maxheight) maxheight = thiswin->height;
+ }
+#ifdef DOUBLEBUFFER
+ if (dbuf != (Pixmap)NULL) XFreePixmap(dpy, dbuf);
+ dbuf = XCreatePixmap(dpy, areawin->window, maxwidth, maxheight,
+ DefaultDepthOfScreen(xcScreen(w)));
+#endif
+ if (areawin->clipmask != (Pixmap)NULL) XFreePixmap(dpy, areawin->clipmask);
+ areawin->clipmask = XCreatePixmap(dpy, areawin->window,
+ maxwidth, maxheight, 1);
+
+ if (areawin->pbuf != (Pixmap)NULL) {
+ XFreePixmap(dpy, areawin->pbuf);
+ areawin->pbuf = XCreatePixmap(dpy, areawin->window,
+ maxwidth, maxheight, 1);
+ }
+
+ if (areawin->cmgc != (GC)NULL) XFreeGC(dpy, areawin->cmgc);
+ values.foreground = 0;
+ values.background = 0;
+ areawin->cmgc = XCreateGC(dpy, areawin->clipmask,
+ GCForeground | GCBackground, &values);
+
+ reset_gs();
+
+ /* Re-compose the directores to match the new dimensions */
+ composelib(LIBLIB);
+ composelib(PAGELIB);
+
+ /* Re-center image in resized window */
+ zoomview(NULL, NULL, NULL);
+ }
+
+ /* Flush all expose events from the buffer */
+
+ while (XCheckWindowEvent(dpy, areawin->window, ExposureMask, &discard) == True);
+ }
+}
+
+/*--------------------------------------*/
+/* Draw the primary graphics window */
+/*--------------------------------------*/
+
+void drawwindow(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ Window win, tmpwin;
+ float x, y, spc, spc2, i, j, fpart;
+ /*short *selectobj; (jdk) */
+ XPoint originpt;
+ XEvent discard;
+#ifdef OPENGL
+ GLsizei width, height;
+#endif
+
+ if (!xcIsRealized(areawin->area)) return;
+
+ newmatrix();
+
+#ifdef OPENGL
+ glXMakeCurrent(dpy, (GLXDrawable)areawin->window, grXcontext);
+ glDrawBuffer(GL_BACK);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ width = (GLsizei)Tk_Width(areawin->area);
+ height = (GLsizei)Tk_Height(areawin->area);
+
+ glViewport((GLsizei)0, (GLsizei)0, width, height);
+
+ /* Need to twiddle with these? */
+ glScalef(1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1), 1.0);
+ glTranslated(-(width >> 1), -(height >> 1), 0);
+
+ glClearColor(1.0, 1.0, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glEnable(GL_POINT_SMOOTH);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_POLYGON_SMOOTH);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ XcSetFunction(GXcopy);
+
+#else
+
+ XcSetFunction(GXcopy);
+
+#ifdef DOUBLEBUFFER
+ tmpwin = areawin->window;
+ win = (Window)dbuf;
+ areawin->window = win;
+ if (xobjs.pagelist[areawin->page]->background.name == (char *)NULL
+ || (copybackground() < 0)) {
+ XSetForeground(dpy, areawin->gc, BACKGROUND);
+ XFillRectangle(dpy, win, areawin->gc, 0, 0, areawin->width,
+ areawin->height);
+ }
+#else
+
+ if (xobjs.pagelist[areawin->page]->background.name != (char *)NULL)
+ copybackground();
+ else
+ XClearWindow(dpy, areawin->window);
+#endif
+
+#endif /* OPENGL */
+
+ win = areawin->window;
+
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapRound, JoinBevel);
+
+ /* draw GRIDCOLOR lines for grid; mark axes in AXESCOLOR */
+
+ if (eventmode != CATALOG_MODE && eventmode != ASSOC_MODE
+ && eventmode != FONTCAT_MODE && eventmode != EFONTCAT_MODE
+ && eventmode != CATMOVE_MODE && eventmode != CATTEXT_MODE) {
+
+ float major_snapspace, spc3;
+
+ spc = xobjs.pagelist[areawin->page]->gridspace * areawin->vscale;
+ if (areawin->gridon && spc > 8) {
+ fpart = (float)(-areawin->pcorner.x)
+ / xobjs.pagelist[areawin->page]->gridspace;
+ x = xobjs.pagelist[areawin->page]->gridspace *
+ (fpart - (float)((int)fpart)) * areawin->vscale;
+ fpart = (float)(-areawin->pcorner.y)
+ / xobjs.pagelist[areawin->page]->gridspace;
+ y = xobjs.pagelist[areawin->page]->gridspace *
+ (fpart - (float)((int)fpart)) * areawin->vscale;
+
+ SetForeground(dpy, areawin->gc, GRIDCOLOR);
+ for (i = x; i < (float)areawin->width; i += spc)
+ DrawLine (dpy, win, areawin->gc, (int)(i + 0.5),
+ 0, (int)(i + 0.5), areawin->height);
+ for (j = (float)areawin->height - y; j > 0; j -= spc)
+ DrawLine (dpy, win, areawin->gc, 0, (int)(j - 0.5),
+ areawin->width, (int)(j - 0.5));
+ };
+ if (areawin->axeson) {
+ XPoint zeropt;
+ zeropt.x = zeropt.y = 0;
+ SetForeground(dpy, areawin->gc, AXESCOLOR);
+ user_to_window(zeropt, &originpt);
+ DrawLine (dpy, win, areawin->gc, originpt.x, 0,
+ originpt.x, areawin->height);
+ DrawLine (dpy, win, areawin->gc, 0, originpt.y,
+ areawin->width, originpt.y);
+ }
+
+ /* bounding box goes beneath everything except grid/axis lines */
+ UDrawBBox();
+
+ /* draw a little red dot at each snap-to point */
+
+ spc2 = xobjs.pagelist[areawin->page]->snapspace * areawin->vscale;
+ if (areawin->snapto && spc2 > 8) {
+ float x2, y2;
+
+ fpart = (float)(-areawin->pcorner.x)
+ / xobjs.pagelist[areawin->page]->snapspace;
+ x2 = xobjs.pagelist[areawin->page]->snapspace *
+ (fpart - (float)((int)fpart)) * areawin->vscale;
+ fpart = (float)(-areawin->pcorner.y)
+ / xobjs.pagelist[areawin->page]->snapspace;
+ y2 = xobjs.pagelist[areawin->page]->snapspace *
+ (fpart - (float)((int)fpart)) * areawin->vscale;
+
+#if defined(TCL_WRAPPER) && defined(XC_WIN32) && defined(DOUBLEBUFFER)
+ {
+ HDC hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, Tk_GetHWND(win));
+#endif
+ SetForeground(dpy, areawin->gc, SNAPCOLOR);
+ for (i = x2; i < areawin->width; i += spc2)
+ for (j = areawin->height - y2; j > 0; j -= spc2)
+#if defined(TCL_WRAPPER) && defined(XC_WIN32) && defined(DOUBLEBUFFER)
+ SetPixelV(hdc, (int)(i + 0.5), (int)(j - 0.05), areawin->gc->foreground);
+#endif
+ DrawPoint (dpy, win, areawin->gc, (int)(i + 0.5),
+ (int)(j - 0.5));
+#if defined(TCL_WRAPPER) && defined(XC_WIN32) && defined(DOUBLEBUFFER)
+ DeleteDC(hdc);
+ }
+#endif
+ };
+
+ /* Draw major snap points (code contributed by John Barry) */
+
+ major_snapspace = xobjs.pagelist[areawin->page]->gridspace * 20;
+ spc3 = major_snapspace * areawin->vscale;
+ if (spc > 4) {
+ fpart = (float)(-areawin->pcorner.x) / major_snapspace;
+ x = major_snapspace * (fpart - (float)((int)fpart)) * areawin->vscale;
+ fpart = (float)(-areawin->pcorner.y) / major_snapspace;
+ y = major_snapspace * (fpart - (float)((int)fpart)) * areawin->vscale;
+
+ SetForeground(dpy, areawin->gc, GRIDCOLOR);
+ for (i = x; i < (float)areawin->width; i += spc3) {
+ for (j = (float)areawin->height - y; j > 0; j -= spc3) {
+ XDrawArc(dpy, win, areawin->gc, (int)(i + 0.5) - 1,
+ (int)(j - 0.5) - 1, 2, 2, 0, 360*64);
+ }
+ }
+ }
+
+ SetBackground(dpy, areawin->gc, BACKGROUND);
+
+ /* Determine the transformation matrix for the topmost object */
+ /* and draw the hierarchy above the current edit object (if */
+ /* "edit-in-place" is selected). */
+
+ if (areawin->editinplace == True) {
+ if (areawin->stack != NULL) {
+ pushlistptr lastlist = NULL, thislist;
+ Matrix mtmp;
+
+ UPushCTM(); /* save our current state */
+
+ /* It's easiest if we first push the current page onto the stack, */
+ /* then we don't need to treat the top-level page separately. We */
+ /* pop it at the end. */
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+
+ thislist = areawin->stack;
+
+ while ((thislist != NULL) &&
+ (is_library(thislist->thisinst->thisobject) < 0)) {
+
+ /* Invert the transformation matrix of the instance on the stack */
+ /* to get the proper transformation matrix of the drawing one */
+ /* up in the hierarchy. */
+
+ UResetCTM(&mtmp);
+ UPreMultCTM(&mtmp, thislist->thisinst->position,
+ thislist->thisinst->scale, thislist->thisinst->rotation);
+ InvertCTM(&mtmp);
+ UPreMultCTMbyMat(DCTM, &mtmp);
+
+ lastlist = thislist;
+ thislist = thislist->next;
+
+ /* The following will be true for moves between schematics and symbols */
+ if ((thislist != NULL) && (thislist->thisinst->thisobject->symschem
+ == lastlist->thisinst->thisobject))
+ break;
+ }
+
+ if (lastlist != NULL) {
+ pushlistptr stack = NULL;
+ SetForeground(dpy, areawin->gc, OFFBUTTONCOLOR);
+ UDrawObject(lastlist->thisinst, SINGLE, DOFORALL,
+ xobjs.pagelist[areawin->page]->wirewidth, &stack);
+ /* This shouldn't happen, but just in case. . . */
+ if (stack) free_stack(&stack);
+ }
+
+ pop_stack(&areawin->stack); /* restore the original stack state */
+ UPopCTM(); /* restore the original matrix state */
+ }
+ }
+ }
+
+ /* draw all of the elements on the screen */
+
+ SetForeground(dpy, areawin->gc, FOREGROUND);
+
+ /* Initialize hierstack */
+ if (areawin->hierstack) free_stack(&areawin->hierstack);
+ UDrawObject(areawin->topinstance, TOPLEVEL, FOREGROUND,
+ xobjs.pagelist[areawin->page]->wirewidth, &areawin->hierstack);
+ if (areawin->hierstack) free_stack(&areawin->hierstack);
+
+ /* draw the highlighted netlist, if any */
+ if (checkvalid(topobject) != -1)
+ if (topobject->highlight.netlist != NULL)
+ highlightnetlist(topobject, areawin->topinstance, 1);
+
+ /* Sanity check---specifically to track down an error */
+ if ((areawin->selects == 1) && *(areawin->selectlist) >= topobject->parts) {
+ Wprintf("Internal error!");
+ areawin->selects = 0;
+ unselect_all();
+ }
+
+ /* draw selected elements in the SELECTION color */
+ /* special case---single label partial text selected */
+
+ if ((areawin->selects == 1) && SELECTTYPE(areawin->selectlist) == LABEL
+ && areawin->textend > 0 && areawin->textpos > areawin->textend) {
+ labelptr drawlabel = SELTOLABEL(areawin->selectlist);
+ UDrawString(drawlabel, DOSUBSTRING, areawin->topinstance);
+ }
+ else {
+ if (eventmode == NORMAL_MODE || eventmode == MOVE_MODE || eventmode == COPY_MODE
+ || eventmode == SELAREA_MODE || eventmode == CATALOG_MODE)
+ draw_all_selected();
+ }
+
+ /* fast copy of buffer */
+
+#ifdef OPENGL
+ glXSwapBuffers(dpy, (GLXDrawable)areawin->window);
+
+ /* Draw interactive elements into the front buffer */
+ glDrawBuffer(GL_FRONT);
+
+#else
+#ifdef DOUBLEBUFFER
+ areawin->window = tmpwin;
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, 0, areawin->width,
+ areawin->height, 0, 0);
+#endif
+#endif /* OPENGL */
+
+ /* draw pending elements, if any */
+
+ if (eventmode != NORMAL_MODE) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE ||
+ eventmode == CATTEXT_MODE) {
+ labelptr newlabel = TOLABEL(EDITPART);
+ UDrawTLine(newlabel);
+ }
+ else if (eventmode == SELAREA_MODE) {
+ UDrawBox(areawin->origin, areawin->save);
+ }
+ else if (eventmode == RESCALE_MODE) {
+ UDrawRescaleBox(&areawin->save);
+ }
+ else if (eventmode == BOX_MODE || eventmode == WIRE_MODE) {
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ UDrawPolygon(TOPOLY(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ XcSetXORFg(areawin->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawPolygon(TOPOLY(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else if (eventmode == ARC_MODE) {
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ UDrawArc(TOARC(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ XcSetXORFg(areawin->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawArc(TOARC(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else if (eventmode == SPLINE_MODE) {
+ SetForeground(dpy, areawin->gc, BACKGROUND);
+ UDrawSpline(TOSPLINE(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ XcSetXORFg(areawin->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ UDrawSpline(TOSPLINE(ENDPART), xobjs.pagelist[areawin->page]->wirewidth);
+ }
+ else if (eventmode == EPOLY_MODE || eventmode == EARC_MODE ||
+ eventmode == ESPLINE_MODE || eventmode == EPATH_MODE) {
+ XcSetXORFg(areawin->color, BACKGROUND);
+ XcSetFunction(GXxor);
+ }
+ }
+
+ /* flush out multiple expose/resize events from the event queue */
+
+ while (XCheckWindowEvent(dpy, areawin->window, ExposureMask, &discard) == True);
+
+ /* end by restoring graphics state */
+
+ SetForeground(dpy, areawin->gc, areawin->gccolor);
+ SetFunction(dpy, areawin->gc, areawin->gctype);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw the current window (areawin). Check if other windows contain */
+/* the same object or one of its ancestors. If so, redraw them, too. */
+/*----------------------------------------------------------------------*/
+
+void drawarea(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ XCWindowDataPtr thiswin, focuswin;
+
+ if (xobjs.suspend >= 0) {
+ if (xobjs.suspend == 0)
+ xobjs.suspend = 1; /* Mark that a refresh is pending */
+ return;
+ }
+
+ focuswin = areawin;
+
+ for (thiswin = xobjs.windowlist; thiswin != NULL; thiswin = thiswin->next) {
+ if (thiswin == focuswin) continue;
+
+ /* Note: need to check ancestry here, not just blindly redraw */
+ /* all the windows all the time. */
+ areawin = thiswin;
+ drawwindow(NULL, NULL, NULL);
+ }
+ areawin = focuswin;
+ drawwindow(w, clientdata, calldata);
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/examples/.xcircuitrc b/examples/.xcircuitrc
new file mode 100644
index 0000000..d21ae4e
--- /dev/null
+++ b/examples/.xcircuitrc
@@ -0,0 +1,23 @@
+#-----------------------------------------#
+# xcircuitrc file for editing sheet music #
+# (TCL version) #
+#-----------------------------------------#
+
+# 1) Don't load any of the default libraries.
+# Instead, load only "musiclib".
+library override
+library 1 load musiclib
+
+# 2) Load font Times-Roman and set the default font to Times-RomanISO
+loadfont Times-Roman
+# set fontfamily Times-Roman
+label family Times-Roman
+
+# 3) Set various parameters for music editing
+config boxedit rhomboidy
+config colorscheme inverse
+xcircuit::xschema disable
+
+# 4) Set Backspace = Delete
+bindkey "BackSpace" "Text Left" forget
+bindkey "BackSpace" "Text Delete"
diff --git a/examples/.xcircuitrc.py b/examples/.xcircuitrc.py
new file mode 100644
index 0000000..fa24842
--- /dev/null
+++ b/examples/.xcircuitrc.py
@@ -0,0 +1,23 @@
+#-----------------------------------------#
+# xcircuitrc file for editing sheet music #
+# (python version) #
+# Rename this file to .xcircuitrc #
+#-----------------------------------------#
+
+# 1) Don't load any of the default libraries.
+# Instead, load only "musiclib".
+override("library")
+library("/usr/local/lib/xcircuit-3.6/musiclib")
+
+# 2) Load font Times-Roman and set the default font to Times-RomanISO
+font("Times-Roman")
+set("font", "Times-RomanISO")
+
+# 3) Set various parameters for music editing
+set("boxedit", "rhomboid-y")
+set("colorscheme", "inverse")
+set("xschema", "off")
+
+# 4) Set Backspace = Delete
+unbind("BackSpace", "Text Left")
+bind("BackSpace", "Text Delete")
diff --git a/examples/FlareLED.ps b/examples/FlareLED.ps
new file mode 100644
index 0000000..d807858
--- /dev/null
+++ b/examples/FlareLED.ps
@@ -0,0 +1,720 @@
+%!PS-Adobe-3.0
+%%Title: examples/FlareLED
+%%Creator: Xcircuit v2.3
+%%CreationDate: Mon Jul 2 14:17:57 2001
+%%Pages: 1
+%%BoundingBox: -319 -124 931 916
+%%DocumentNeededResources: font Helvetica font Helvetica-Bold font Times-Roman
+%%+ font Times-RomanISO font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.3 1
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale /rotval exch def /just exch def
+ just 16 and 0 gt {0 1 dtransform gsave pagemat setmatrix idtransform
+ exch grestore 1 0 dtransform gsave pagemat setmatrix idtransform
+ exch grestore dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs 0 array def
+ /fscale 1.0 def /kY 0 def
+ gsave dup 1 add copy 0 exch {exch dup type /stringtype eq {true
+ charpath flattenpath} {exec} ifelse } repeat pop pathbbox grestore
+ 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and 0 gt {exch pop
+ neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt {exch pop
+ neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def rotval rotate Kn currentpoint translate
+ /Bline 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+/Times-Roman findfont dup length dict begin
+{1 index /FID ne {def} {pop pop} ifelse} forall
+/Encoding ISOLatin1Encoding def currentdict end
+/Times-RomanISO exch definefont pop
+
+% XCircuit output starts here.
+
+/PIC16C54 {
+% 0 0 480 736 bbox
+(?) 1 beginparm
+0 1.00 0 0 0 736 480 736 480 0 4 polygon
+(PIC16C54A) {/Helvetica-Bold cf} 2 21 0 1.00 240 320 label
+(Vdd) {/Helvetica cf} 2 23 0 1.00 464 368 label
+(RA2) {/Helvetica cf} 2 20 0 1.00 16 688 label
+(RA3) {/Helvetica cf} 2 20 0 1.00 16 624 label
+(RTCC) {/Helvetica cf} 2 20 0 1.00 16 560 label
+(MCLR) {ol} {/Helvetica cf} 3 20 0 1.00 16 496 label
+(Vss) {/Helvetica cf} 2 20 0 1.00 16 368 label
+(RB0) {/Helvetica cf} 2 20 0 1.00 16 240 label
+(RB1) {/Helvetica cf} 2 20 0 1.00 16 176 label
+(RB2) {/Helvetica cf} 2 20 0 1.00 16 112 label
+(RB3) {/Helvetica cf} 2 20 0 1.00 16 48 label
+(RB4) {/Helvetica cf} 2 23 0 1.00 464 48 label
+(RB5) {/Helvetica cf} 2 23 0 1.00 464 112 label
+(RB6) {/Helvetica cf} 2 23 0 1.00 464 176 label
+(RB7) {/Helvetica cf} 2 23 0 1.00 464 240 label
+(OSC2/CLKOUT) {/Helvetica cf} 2 23 0 1.00 464 496 label
+(OSC1/CLKIN) {/Helvetica cf} 2 23 0 1.00 464 560 label
+(RA0) {/Helvetica cf} 2 23 0 1.00 464 624 label
+(RA1) {/Helvetica cf} 2 23 0 1.00 464 688 label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 224 256 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 0 688 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 0 624 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 0 560 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 0 496 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 0 368 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 0 240 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 0 176 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 0 112 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 0 48 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 480 48 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 480 112 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 480 176 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 480 240 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 480 368 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 480 496 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 480 560 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 480 624 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 480 688 pinlabel
+endgate
+} def
+
+/LTC490 {
+% 0 0 416 384 bbox
+(?) 1 beginparm
+0 1.00 0 0 0 384 416 384 416 0 4 polygon
+(RS422) {/Helvetica cf} 2 21 0 1.00 192 176 label
+(Transciever) {/Helvetica cf} 2 21 0 1.00 208 128 label
+(LTC490) {/Helvetica-Bold cf} 2 21 0 1.00 192 256 label
+(Vcc) {/Helvetica cf} 2 20 0 1.00 16 336 label
+(R) {/Helvetica cf} 2 20 0 1.00 16 240 label
+(D) {/Helvetica cf} 2 20 0 1.00 16 144 label
+(GND) {/Helvetica cf} 2 20 0 1.00 16 48 label
+(Y) {/Helvetica cf} 2 23 0 1.00 400 48 label
+(Z) {/Helvetica cf} 2 23 0 1.00 400 144 label
+(B) {/Helvetica cf} 2 23 0 1.00 400 240 label
+(A) {/Helvetica cf} 2 23 0 1.00 400 336 label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 208 80 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 0 336 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 0 240 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 0 144 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 0 48 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 416 48 pinlabel
+(6) {/Helvetica cf} 2 20 0 1.00 416 144 pinlabel
+(7) {/Helvetica cf} 2 20 0 1.00 416 240 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 416 336 pinlabel
+endgate
+} def
+
+/terminal_block {
+% -160 -80 320 173 bbox
+(?) 1 beginparm
+0 1.00 -160 -80 -160 48 160 48 160 -80 4 polygon
+(ED100/3DS) {/Helvetica cf} 2 21 0 1.00 0 80 label
+1 1.00 0 -16 32 0.00 360.00 xcarc
+1 1.00 96 -16 32 0.00 360.00 xcarc
+1 1.00 -96 -16 32 0.00 360.00 xcarc
+sce
+mark v1 (pcb:J) {/Helvetica cf} ctmk 21 0 1.00 0 -112 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 25 0 1.00 -96 -16 pinlabel
+(2) {/Helvetica cf} 2 25 0 1.00 0 -16 pinlabel
+(3) {/Helvetica cf} 2 25 0 1.00 96 -16 pinlabel
+endgate
+} def
+
+/LTC1152 {
+% -192 -192 384 384 bbox
+(?) 1 beginparm
+0 1.00 -192 -192 -192 192 192 192 192 -192 4 polygon
+(LTC1152) {/Helvetica-Bold cf} 2 25 0 1.00 0 48 label
+(Op-amp) {/Helvetica cf} 2 29 0 1.00 0 0 label
+(SHDN) {/Helvetica cf} 2 20 0 1.00 -176 144 label
+(IN) {/Helvetica cf} (-) {/Symbol cf} 4 20 0 1.00 -176 48 label
+(IN) {/Helvetica cf} (+) {/Symbol cf} 4 20 0 1.00 -176 -48 label
+(-) {/Symbol cf} (V) {/Helvetica cf} 4 20 0 1.00 -176 -144 label
+(COMP) {/Helvetica cf} 2 23 0 1.00 176 -144 label
+(OUT) {/Helvetica cf} 2 23 0 1.00 176 -48 label
+(+) {/Symbol cf} (V) {/Helvetica cf} 4 23 0 1.00 176 48 label
+(CP) {/Helvetica cf} 2 23 0 1.00 176 144 label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -80 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -192 144 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -192 48 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -192 -48 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 192 -144 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -192 -144 pinlabel
+(6) {/Helvetica cf} 2 20 0 1.00 192 -48 pinlabel
+(7) {/Helvetica cf} 2 20 0 1.00 192 48 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 192 144 pinlabel
+endgate
+} def
+
+/DSUB9 {
+% -160 0 320 186 bbox
+(?) 1 beginparm
+1 1.00 -128 96 16 0.00 360.00 xcarc
+1 1.00 -32 32 16 0.00 360.00 xcarc
+1 1.00 0 96 16 0.00 360.00 xcarc
+1 1.00 64 96 16 0.00 360.00 xcarc
+1 1.00 128 96 16 15.00 375.00 xcarc
+1 1.00 96 32 16 0.00 360.00 xcarc
+1 1.00 32 32 16 0.00 360.00 xcarc
+1 1.00 -64 96 16 0.00 360.00 xcarc
+1 1.00 -96 32 16 0.00 360.00 xcarc
+sce
+mark v1 (pcb:J) {/Helvetica cf} ctmk 21 0 1.00 16 -48 infolabel
+128 128 beginpath
+128 96 32 450.00 333.43 arcn
+124 17 1 polyc
+96 32 32 333.43 270.00 arcn
+-96 0 1 polyc
+-96 32 32 270.00 206.57 arcn
+-156 81 1 polyc
+-128
+96 32 206.57 90.00 arcn
+128 128 1 polyc
+1 1.00 endpath
+(AMP 745781-4) {/Helvetica cf} 2 25 0 1.00 0 160 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 25 0 1.00 -128 96 pinlabel
+(3) {/Helvetica cf} 2 25 0 1.00 0 96 pinlabel
+(2) {/Helvetica cf} 2 25 0 1.00 -64 96 pinlabel
+(4) {/Helvetica cf} 2 25 0 1.00 64 96 pinlabel
+(5) {/Helvetica cf} 2 25 0 1.00 128 96 pinlabel
+(6) {/Helvetica cf} 2 29 0 1.00 -96 32 pinlabel
+(7) {/Helvetica cf} 2 29 0 1.00 -32 32 pinlabel
+(8) {/Helvetica cf} 2 29 0 1.00 32 32 pinlabel
+(9) {/Helvetica cf} 2 29 0 1.00 96 32 pinlabel
+endgate
+} def
+
+/Crystal {
+% -144 -144 288 288 bbox
+(?) 1 beginparm
+0 1.00 -144 -144 -144 144 144 144 144 -144 4 polygon
+(CTX169) {/Helvetica-Bold cf} 2 25 0 1.00 0 16 label
+(MHz) {hS} (20) {/Helvetica cf} 4 21 0 1.00 0 -32 label
+(N/C) {/Helvetica cf} 2 20 0 1.00 -128 96 label
+(GND) {/Helvetica cf} 2 20 0 1.00 -128 -96 label
+(OUT) {/Helvetica cf} 2 23 0 1.00 128 -96 label
+(Vdd) {/Helvetica cf} 2 23 0 1.00 128 96 label
+sce
+mark v1 (pcb:X) {/Helvetica cf} ctmk 21 0 1.00 0 -176 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -144 96 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -144 -96 pinlabel
+(3) {/Helvetica cf} 2 20 0 1.00 144 -96 pinlabel
+(4) {/Helvetica cf} 2 20 0 1.00 144 96 pinlabel
+endgate
+} def
+
+/ADC12138 {
+% -240 -464 480 928 bbox
+(?) 1 beginparm
+0 1.00 -240 -464 -240 464 240 464 240 -464 4 polygon
+(CH0) {/Helvetica cf} 2 20 0 1.00 -224 416 label
+(CH1) {/Helvetica cf} 2 20 0 1.00 -224 352 label
+(CH2) {/Helvetica cf} 2 20 0 1.00 -224 288 label
+(CH3) {/Helvetica cf} 2 20 0 1.00 -224 224 label
+(CH4) {/Helvetica cf} 2 20 0 1.00 -224 160 label
+(CH5) {/Helvetica cf} 2 20 0 1.00 -224 96 label
+(CH6) {/Helvetica cf} 2 20 0 1.00 -224 32 label
+(CH7) {/Helvetica cf} 2 20 0 1.00 -224 -32 label
+(COM) {/Helvetica cf} 2 20 0 1.00 -224 -96 label
+(MuxOut1) {/Helvetica cf} 2 20 0 1.00 -224 -160 label
+(A/Din2) {/Helvetica cf} 2 20 0 1.00 -224 -352 label
+(DGND) {/Helvetica cf} 2 20 0 1.00 -224 -416 label
+(+) {/Symbol cf} (VA) {/Helvetica cf} 4 23 0 1.00 224 -416 label
+(-) {/Symbol cf} (Vref) {/Helvetica cf} 4 23 0 1.00 224 -352 label
+(+) {/Symbol cf} (Vref) {/Helvetica cf} 4 23 0 1.00 224 -288 label
+(AGND) {/Helvetica cf} 2 23 0 1.00 224 -224 label
+(PD) {/Helvetica cf} 2 23 0 1.00 224 -160 label
+(EOC) {/Helvetica cf} 2 23 0 1.00 224 -96 label
+(CONV) {ol} {/Helvetica cf} 3 23 0 1.00 224 -32 label
+(CS) {ol} {/Helvetica cf} 3 23 0 1.00 224 32 label
+(DO) {/Helvetica cf} 2 23 0 1.00 224 96 label
+(DI) {/Helvetica cf} 2 23 0 1.00 224 160 label
+(SCLK) {/Helvetica cf} 2 23 0 1.00 224 224 label
+(A/Din1) {/Helvetica cf} 2 20 0 1.00 -224 -224 label
+(MuxOut2) {/Helvetica cf} 2 20 0 1.00 -224 -288 label
+(CCLK) {/Helvetica cf} 2 23 0 1.00 224 288 label
+(DOR) {ol} {/Helvetica cf} 3 23 0 1.00 224 352 label
+(+) {/Symbol cf} (VD) {/Helvetica cf} 4 23 0 1.00 224 416 label
+(ADC12138) {/Helvetica-Bold cf} 2 21 0 1.00 0 64 label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 0 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -240 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -240 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -240 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -240 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -240 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -240 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -240 32 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -240 -32 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -240 -96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -240 -160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -240 -224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -240 -288 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -240 -352 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -240 -416 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 240 -416 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 240 -352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 240 -288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 240 -224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 240 -160 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 240 -96 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 240 -32 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 240 32 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 240 96 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 240 160 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 240 224 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 240 288 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 240 352 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 240 416 pinlabel
+endgate
+} def
+
+/TK11950 {
+% -336 -112 672 224 bbox
+(?) 1 beginparm
+0 1.00 -336 -112 -336 112 336 112 336 -112 4 polygon
+(NOISE BYPASS) {/Helvetica cf} 2 20 0 1.00 -320 64 label
+(CONTROL) {/Helvetica cf} 2 20 0 1.00 -320 0 label
+(RESET OUT) {/Helvetica cf} 2 20 0 1.00 -320 -64 label
+(VO) {/Helvetica cf} 2 23 0 1.00 320 -64 label
+(GND) {/Helvetica cf} 2 23 0 1.00 320 0 label
+(VIN) {/Helvetica cf} 2 23 0 1.00 320 64 label
+(TK11950) {/Helvetica-Bold cf} 2 21 0 1.00 64 16 label
+(V) {hS} (5.0) {/Helvetica cf} 4 29 0 1.00 64 -32 label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -144 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -336 64 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -336 0 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -336 -64 pinlabel
+(4) {/Helvetica cf} 2 20 0 1.00 336 -64 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 336 0 pinlabel
+(6) {/Helvetica cf} 2 20 0 1.00 336 64 pinlabel
+endgate
+} def
+
+/Capacitor {
+% -32 -64 186 128 bbox
+(1.0) (\265) (?) 3 beginparm
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+sce
+mark v2 v1 ( %p1 %p2 ) v3 (spice:C) {/Times-RomanISO cf} ctmk 4 0 1.00 -208
+-160 infolabel
+sce
+(sim:c %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+mark (F) v2 {hS} v1 {/Times-RomanISO cf} ctmk 20 0 1.00 48 0 label
+sce
+mark v3 (pcb:C) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+/LM13700 {
+% -256 -256 480 544 bbox
+(?) 1 beginparm
+0 1.00 -256 -256 -256 288 224 288 224 -256 4 polygon
+(BufIn1) {/Helvetica cf} 2 20 0 1.00 -240 -144 label
+(BufOut1) {/Helvetica cf} 2 20 0 1.00 -240 -208 label
+(BufIn2) {/Helvetica cf} 2 23 0 1.00 208 -144 label
+(+) {/Symbol cf} (V) {/Helvetica cf} 4 23 0 1.00 208 -80 label
+(Out2) {/Helvetica cf} 2 23 0 1.00 208 -16 label
+1.000 0.000 0.000 scb
+(7) {/Helvetica cf} 2 23 0 1.00 -256 -144 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -256 -208 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 -144 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 -80 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 -16 pinlabel
+sce
+(LM13700) {/Helvetica-Bold cf} 2 21 0 1.00 -16 16 label
+(Iabc1) {/Helvetica cf} 2 20 0 1.00 -240 240 label
+(Dbias1) {/Helvetica cf} 2 20 0 1.00 -240 176 label
+(1) {/Helvetica cf} (+) {/Symbol cf} (In) {/Helvetica cf} 6 20 0 1.00 -240 112
+label
+(Out1) {/Helvetica cf} 2 20 0 1.00 -240 -16 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -256 240 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -256 176 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -256 112 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -256 48 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -256 -16 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 112 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 176 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 240 pinlabel
+sce
+(-) {/Symbol cf} (V) {/Helvetica cf} 4 20 0 1.00 -240 -80 label
+1.000 0.000 0.000 scb
+(6) {/Helvetica cf} 2 23 0 1.00 -256 -80 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 48 pinlabel
+sce
+(BufOut2) {/Helvetica cf} 2 23 0 1.00 208 -208 label
+1.000 0.000 0.000 scb
+(9) {/Helvetica cf} 2 20 0 1.00 224 -208 pinlabel
+sce
+(1) {/Helvetica cf} (-) {/Symbol cf} (In) {/Helvetica cf} 6 20 0 1.00 -240 48
+label
+(Iabc2) {/Helvetica cf} 2 23 0 1.00 208 240 label
+(Dbias2) {/Helvetica cf} 2 23 0 1.00 208 176 label
+(2) {/Helvetica cf} (+) {/Symbol cf} (In) {/Helvetica cf} 6 23 0 1.00 208 112
+label
+(2) {/Helvetica cf} (-) {/Symbol cf} (In) {/Helvetica cf} 6 23 0 1.00 208 48
+label
+sce
+mark v1 (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 -16 -304 infolabel
+endgate
+} def
+
+/Resistor {
+% -14 -64 157 128 bbox
+(1.0) (k) (?) 3 beginparm
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+sce
+mark v2 v1 ( %p1 %p2 ) v3 (spice:R) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+sce
+(sim:R %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+mark (W) {/Symbol cf} v2 {hS} v1 {/Times-Roman cf} ctmk 20 0 1.00 32 0 label
+sce
+mark v3 (pcb:R) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/dot {
+% -10 -10 20 20 bbox
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/vdd {
+% -32 0 64 66 bbox
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 1688 848 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 664 1648 [(5) ] PIC16C54
+1.00 180 -24 2384 [(6) ] LTC490
+1.00 0 712 -160 [(2) ] terminal_block
+1.00 0 1800 944 [(7) ] LTC1152
+1.00 0 -568 1296 [(3) ] DSUB9
+1.00 180 1576 2192 [(1) ] Crystal
+1.00 0 904 1088 [(2) ] ADC12138
+1.00 -181 -56 1664 [(4) ] TK11950
+1 1.00 1432 2288 1304 2288 1304 2208 1144 2208 4 polygon
+1.00 -1 2072 1168 Capacitor
+1.00 0 920 304 [(1) ] LM13700
+1.00 0 1096 -160 [(1) ] terminal_block
+1.00 0 1320 1424 Resistor
+1.00 0 120 1984 Resistor
+1.00 0 328 1456 Resistor
+1.00 -1 -696 2064 Resistor
+1.00 0 408 1600 Resistor
+1.00 0 1384 992 Resistor
+1.00 0 1784 2224 Capacitor
+1.00 -1 1512 720 Capacitor
+1.00 0 2088 832 Capacitor
+1.00 0 -280 1456 Capacitor
+1.00 0 504 416 Capacitor
+1 1.00 664 544 504 544 504 480 3 polygon
+1 1.00 504 352 504 224 664 224 3 polygon
+1 1.00 -664 1328 -664 224 504 224 3 polygon
+1.00 0 -664 224 gnd
+1 1.00 664 160 -472 160 -472 1328 3 polygon
+1 1.00 -696 2000 -696 1392 2 polygon
+1 1.00 -440 2240 -504 2240 -504 1392 3 polygon
+1 1.00 -440 2336 -568 2336 -568 1392 3 polygon
+1 1.00 280 1664 408 1664 408 2336 -24 2336 4 polygon
+1 1.00 -24 2048 344 2048 2 polygon
+1 1.00 344 2048 344 1728 280 1728 3 polygon
+1 1.00 328 1520 328 1600 280 1600 3 polygon
+1 1.00 408 1664 408 1664 2 polygon
+1 1.00 328 1520 408 1520 408 1536 3 polygon
+1.00 -181 1704 1760 [(3) ] TK11950
+1 1.00 1144 736 1352 736 2 polygon
+1.00 0 1352 736 dot
+1 1.00 1608 896 1384 896 1384 928 3 polygon
+1 1.00 1608 1088 1384 1088 1384 1056 3 polygon
+1 1.00 1992 992 2136 992 2136 1232 1384 1232 1384 1088 5 polygon
+1.00 0 1384 1088 dot
+1 1.00 -440 2144 -696 2144 -696 2128 3 polygon
+1 1.00 -440 2048 -536 2048 -536 2000 -696 2000 4 polygon
+1 1.00 -632 1392 -632 2144 2 polygon
+1.00 0 -632 2144 dot
+1.00 0 -696 2000 dot
+1 1.00 -440 1392 -440 1888 408 1888 3 polygon
+1.00 0 408 1888 dot
+1.00 0 408 1664 dot
+1.00 0 328 1520 dot
+1 1.00 1144 2016 1368 2016 1368 2112 1432 2112 4 polygon
+1 1.00 664 2016 568 2016 568 2432 1784 2432 1784 2288 1720 2288 6 polygon
+1 1.00 1352 2016 1784 2016 1784 2160 3 polygon
+1.00 0 1368 2016 dot
+1 1.00 1144 1376 1240 1376 1240 2144 1144 2144 4 polygon
+1 1.00 1144 1312 1224 1312 1224 1632 616 1632 616 1888 664 1888 6 polygon
+1 1.00 1144 1248 1208 1248 1208 1616 600 1616 600 1824 664 1824 6 polygon
+1 1.00 1144 1184 1192 1184 1192 1600 584 1600 584 1760 664 1760 6 polygon
+1 1.00 1144 1120 1176 1120 1176 1584 568 1584 568 1696 664 1696 6 polygon
+1 1.00 1144 1056 1256 1056 1256 1760 1144 1760 4 polygon
+1 1.00 1144 992 1272 992 1272 1696 1144 1696 4 polygon
+1 1.00 1144 2272 1208 2272 1208 2416 24 2416 24 2240 -24 2240 6 polygon
+1 1.00 -24 2144 40 2144 40 2400 1176 2400 1176 2336 1144 2336 6 polygon
+1 1.00 664 736 632 736 632 800 664 800 4 polygon
+1 1.00 664 864 632 864 632 928 664 928 4 polygon
+1 1.00 664 672 600 672 2 polygon
+1.00 0 456 608 gnd
+1.00 0 -280 1360 gnd
+1 1.00 -280 1392 -440 1392 2 polygon
+1.00 0 1368 2112 vdd
+1 1.00 1992 800 2040 800 2040 768 2088 768 4 polygon
+1.00 0 1512 640 dot
+1 1.00 1608 800 1512 800 1512 784 3 polygon
+1.00 0 2088 896 dot
+1 1.00 1992 1088 2072 1088 2072 1104 3 polygon
+1.00 0 2072 1232 dot
+1 1.00 664 96 408 96 408 480 664 480 4 polygon
+1 1.00 408 96 408 0 1208 0 1208 480 1128 480 5 polygon
+1.00 0 408 96 dot
+1 1.00 408 480 408 1040 536 1040 536 1440 664 1440 5 polygon
+1.00 0 408 480 dot
+(Flare Genesis) {/Helvetica cf} 2 16 0 1.50 1896 432 label
+(LED Interface) {/Helvetica cf} 2 16 0 1.50 1896 336 label
+1 1.00 664 416 632 416 632 16 712 16 712 -176 5 polygon
+1 1.00 664 352 616 352 616 -176 3 polygon
+1 1.00 1000 -176 1000 -16 1240 -16 1240 352 1144 352 5 polygon
+1 1.00 1096 -176 1096 -32 1256 -32 1256 416 1144 416 5 polygon
+1 1.00 1192 -176 1192 -288 344 -288 344 1072 504 1072 504 1248 664 1248
+7 polygon
+1 1.00 1144 288 1304 288 1304 -320 296 -320 296 1104 472 1104 472 1504 664
+1504 8 polygon
+1 1.00 1144 672 1288 672 1288 800 1144 800 4 polygon
+1 1.00 1384 1072 1288 1072 1288 800 1192 800 4 polygon
+1.00 0 1288 800 dot
+1.00 0 1384 1072 dot
+1 1.00 1144 864 1240 864 1240 928 1144 928 4 polygon
+1 1.00 1560 848 1560 992 1608 992 3 polygon
+1 1.00 1560 848 1352 848 1352 640 2136 640 2136 896 1992 896 6 polygon
+1 1.00 1512 656 1512 640 2 polygon
+1 1.00 1576 800 1576 720 2 polygon
+1.00 0 1576 800 dot
+1.00 0 1576 720 gnd
+1 1.00 -392 1664 -440 1664 2 polygon
+1.00 0 -440 1664 dot
+1 1.00 -392 1728 -424 1728 -424 1856 472 1856 472 2144 664 2144 6 polygon
+1 1.00 120 1920 120 1856 2 polygon
+1.00 0 120 2048 dot
+1.00 0 120 1856 dot
+1 1.00 -392 1600 -408 1600 -408 1520 -280 1520 4 polygon
+1 1.00 -280 1360 -280 1392 2 polygon
+1.00 0 -280 1392 dot
+1 1.00 328 1392 328 1248 -472 1248 3 polygon
+1.00 0 -472 1248 dot
+1 1.00 1144 224 1320 224 2 polygon
+1 1.00 1176 224 1176 32 504 32 504 160 4 polygon
+1.00 0 504 160 dot
+1.00 0 1176 224 dot
+1 1.00 1320 1360 1320 224 2 polygon
+1 1.00 2136 1232 2136 1696 2040 1696 3 polygon
+1.00 0 2136 1232 dot
+1 1.00 2040 1760 2136 1760 2136 1936 1320 1936 1320 1760 1368 1760 6 polygon
+1 1.00 1320 1488 1320 1584 2088 1584 2088 1824 2040 1824 5 polygon
+1 1.00 664 992 600 992 600 1184 664 1184 4 polygon
+1 1.00 664 1120 600 1120 2 polygon
+1 1.00 664 1056 600 1056 2 polygon
+1.00 0 600 1056 dot
+1.00 0 600 1120 dot
+1 1.00 600 992 600 608 2 polygon
+1.00 0 600 672 dot
+1.00 0 600 992 dot
+1 1.00 1240 864 1240 608 456 608 3 polygon
+1.00 0 600 608 dot
+1.00 0 1240 864 dot
+(is not complete!) {CR} (this schematic) {/Helvetica cf} 4 16 0 1.00 1864 -80
+label
+0 1.00 1592 -176 1592 496 2456 496 2456 -176 4 polygon
+1 1.00 1592 400 2456 400 2 polygon
+1 1.00 1592 304 2456 304 2 polygon
+(1.0) {/Helvetica cf} 2 16 0 1.50 1896 240 label
+1 1.00 1592 208 2456 208 2 polygon
+(Project:) {/Helvetica cf} 2 16 0 1.50 1624 432 label
+(Name:) {/Helvetica cf} 2 16 0 1.50 1624 336 label
+(Revision:) {/Helvetica cf} 2 16 0 1.50 1624 240 label
+(Design:) {/Helvetica cf} 2 16 0 1.50 1624 144 label
+(Date:) {/Helvetica cf} 2 16 0 1.50 1624 48 label
+(Notes:) {/Helvetica cf} 2 16 0 1.50 1624 -48 label
+1 1.00 1592 112 2456 112 2 polygon
+1 1.00 1592 16 2456 16 2 polygon
+(Harry Eaton) {/Helvetica cf} 2 16 0 1.50 1912 144 label
+0 1.00 1576 -192 1576 512 2472 512 2472 -192 4 polygon
+1.00 0 -664 224 dot
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/USAflag.ps b/examples/USAflag.ps
new file mode 100644
index 0000000..2b7116e
--- /dev/null
+++ b/examples/USAflag.ps
@@ -0,0 +1,221 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: USAflag
+%%Creator: Xcircuit v1.6
+%%CreationDate: Sat Aug 16 09:29:46 1997
+%%Pages: 1
+%%BoundingBox: 68 68 868 544
+%%DocumentNeededResources:
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 1.6
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--8/8/97 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 1.6 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def
+ findfont fscale scalefont setfont } def
+/Ss { gsave 0.67 dup scale gsave mty neg rmoveto
+ glevel 1 add /glevel exch def } def
+/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto
+ glevel 1 add /glevel exch def } def
+/ns { currentpoint transform % preserve x position!
+ glevel {grestore} repeat /glevel 0 def
+ itransform pop currentpoint pop sub 0 rmoveto } def
+/ul { showflag 1 eq { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { showflag 1 eq { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/bs { gsave true charpath flattenpath pathbbox pop exch pop sub
+ grestore 0 rmoveto } def
+/textx { dup 2 mul 1 add copy 0 exch
+ { exch exec exch stringwidth pop add } repeat neg ns } def
+/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch
+ pop exch sub exch pop neg grestore } def
+/texty { gsave 2 copy pop exec mty } def
+/tcenter { textx grestore 0.5 mul 0 rmoveto } def
+/tright { textx grestore 0 rmoveto } def
+/tmiddle { texty 0.5 mul rmoveto } def
+/ttop { texty rmoveto } def
+/tshow { { exec show } repeat ns } def
+
+/label { gsave translate 0 0 moveto rotate /just exch def
+ /glevel 0 def /showflag 0 def
+ just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} if
+ just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} if
+ /showflag 1 def tshow grestore } def
+
+/begingate { gsave translate 0 0 moveto dup 0 lt {neg 1 sub -1 1 scale} if
+ rotate dup scale } bind def
+/endgate { grestore } bind def
+
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave tmpa pathbbox clip transform neg exch neg 4 2 roll transform
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ [1 0 0 1 0 0] setmatrix { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 gt exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt { newpath } { stroke } ifelse grestore } def
+/scb { gsave setrgbcolor } bind def /sce { grestore } bind def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 0 setgray } def
+/inchscale {0.375 mul dup scale} def
+/cmscale {0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/star {
+% -128 -112 256 240 bbox
+begingate
+240 1.00 -32 32 -128 32 -50 -22 -80 -112 0 -56 80 -112 50 -22 128 32 32 32
+0 128 10 polygon
+endgate
+} def
+
+%%Page: 1 1
+/pgsave save def bop
+% 192 768 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+0.000 0.000 0.810 scb
+240 1.00 192 768 192 1440 1152 1440 1152 768 4 polygon
+sce
+1.000 1.000 1.000 scb
+240 1.00 192 480 192 576 2304 576 2304 480 4 polygon
+0.20 0 432 976 star
+0.20 0 592 976 star
+0.20 0 832 1040 star
+0.20 0 992 1296 star
+0.20 0 672 1168 star
+0.20 0 672 1296 star
+0.20 0 672 1040 star
+0.20 0 832 1296 star
+0.20 0 992 1168 star
+0.20 0 832 1168 star
+sce
+0.984 0.079 0.254 scb
+240 1.00 1152 1152 1152 1248 2304 1248 2304 1152 4 polygon
+240 1.00 1152 960 1152 1056 2304 1056 2304 960 4 polygon
+240 1.00 192 576 192 672 2304 672 2304 576 4 polygon
+sce
+1.000 1.000 1.000 scb
+0.20 0 592 1104 star
+sce
+0.984 0.079 0.254 scb
+240 1.00 1152 1344 1152 1440 2304 1440 2304 1344 4 polygon
+240 1.00 192 384 192 480 2304 480 2304 384 4 polygon
+sce
+1.000 1.000 1.000 scb
+0.20 0 752 848 star
+0.20 0 1072 848 star
+0.20 0 912 848 star
+0.20 0 672 912 star
+0.20 0 992 1040 star
+0.20 0 832 912 star
+0.20 0 992 912 star
+0.20 0 352 1040 star
+0.20 0 512 1296 star
+0.20 0 272 1232 star
+0.20 0 272 1360 star
+0.20 0 272 1104 star
+0.20 0 352 1296 star
+0.20 0 512 1168 star
+0.20 0 352 1168 star
+0.20 0 272 848 star
+0.20 0 592 848 star
+0.20 0 432 848 star
+0.20 0 272 976 star
+0.20 0 512 1040 star
+0.20 0 352 912 star
+0.20 0 512 912 star
+0.20 0 912 1104 star
+0.20 0 1072 1360 star
+0.20 0 752 1232 star
+0.20 0 752 1360 star
+0.20 0 752 1104 star
+0.20 0 912 1360 star
+0.20 0 1072 1232 star
+0.20 0 912 1232 star
+0.20 0 752 976 star
+0.20 0 1072 1104 star
+0.20 0 912 976 star
+0.20 0 1072 976 star
+0.20 0 432 1104 star
+0.20 0 592 1360 star
+0.20 0 432 1360 star
+0.20 0 592 1232 star
+0.20 0 432 1232 star
+sce
+0.984 0.079 0.254 scb
+240 1.00 192 192 192 288 2304 288 2304 192 4 polygon
+sce
+1.000 1.000 1.000 scb
+240 1.00 1152 1056 1152 1152 2304 1152 2304 1056 4 polygon
+240 1.00 1152 864 1152 960 2304 960 2304 864 4 polygon
+sce
+0.984 0.079 0.254 scb
+240 1.00 1152 768 1152 864 2304 864 2304 768 4 polygon
+sce
+1.000 1.000 1.000 scb
+240 1.00 2304 736 2304 768 2304 768 2304 736 4 polygon
+240 1.00 192 288 192 384 2304 384 2304 288 4 polygon
+240 1.00 192 672 192 768 2304 768 2304 672 4 polygon
+240 1.00 1152 1248 1152 1344 2304 1344 2304 1248 4 polygon
+sce
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/analog1.ps b/examples/analog1.ps
new file mode 100644
index 0000000..d66aff6
--- /dev/null
+++ b/examples/analog1.ps
@@ -0,0 +1,241 @@
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.0
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.0 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def
+ findfont fscale scalefont setfont } def
+/Ss { gsave 0.67 dup scale gsave mty neg rmoveto
+ glevel 1 add /glevel exch def } def
+/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto
+ glevel 1 add /glevel exch def } def
+/ns { currentpoint transform % preserve x position!
+ glevel {grestore} repeat /glevel 0 def
+ itransform pop currentpoint pop sub 0 rmoveto } def
+/ul { showflag 1 eq { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { showflag 1 eq { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave true charpath flattenpath pathbbox pop exch pop sub
+ grestore } def
+/bs { stW 0 rmoveto } def
+/pspc 0 def
+/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def
+/hS { qS qS } def
+/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq
+ {stringwidth pop add}{exec} ifelse } repeat neg ns } def
+/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch
+ pop exch sub exch pop neg grestore } def
+/texty { gsave 2 copy pop exec mty } def
+/tcenter { textx grestore 0.5 mul 0 rmoveto } def
+/tright { textx grestore fspc sub 0 rmoveto } def
+/tmiddle { texty 0.5 mul rmoveto } def
+/ttop { texty fspc sub rmoveto } def
+/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def
+
+/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt
+ {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore
+ 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore
+ dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if
+ /glevel 0 def /showflag 0 def /fspc pspc def
+ just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse}
+ {fspc 0 rmoveto} ifelse
+ just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse}
+ {0 fspc rmoveto} ifelse
+ /showflag 1 def tshow grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore } bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt { newpath } { stroke } ifelse grestore } def
+/scb { gsave setrgbcolor } bind def /sce { grestore } bind def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/resistor {
+% -14 -64 66 128 bbox
+(10) (k) 2 beginparm
+% fundamental
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:R%i %pr.1 %pr.2 %v"10"%v"k") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:r %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(W) {/Symbol 1.000 cf} () v2 () {hS} () v1 () {/Helvetica 1.000 cf} 10 29 90 24 0 label
+endgate
+} def
+
+/nmos {
+% -64 -64 64 128 bbox
+(1.0) (1.0) 2 beginparm
+% fundamental
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Helvetica 1.000 cf} 2 7 0 -64 0 pinlabel
+(S) {/Helvetica 1.000 cf} 2 13 0 0 -64 pinlabel
+(D) {/Helvetica 1.000 cf} 2 9 0 0 64 pinlabel
+sce
+(u) v2 (u L=) v1 (spice:M%i %pD %pG %pS GND nmos W=) {/Times-Roman 1.000 cf} 6 4 0 -244 -139 infolabel
+(sim:n %pG %pS %pD) {/Times-Roman 1.000 cf} 2 4 0 -244 -187 infolabel
+endgate
+} def
+
+/dot {
+% -10 -10 20 20 bbox
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman 1.000 cf} 2 1 0 0 0 pinglobal
+sce
+endgate
+} def
+
+/vdd {
+% -32 0 64 66 bbox
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman 0.900 cf} 2 17 0 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman 1.000 cf} 2 13 0 0 0 pinglobal
+sce
+endgate
+} def
+
+/circle {
+% -6 -12 28 24 bbox
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman 1.000 cf} 2 4 0 16 0 pinlabel
+(out) {/Times-Roman 1.000 cf} 2 7 0 0 0 pinlabel
+sce
+endgate
+} def
+
+%%Page: analog1 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 448 284 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 224 540 [(100) () ] resistor
+1.00 0 448 540 [(20) (k) ] resistor
+1.00 0 448 316 [(4.0) (2.0) ] nmos
+1.00 -1 224 316 [(10) (2.0) ] nmos
+1 1.00 224 476 224 380 2 polygon
+1 1.00 448 476 448 380 2 polygon
+1 1.00 384 316 288 316 2 polygon
+1 1.00 336 316 336 412 224 412 3 polygon
+1.00 0 224 412 dot
+1.00 0 336 316 dot
+1.00 0 224 252 gnd
+1.00 0 448 252 gnd
+1.00 0 224 604 vdd
+1.00 0 448 604 vdd
+1 1.00 448 412 544 412 2 polygon
+1.00 0 448 412 dot
+1.00 0 544 412 circle
+1.000 0.000 0.000 scb
+(Vout) {/Times-Roman 1.000 cf} 2 20 0 560 412 pinlabel
+sce
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/analog2.ps b/examples/analog2.ps
new file mode 100644
index 0000000..416279a
--- /dev/null
+++ b/examples/analog2.ps
@@ -0,0 +1,224 @@
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.0
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.0 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def
+ findfont fscale scalefont setfont } def
+/Ss { gsave 0.67 dup scale gsave mty neg rmoveto
+ glevel 1 add /glevel exch def } def
+/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto
+ glevel 1 add /glevel exch def } def
+/ns { currentpoint transform % preserve x position!
+ glevel {grestore} repeat /glevel 0 def
+ itransform pop currentpoint pop sub 0 rmoveto } def
+/ul { showflag 1 eq { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { showflag 1 eq { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave true charpath flattenpath pathbbox pop exch pop sub
+ grestore } def
+/bs { stW 0 rmoveto } def
+/pspc 0 def
+/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def
+/hS { qS qS } def
+/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq
+ {stringwidth pop add}{exec} ifelse } repeat neg ns } def
+/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch
+ pop exch sub exch pop neg grestore } def
+/texty { gsave 2 copy pop exec mty } def
+/tcenter { textx grestore 0.5 mul 0 rmoveto } def
+/tright { textx grestore fspc sub 0 rmoveto } def
+/tmiddle { texty 0.5 mul rmoveto } def
+/ttop { texty fspc sub rmoveto } def
+/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def
+
+/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt
+ {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore
+ 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore
+ dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if
+ /glevel 0 def /showflag 0 def /fspc pspc def
+ just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse}
+ {fspc 0 rmoveto} ifelse
+ just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse}
+ {0 fspc rmoveto} ifelse
+ /showflag 1 def tshow grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore } bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt { newpath } { stroke } ifelse grestore } def
+/scb { gsave setrgbcolor } bind def /sce { grestore } bind def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/source {
+% -32 -64 64 128 bbox
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/vsource {
+% -32 -64 172 128 bbox
+(5) 1 beginparm
+% fundamental
+1.00 0 0 0 source
+(+) {/Symbol 1.000 cf} 2 5 0 0 18 label
+(-) {/Symbol 1.000 cf} 2 5 0 0 -18 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(v.m) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:V%i %pv.m %pv.p %v5) {/Helvetica 1.000 cf} 2 20 0 -96 -160 infolabel
+(V) {hS} () v1 () {/Helvetica 1.000 cf} 6 20 0 48 0 label
+endgate
+} def
+
+/capacitor {
+% -32 -64 177 128 bbox
+(1.0) (p) 2 beginparm
+% fundamental
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(c.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(c.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:C%i %pc.1 %pc.2 %v"1.0"%v"p") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:c %pc.1 %pc.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(F) v2 () {hS} () v1 () {/Helvetica 1.000 cf} 8 20 0 48 0 label
+endgate
+} def
+
+/resistor {
+% -14 -64 143 128 bbox
+(1.0) (k) 2 beginparm
+% fundamental
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:R%i %pr.1 %pr.2 %v"1.0"%v"k") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:r %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(W) {/Symbol 1.000 cf} () v2 () {hS} () v1 () {/Helvetica 1.000 cf} 10 20 0 32 0 label
+endgate
+} def
+
+/gnd {
+% -32 -60 64 60 bbox
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman 1.000 cf} 2 1 0 0 0 pinglobal
+sce
+endgate
+} def
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 400 336 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 400 400 [(2.5) ] vsource
+1.00 0 656 400 [(1.0) (u) ] capacitor
+1 1.00 656 464 656 528 2 polygon
+1 1.00 400 336 400 272 656 272 656 336 4 polygon
+1.00 0 400 528 [(100) () ] resistor
+1 1.00 400 592 400 624 656 624 656 528 4 polygon
+1.00 0 400 272 gnd
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/analoglib1.lps b/examples/analoglib1.lps
new file mode 100644
index 0000000..1f74dd4
--- /dev/null
+++ b/examples/analoglib1.lps
@@ -0,0 +1,238 @@
+%! PostScript set of library objects for XCircuit
+% Version: 2.0
+% Library name is: analoglib
+% Author: Tim Edwards <tim@stravinsky.jhuapl.edu>
+%
+
+% XCircuitLib library objects
+
+/arrowhead {
+% -12 -32 24 36 bbox
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26
+8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/source {
+% -32 -64 64 128 bbox
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/capacitor {
+% -32 -64 177 128 bbox
+(1.0) (p) 2 beginparm
+% fundamental
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(c.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(c.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:C%i %pc.1 %pc.2 %v"1.0"%v"p") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:c %pc.1 %pc.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(F) v2 {hS} v1 {/Helvetica 1.000 cf} 5 20 0 48 0 label
+endgate
+} def
+
+/polarized {
+% -32 -64 177 128 bbox
+(1.0) (p) 2 beginparm
+% fundamental
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+1.000 0.000 0.000 scb
+(t) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(b) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:C%i %pt %pb %v"1.0"%v"p") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:e %pt %pb %pb) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(F) v2 {hS} v1 {/Helvetica 1.000 cf} 5 20 0 48 0 label
+endgate
+} def
+
+/resistor {
+% -14 -64 151 128 bbox
+(1.0) (k) 2 beginparm
+% fundamental
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:R%i %pr.1 %pr.2 %v"1.0"%v"k") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:r %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(W) {/Symbol 1.000 cf} v2 {hS} v1 {/Helvetica 1.000 cf} 6 20 0 32 0 label
+endgate
+} def
+
+/inductor {
+% -14 -64 164 112 bbox
+(1.0) (m) 2 beginparm
+% fundamental
+1 1.00 20 -28 20 -44 0 -48 0 -24 spline
+1 1.00 -20 -20 -20 -32 0 -28 0 -24 spline
+1 1.00
+20 32 20 16 0 12 0 36 spline
+1 1.00 20 12 20 -4 0 -8 0 16 spline
+1 1.00 20 -8 20 -24 0 -28 0 -4 spline
+1 1.00 -20 20 -20
+8 0 12 0 16 spline
+1 1.00 -20 0 -20 -12 0 -8 0 -4 spline
+1 1.00 0 -48 0 -64 2 polygon
+1 1.00 0 36 0 48 2 polygon
+1.000 0.000 0.000 scb
+(l.1) {/Times-Roman 1.000 cf} 2 9 0 0 48 pinlabel
+(l.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:L%i %pl.1 %pl.2 %v"1.0"%v"m") {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel
+(sim:l %pl.1 %pl.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel
+(H) v2 {hS} v1 {/Helvetica 1.000 cf} 5 20 0 32 0 label
+endgate
+} def
+
+/vsource {
+% -32 -64 139 128 bbox
+(5) 1 beginparm
+% fundamental
+1.00 0 0 0 source
+(+) {/Symbol 1.000 cf} 2 5 0 0 18 label
+(-) {/Symbol 1.000 cf} 2 5 0 0 -18 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(v.m) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:V%i %pv.p %pv.m %v"5") {/Helvetica 1.000 cf} 2 20 0 -96 -160 infolabel
+(V) {hS} v1 {/Helvetica 1.000 cf} 4 20 0 48 0 label
+endgate
+} def
+
+/isource {
+% -32 -64 163 128 bbox
+(1) (m) 2 beginparm
+% fundamental
+1.00 0 0 0 source
+1 0.75 0 20 0 -8 2 polygon
+0.80 180 0 -20 arrowhead
+1.000 0.000 0.000 scb
+(i.p) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(i.m) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:I%i %pi.p %pi.m %v"1"%v"m") {/Times-Roman 1.000 cf} 2 20 0 -96 -160 infolabel
+(A) v2 {hS} v1 {/Helvetica 1.000 cf} 5 20 0 48 0 label
+endgate
+} def
+
+/acsource {
+% -32 -64 211 128 bbox
+(5) (0) (1) (k) 4 beginparm
+% fundamental
+1.00 0 0 0 source
+1 0.80 0 -48 0 48 -16 0 16 0 spline
+1.000 0.000 0.000 scb
+(s.p) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(s.m) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:V%i %ps.p %ps.m SIN\(%v"0" %v"5" %v"1"%v"k"\)) {/Helvetica 1.000 cf} 2 20 0 -336 -160 infolabel
+(offset) {ss} (V) {hS} v2 {/Helvetica 1.000 cf} 6 20 0 48 0 label
+(p-p) {ss} (V) {hS} v1 {/Helvetica 1.000 cf} 6 20 0 48 48 label
+(Hz) v4 {hS} v3 {/Helvetica 1.000 cf} 5 20 0 48 -48 label
+endgate
+} def
+
+/nmos {
+% -64 -64 161 128 bbox
+(3) (2) 2 beginparm
+% fundamental
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Helvetica 1.000 cf} 2 7 0 -64 0 pinlabel
+(S) {/Helvetica 1.000 cf} 2 13 0 0 -64 pinlabel
+(D) {/Helvetica 1.000 cf} 2 9 0 0 64 pinlabel
+sce
+(spice:M%i %pD %pG %pS GND nmos W=%v"3" L=%v"2") {/Times-Roman 1.000 cf} 2 4 0 -244 -139 infolabel
+(sim:n %pG %pD %pS) {/Times-Roman 1.000 cf} 2 4 0 -244 -187 infolabel
+v1 (W=) {/Helvetica 1.000 cf} 3 20 0 16 16 label
+v2 (L=) {/Helvetica 1.000 cf} 3 20 0 16 -16 label
+endgate
+} def
+
+/pmos {
+% -64 -64 161 128 bbox
+(3) (2) 2 beginparm
+% fundamental
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Helvetica 1.000 cf} 2 9 0 0 64 pinlabel
+(D) {/Helvetica 1.000 cf} 2 13 0 0 -64 pinlabel
+(G) {/Helvetica 1.000 cf} 2 7 0 -64 0 pinlabel
+sce
+(spice:M%i %pD %pG %pS Vdd pmos W=%v"3" L=%v"2") {/Times-Roman 1.000 cf} 2 4 0 -196 -139 infolabel
+(sim:p %pG %pD %pS) {/Times-Roman 1.000 cf} 2 4 0 -196 -187 infolabel
+v1 (W=) {/Helvetica 1.000 cf} 3 20 0 16 16 label
+v2 (L=) {/Helvetica 1.000 cf} 3 20 0 16 -16 label
+endgate
+} def
+
+/npn {
+% -64 -64 73 128 bbox
+begingate
+% fundamental
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 240 0 -48 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(B) {/Times-Roman 1.000 cf} 2 7 0 -64 0 pinlabel
+(E) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+(spice:Q%i %pC %pB %pE npn) {/Times-Roman 1.000 cf} 2 4 0 -244 -139 infolabel
+(sim:b %pB %pE %pC) {/Times-Roman 1.000 cf} 2 4 0 -244 -187 infolabel
+endgate
+} def
+
+/pnp {
+% -64 -64 64 128 bbox
+begingate
+% fundamental
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 120 -48 22 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+(B) {/Times-Roman 1.000 cf} 2 7 0 -64 0 pinlabel
+(E) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+sce
+(spice:Q%i %pC %pB %pE pnp) {/Times-Roman 1.000 cf} 2 4 0 -244 -139 infolabel
+endgate
+} def
+
+% EndLib
diff --git a/examples/border.ps b/examples/border.ps
new file mode 100644
index 0000000..fc474a0
--- /dev/null
+++ b/examples/border.ps
@@ -0,0 +1,231 @@
+%!PS-Adobe-3.0
+%%Title: border
+%%Creator: XCircuit v3.6 rev4
+%%CreationDate: Tue Feb 21 09:36:15 2006
+%%Pages: 1
+%%BoundingBox: 0 0 612 792
+%%DocumentNeededResources:
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 3.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--7/13/05 (tim.edwards@multigig.com)
+% The Johns Hopkins University (1993-2004)
+% MultiGiG, Inc. (2004-present)
+%
+%%BeginResource: procset XCIRCproc 3.3 0
+%
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 384 and 0 gt {/mshow {pop} def} {/mshow {show}
+ def} ifelse just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {dup type
+ /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse}
+ ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {mshow} {dup type
+ /arraytype eq {exec} {12 string cvs mshow} ifelse} ifelse} repeat
+ grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+/graphic { gsave 4 index cvx exec /DataSource get resetfile translate
+ 0 0 moveto neg rotate dup scale cvx exec image grestore } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def /setpagedevice {pop} def bop
+ rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+%%BeginSetup
+
+/bbord {
+begingate
+1 1.00 96 1920 1344 1920 2 polygon
+1 2.00 96 1896 1344 1896 2 polygon
+1 2.00 1416 1824 1416 96 2 polygon
+1 2.00 1344 1824 72 0.00 90.00 xcarc
+1 1.00 1344 1824 96 0.00 90.00 xcarc
+1 1.00 1440 1824 1440 96 2 polygon
+1 2.00 1344 96 72 270.00 360.00 xcarc
+1 1.00 1344 96 96 270.00 360.00 xcarc
+1 2.00 96 1824 72 90.00 180.00 xcarc
+1 1.00 96 1824 96 90.00 180.00 xcarc
+1 2.00 24 1824 24 96 2 polygon
+1 1.00 0 1824 0 96 2 polygon
+1 1.00 96 0 1344 0 2 polygon
+1 2.00 96 24 1344 24 2 polygon
+1 2.00 96 96 72 180.00 270.00 xcarc
+1 1.00 96 96 96 180.00 270.00 xcarc
+endgate
+} def
+
+/border-inch {
+begingate
+0.490 0.490 0.490 scb
+504 1.00 96 1896 96 1920 1344 1920 1344 1896 4 polygon
+504 1.00 0 96 0 1824 24 1824 24 96 4 polygon
+504 1.00 1416 1824 1416 96 1440 96 1440 1824 4 polygon
+0 95 beginpath
+96 96 96 180.00 270.00 arc
+96 24 1 polyc
+96 96 72 270.00 180.00 arcn
+248
+1.00 endpath
+0 1824 beginpath
+96 1824 96 180.00 90.00 arcn
+96 1896 1 polyc
+96 1824 72 90.00 180.00 arc
+
+248 1.00 endpath
+1440 96 beginpath
+1344 96 96 360.00 270.00 arcn
+1344 24 1 polyc
+1344 96 72 270.00
+360.00 arc
+248 1.00 endpath
+1440 1824 beginpath
+1344 1824 96 0.00 90.00 arc
+1344 1896 1 polyc
+1344 1824 72 90.00
+0.00 arcn
+248 1.00 endpath
+504 1.00 1344 0 1344 24 96 24 96 0 4 polygon
+sce
+1.00 0 0 0 bbord
+endgate
+} def
+
+
+%%EndSetup
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+%%PageBoundingBox: 0 0 612 792
+/pgsave save def bop
+1.0000 inchscale
+2.6000 setlinewidth 0 0 translate
+
+1.00 0 96 96 border-inch
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/buses.ps b/examples/buses.ps
new file mode 100644
index 0000000..4d61508
--- /dev/null
+++ b/examples/buses.ps
@@ -0,0 +1,365 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: buses
+%%Creator: Xcircuit v3.2
+%%CreationDate: Thu May 20 17:13:16 2004
+%%Pages: 1
+%%BoundingBox: 68 68 607 463
+%%DocumentNeededResources: font Times-Roman font Helvetica font Helvetica-Bold
+%%+ font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 3.1
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--1/5/04 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 3.1 0
+%
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 384 and 0 gt {/mshow {pop} def} {/mshow {show}
+ def} ifelse just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {dup type
+ /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse}
+ ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {mshow} {dup type
+ /arraytype eq {exec} {12 string cvs mshow} ifelse} ifelse} repeat
+ grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def /setpagedevice {pop} def bop
+ rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+%%BeginDocumentSetup
+
+/test_ic {
+<</idx (?) >> begingate
+0 1.00 -112 -112 -112 128 128 128 128 -112 4 polygon
+(test_ic) {/Helvetica-Bold cf} 2 21 0 1.00 0 48 label
+(rdata\(7:0\)) {/Helvetica cf} 2 23 0 1.00 112 -16 label
+1.000 0.000 0.000 scb
+(\(9:2\)) {/Helvetica cf} 2 20 0 1.00 128 -16 pinlabel
+(1) {/Helvetica cf} 2 17 0 1.00 0 128 pinlabel
+(10) {/Helvetica cf} 2 29 0 1.00 0 -112 pinlabel
+sce
+(VDD) {/Helvetica cf} 2 29 0 1.00 0 112 label
+(GND) {/Helvetica cf} 2 17 0 1.00 0 -96 label
+0.180 0.545 0.341 scb
+mark idx (pcb:U) {/Helvetica cf} ctmk 23 0 1.00 -128 48 infolabel
+sce
+mark idx (U) {/Helvetica cf} ctmk 23 0 1.00 -128 0 label
+endgate
+} def
+
+/5V {
+% trivial
+begingate
+1 1.00 -32 0 32 0 2 polygon
+1 1.00 0 0 0 -32 2 polygon
+(V) {/Times-Roman cf} (+5) {/Symbol cf} 4 17 0 0.90 0 8 label
+0.933 0.604 0.000 scb
+(dVdd) {/Times-Roman cf} 2 13 0 1.00 0 -32 pinglobal
+endgate
+} def
+
+/gnd {
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+0.933 0.604 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/Resistor {
+<</p_rot 0 /p_jst 20 /idx (?) /units (k) /value (1.0) >> begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) idx (spice:R) {/Times-Roman cf} ctmk 4 0 1.00 -208
+-160 infolabel
+(sim:r %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (W) {/Symbol cf} units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00
+32 0 label
+0.180 0.545 0.341 scb
+mark idx (pcb:R) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+/ic2 {
+<</idx (?) >> begingate
+0 1.00 -112 -96 -112 112 112 112 112 -96 4 polygon
+1.000 0.000 0.000 scb
+(\(2:3\)) {/Helvetica cf} 2 23 0 1.00 -112 16 pinlabel
+(1) {/Helvetica cf} 2 29 0 1.00 0 -96 pinlabel
+(4) {/Helvetica cf} 2 17 0 1.00 0 112 pinlabel
+sce
+(IC#2) {/Helvetica-Bold cf} 2 21 0 1.00 0 16 label
+(d) {/Helvetica cf} 2 20 0 1.00 -96 16 label
+(GND) {/Helvetica cf} 2 17 0 1.00 0 -80 label
+(VDD) {/Helvetica cf} 2 29 0 1.00 0 96 label
+0.180 0.545 0.341 scb
+mark idx (pcb:U) {/Helvetica cf} ctmk 20 0 1.00 128 64 infolabel
+sce
+mark idx (U) {/Helvetica cf} ctmk 20 0 1.00 128 16 label
+endgate
+} def
+
+/Polarized {
+<</p_rot 0 /p_jst 20 /idx (?) /units (p) /value (1.0) >> begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) idx (spice:C) {/Times-Roman cf} ctmk 4 0 1.00 -208
+-160 infolabel
+(sim:e %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (F) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+0.180 0.545 0.341 scb
+mark idx (pcb:C) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+/tap {
+% trivial
+<</out (bus\(0\)) /in (bus\(0:7\)) >> begingate
+496 1.00 0 8 16 0 0 -8 3 polygon
+1.000 0.000 0.000 scb
+mark out {/Helvetica cf} ctmk 20 0 1.00 16 0 pinlabel
+mark in {/Helvetica cf} ctmk 23 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/arrowhead {
+% trivial
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/arrow {
+% trivial
+begingate
+1 0.80 0 -40 0 20 2 polygon
+1.00 0 0 40 arrowhead
+endgate
+} def
+
+
+%%EndDocumentSetup
+
+%%Page: bustest 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+1.0000 inchscale
+2.6000 setlinewidth 1093 852 translate
+
+1 1.00 -592 -384 -336 -384 -336 288 -300 288 4 polygon
+1.000 0.000 0.000 scb
+(mynet\(0:7\)) {/Helvetica cf} 2 20 0 1.00 -300 288 pinlabel
+sce
+1 1.00 -320 -224 160 -224 2 polygon
+1 1.00 -320 -144 48 -144 2 polygon
+1 1.00 -320 -64 -32 -64 2 polygon
+1.000 0.000 0.000 scb
+(mynet\(0\)) {/Helvetica cf} 2 23 0 1.00 -360 -64 pinlabel
+(mynet\(1:2\)) {/Helvetica cf} 2 23 0 1.00 -360 -144 pinlabel
+(mynet\(4:3\)) {/Helvetica cf} 2 23 0 1.00 -360 -224 pinlabel
+sce
+1 1.00 -320 -304 -32 -304 2 polygon
+1.000 0.000 0.000 scb
+(mynet\(4\)) {/Helvetica cf} 2 23 0 1.00 -360 -304 pinlabel
+sce
+1.00 0 -720 -368 <</idx (3) >> test_ic
+1.00 0 -720 -208 5V
+1.00 0 -720 -480 gnd
+1 1.00 -32 -64 -32 176 2 polygon
+-1.00 270 64 176 <</idx (1) /p_jst 17 /p_rot 90 >> Resistor
+1 1.00 0 176 -32 176 2 polygon
+1 1.00 128 176 176 176 2 polygon
+1.00 0 176 144 gnd
+1.00 0 272 -80 <</idx (2) >> ic2
+-1.00 0 -32 -416 <</idx (1) >> Polarized
+1 1.00 -32 -304 -32 -352 2 polygon
+1.00 0 -32 -480 gnd
+1.00 0 336 -432 <</idx (1) >> ic2
+1 1.00 160 -224 160 -416 224 -416 3 polygon
+1 1.00 48 -144 48 -64 160 -64 3 polygon
+1.00 0 336 -528 gnd
+1.00 0 272 -176 gnd
+1.00 0 272 64 5V
+1.00 0 336 -288 5V
+1 1.00 176 144 176 176 2 polygon
+1.00 0 -336 -64 tap
+1.00 0 -336 -144 <</out (bus\(1:2\)) >> tap
+1.00 0 -336 -224 <</out (bus\(4:3\)) >> tap
+1.00 0 -336 -304 <</out (bus\(4\)) >> tap
+1.000 0.000 0.000 scb
+(mynet\(0\)) {/Times-Roman cf} 2 20 0 0.70 -784 216 pinlabel
+(mynet\(1\)) {/Times-Roman cf} 2 20 0 0.70 -784 184 pinlabel
+(mynet\(2\)) {/Times-Roman cf} 2 20 0 0.70 -784 152 pinlabel
+(mynet\(3\)) {/Times-Roman cf} 2 20 0 0.70 -784 120 pinlabel
+(mynet\(4\)) {/Times-Roman cf} 2 20 0 0.70 -784 88 pinlabel
+(mynet\(5\)) {/Times-Roman cf} 2 20 0 0.70 -784 56 pinlabel
+(mynet\(6\)) {/Times-Roman cf} 2 20 0 0.70 -784 24 pinlabel
+(mynet\(7\)) {/Times-Roman cf} 2 20 0 0.70 -784 -8 pinlabel
+sce
+2 1.00 -816 -40 -816 248 -640 248 -640 -40 4 polygon
+(on each of the pin labels below.) {CR} (Try connectivity \(Alt-w\))
+{/Times-Roman cf} 4 16 0 0.70 -820 272 label
+-1.00 225 -296 -16 arrow
+(symbol.) {CR} (labels in the "tap") {CR} (defined by the) {CR} (subnets are)
+{/Times-Roman cf} 8 16 0 0.70 -260 28 label
+-1.00 150 -464 -8 arrow
+(for reference.) {CR} (These labels are) {/Times-Roman cf} 4 17 0 0.70 -492 48
+label
+-1.00 255 -48 312 arrow
+(nothing at all.) {CR} (also valid to write "mynet" here, or) {CR}
+(spelled out explicitly. However, it is) {CR}
+(The bus name and dimensions can be) {/Times-Roman cf} 8 16 0 0.70 16 272 label
+(XCircuit bus notation tutorial\320buses.ps) {/Times-Roman cf} 2 16 0 0.70 -848
+-656 label
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/diffamp_test.ps b/examples/diffamp_test.ps
new file mode 100644
index 0000000..e3c4a83
--- /dev/null
+++ b/examples/diffamp_test.ps
@@ -0,0 +1,518 @@
+%!PS-Adobe-3.0
+%%Title: examples/diffamp_test
+%%Creator: Xcircuit v2.1
+%%CreationDate: Thu Dec 14 21:21:31 2000
+%%Pages: 2
+%%BoundingBox: 176 218 436 574
+%%DocumentNeededResources: font Times-Roman font Helvetica font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.1
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--11/20/00 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.1 4
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/CR { 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/Kn { 2 copy kY add /kY exch def kX add /kX exch def rmoveto } bind def
+/bs { stW 0 Kn } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { /fscale exch def xfont findfont fscale scalefont setfont
+ /kX 0 def /kY 0 def} def
+/cf { dup type /realtype eq {40 mul /fscale0 exch def } if /xfont exch def
+ fscale0 cf0 } def
+/ss { 0.67 fscale mul cf0 0 fscale 0.5 mul neg Kn } def
+/Ss { 0.67 fscale mul cf0 0 fscale 0.5 mul Kn } def
+/ns { kX neg kY neg Kn fscale0 cf0 } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt
+ {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore
+ 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore
+ dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def gsave dup 1 add copy
+ 0 exch {exch dup type /stringtype eq {true charpath flattenpath}
+ {exec} ifelse } repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll
+ just 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub
+ 0.5 mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch
+ just 4 and 0 gt {just 8 and 0 gt {exch pop neg fspc sub}
+ {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def Kn currentpoint translate /Bline 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/ampl_test {
+% -224 32 192 224 bbox
+% ampl_test is_schematic
+begingate
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica 1.000 cf} 2 23 0 -224 192 pinlabel
+(Vinp) {/Helvetica 1.000 cf} 2 23 0 -224 96 pinlabel
+(Voutn) {/Helvetica 1.000 cf} 2 20 0 -32 96 pinlabel
+(Voutp) {/Helvetica 1.000 cf} 2 20 0 -32 192 pinlabel
+(Vcmref) {/Helvetica 1.000 cf} 2 25 0 -160 256 pinlabel
+(Vbias) {/Helvetica 1.000 cf} 2 29 0 -160 32 pinlabel
+sce
+1 1.00 -224 96 -192 96 2 polygon
+1 1.00 -224 192 -192 192 2 polygon
+1 1.00 -128 192 -32 192 2 polygon
+1 1.00 -128 96 -32 96 2 polygon
+(-) {/Symbol 1.000 cf} 2 5 0 -141 106 label
+(+) {/Symbol 1.000 cf} 2 5 0 -141 186 label
+1 1.00 -32 144 -192 224 -192 64 -32 144 4 polygon
+(-) {/Symbol 1.000 cf} 2 5 0 -173 186 label
+(+) {/Symbol 1.000 cf} 2 5 0 -173 106 label
+1 1.00 -160 80 -160 32 2 polygon
+1 1.00 -160 208 -160 256 2 polygon
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman 1.000 cf} 2 1 0 0 0 pinglobal
+endgate
+} def
+
+/source {
+% -32 -64 64 128 bbox
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/Vsource {
+% -32 -64 139 128 bbox
+(5) 1 beginparm
+1.00 0 0 0 source
+(+) {/Symbol 1.000 cf} 2 5 0 0 18 label
+(-) {/Symbol 1.000 cf} 2 5 0 0 -18 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(v.m) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+mark v1 (spice:V%i %pv.p %pv.m ) {/Times-Roman 1.000 cf} ctmk 20 0 -96 -160 infolabel
+mark (V) {hS} v1 {/Times-Roman 1.000 cf} ctmk 20 0 48 0 label
+endgate
+} def
+
+/dot {
+% -6 -6 12 12 bbox
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman 1.000 cf} 2 29 0 0 0 pinlabel
+endgate
+} def
+
+/jumper {
+% -4 -14 18 28 bbox
+% trivial
+begingate
+1 1.00 0 0 10 -90.00 90.00 xcarc
+1 1.00 0 10 0 16 2 polygon
+1 1.00 0 -10 0 -16 2 polygon
+1.000 0.000 0.000 scb
+(a) {/Times-Roman 1.000 cf} 2 1 0 0 16 pinlabel
+(a) {/Times-Roman 1.000 cf} 2 13 0 0 -16 pinlabel
+endgate
+} def
+
+/circle {
+% -6 -12 28 24 bbox
+% trivial
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman 1.000 cf} 2 4 0 16 0 pinlabel
+(out) {/Times-Roman 1.000 cf} 2 7 0 0 0 pinlabel
+endgate
+} def
+
+%%Page: diffamp_test:1 1
+%%PageOrientation: Landscape
+/pgsave save def bop
+% 1200 848 offsets
+90 rotate 42 -654 translate
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 1024 832 ampl_test
+1.00 0 864 736 gnd
+1.00 0 864 800 [(1) ] Vsource
+1.00 0 1056 800 [(2.5) ] Vsource
+1 1.00 1056 864 1056 1088 864 1088 3 polygon
+1.00 0 1056 736 gnd
+1 1.00 800 928 752 928 752 864 848 864 4 polygon
+1 1.00 880 864 1056 864 2 polygon
+1.00 0 1056 864 dot
+1.00 90 864 864 jumper
+1 1.00 800 1024 720 1024 2 polygon
+1.00 -1 720 1024 circle
+1 1.00 992 928 1040 928 2 polygon
+1 1.00 992 1024 1040 1024 2 polygon
+1.00 90 1056 1024 jumper
+1.00 90 1056 928 jumper
+1 1.00 1072 1024 1136 1024 2 polygon
+1 1.00 1072 928 1136 928 2 polygon
+1.00 0 1136 1024 circle
+1.00 0 1136 928 circle
+1.000 0.000 0.000 scb
+(Vinse) {/Helvetica 1.000 cf} 2 23 0 704 1024 pinlabel
+(Voutp) {/Helvetica 1.000 cf} 2 20 0 1152 1024 pinlabel
+(Voutm) {/Helvetica 1.000 cf} 2 20 0 1152 928 pinlabel
+sce
+1408 624 beginpath
+1408 1168 1 polyc
+1376 1168 32 0.00 90.00 arc
+512 1200 1 polyc
+512 1168 32 90.00 180.00 arc
+480 624
+1 polyc
+512 624 32 180.00 270.00 arc
+1376 592 1 polyc
+1376 624 32 270.00 360.00 arc
+1 1.00 endpath
+(Differential amplifier: test) {/Helvetica 1.000 cf} 2 25 0 944 1232 label
+pgsave restore showpage
+
+/pMOS {
+% -64 -64 240 128 bbox
+(3) (2) 2 beginparm
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(D) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+(G) {/Times-Roman 1.000 cf} 2 7 0 -64 0 pinlabel
+sce
+(spice:M%i %pD %pG %pS Vdd pmos W=%v"3" L=%v"2") {/Times-Roman 1.000 cf} 2 4 0
+-196 -139 infolabel
+sce
+(sim:p %pG %pS %pD) {/Times-Roman 1.000 cf} 2 4 0 -196 -187 infolabel
+mark v1 (W=) {/Times-Roman 1.000 cf} ctmk 20 0 16 32 label
+mark v2 (L=) {/Times-Roman 1.000 cf} ctmk 20 0 16 -32 label
+endgate
+} def
+
+/Resistor {
+% -14 -64 151 128 bbox
+(1.0) (k) 2 beginparm
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+sce
+mark v2 v1 (spice:R%i %pr.1 %pr.2 ) {/Times-Roman 1.000 cf} ctmk 4 0 -208 -160 infolabel
+(sim:R %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 4 0 -208 -208 infolabel
+mark (W) {/Symbol 1.000 cf} v2 {hS} v1 {/Times-Roman 1.000 cf} ctmk 20 0 32 0 label
+endgate
+} def
+
+/nMOS {
+% -64 -64 193 128 bbox
+(3) (2) 2 beginparm
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman 1.000 cf} 2 7 0 -64 0 pinlabel
+(S) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+(D) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+sce
+(spice:M%i %pD %pG %pS GND nmos W=%v"3" L=%v"2") {/Times-Roman 1.000 cf} 2 4 0
+-244 -139 infolabel
+sce
+(sim:n %pG %pS %pD) {/Times-Roman 1.000 cf} 2 4 0 -244 -187 infolabel
+mark v1 (W=) {/Times-Roman 1.000 cf} ctmk 20 0 16 32 label
+mark v2 (L=) {/Times-Roman 1.000 cf} ctmk 20 0 16 -32 label
+endgate
+} def
+
+/pmos4 {
+% -64 -64 211 128 bbox
+(3) (2) 2 beginparm
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel
+(D) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel
+(G) {/Times-Roman 1.000 cf} 2 7 0 -64 0 pinlabel
+sce
+(spice:M%i %pD %pG %pS %pB pmos W=%v"3" L=%v"2") {/Times-Roman 1.000 cf} 2 4 0
+-324 -139 infolabel
+sce
+(sim:p %pG %pS %pD) {/Times-Roman 1.000 cf} 2 4 0 -196 -187 infolabel
+mark v1 (W=) {/Times-Roman 1.000 cf} ctmk 20 0 16 32 label
+mark v2 (L=) {/Times-Roman 1.000 cf} ctmk 20 0 16 -32 label
+1 1.00 -32 0 16 0 2 polygon
+1.000 0.000 0.000 scb
+(B) {/Times-Roman 1.000 cf} 2 20 0 16 0 pinlabel
+endgate
+} def
+
+/vdd {
+% -32 0 64 66 bbox
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman 0.900 cf} 2 17 0 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman 1.000 cf} 2 13 0 0 0 pinglobal
+endgate
+} def
+
+/halfamp {
+% -584 -380 841 830 bbox
+begingate
+1.00 0 128 320 [(525.6) (1.8) ] pMOS
+1.00 -1 -16 320 [(294) (2.4) ] pMOS
+1 1.00 64 320 -544 320 2 polygon
+1.00 0 128 384 vdd
+1.00 0 -16 384 vdd
+1.00 0 128 -96 [(387) (1.2) ] nMOS
+1 1.00 128 -32 128 256 2 polygon
+1 1.00 48 0 128 0 2 polygon
+1.00 0 128 0 dot
+1 1.00 -16 -112 -16 -160 2 polygon
+1.00 0 -16 -160 gnd
+1.00 0 128 -160 gnd
+1 1.00 64 -96 -448 -96 2 polygon
+1 1.00 -16 -64 -16 -80 2 polygon
+1.00 0 -16 -96 jumper
+1.00 -271 -224 16 [(73.2) (35.2) ] pmos4
+1 1.00 -224 0 -224 -96 2 polygon
+1 1.00 -288 16 -288 -96 2 polygon
+1 1.00 -160 16 -160 -96 2 polygon
+1 1.00 -224 80 -224 160 -16 160 3 polygon
+1.00 0 -16 160 dot
+1.00 0 -160 -96 dot
+1.00 0 -224 -96 dot
+1.00 0 -288 -96 dot
+1.00 0 -448 -96 dot
+1 1.00 -448 32 -448 -192 2 polygon
+1.00 -1 -448 96 [(294) (3) ] pmos4
+1 1.00 -384 96 -352 96 2 polygon
+1.00 0 -352 96 circle
+1.00 0 -448 -256 [(21) (3) ] nMOS
+1.00 0 -448 -320 gnd
+1 1.00 -464 96 -560 96 2 polygon
+1 1.00 -448 160 -560 160 2 polygon
+1 1.00 -16 64 -16 256 2 polygon
+1.00 -1 -16 0 [(588) (1.2) ] pMOS
+endgate
+} def
+
+%%Page: ampl_test 2
+%%PageOrientation: Landscape
+/pgsave save def bop
+% ampl_test is_symbol
+% 2257 752 offsets
+90 rotate -98 -513 translate
+0.6472 inchscale
+2.6000 setlinewidth
+
+1.00 0 2001 1136 [(336) (1.8) ] pMOS
+1.00 90 2385 1280 [(300) (k) ] Resistor
+1.00 -1 3121 400 [(21) (3) ] nMOS
+1.00 0 2897 400 [(21) (3) ] nMOS
+1 1.00 3185 400 3185 464 3121 464 3121 688 4 polygon
+1.00 0 2897 752 [(126) (1.2) ] pmos4
+1 1.00 2897 464 2897 688 2 polygon
+1.00 -1 3121 752 [(126) (1.2) ] pmos4
+1 1.00 2913 752 3105 752 2 polygon
+1 1.00 2897 816 3121 816 2 polygon
+1.00 0 3009 816 dot
+1 1.00 3009 752 3009 1072 2 polygon
+1.00 0 3009 1136 [(336) (1.8) ] pMOS
+1.00 0 3009 1200 vdd
+1.00 0 2897 336 gnd
+1.00 0 3121 336 gnd
+1 1.00 2897 464 2817 464 2817 400 3 polygon
+1 1.00 2833 400 1953 400 2 polygon
+1.00 0 2001 816 dot
+1 1.00 2001 752 2001 1072 2 polygon
+1 1.00 2833 752 2801 752 2 polygon
+1 1.00 3185 752 3217 752 2 polygon
+1.00 0 3217 752 circle
+1.00 180 2801 752 circle
+1.00 0 2001 1200 vdd
+1 1.00 2945 1136 1937 1136 2 polygon
+1.00 0 2897 464 dot
+1.00 0 2817 400 dot
+1.00 0 3009 752 dot
+1.00 0 2001 752 dot
+1.00 0 3121 464 dot
+1.00 90 2001 976 jumper
+1.00 90 2577 1280 [(300) (k) ] Resistor
+1 1.00 2449 1280 2513 1280 2 polygon
+1 1.00 2481 1280 2481 1248 2 polygon
+1 1.00 2321 1280 2289 1280 2289 1248 3 polygon
+1 1.00 2641 1280 2673 1280 2673 1248 3 polygon
+1.00 0 2481 1280 dot
+1.00 270 2289 1248 circle
+1.00 270 2481 1248 circle
+1.00 270 2673 1248 circle
+1.00 0 2561 656 halfamp
+1 1.00 1377 976 1169 976 2 polygon
+1.00 -1 1105 976 [(42) (1.8) ] pMOS
+1 1.00 1185 976 1185 912 1105 912 3 polygon
+1.00 0 1105 1040 vdd
+1.00 0 1185 976 dot
+1 1.00 1105 912 1105 624 2 polygon
+1.00 -1 929 1136 [(84) (1.8) ] pMOS
+1 1.00 993 1136 1937 1136 2 polygon
+1 1.00 1009 1136 1009 1072 929 1072 929 624 4 polygon
+1.00 0 929 1200 vdd
+1.00 0 1105 496 gnd
+1.00 0 929 496 gnd
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica 1.000 cf} 2 20 0 2225 752 pinlabel
+(Vinp) {/Helvetica 1.000 cf} 2 23 0 1777 752 pinlabel
+sce
+1 1.00 2689 848 2737 848 2 polygon
+1.00 0 2737 848 circle
+1.00 0 2689 848 dot
+1.000 0.000 0.000 scb
+(Voutn) {/Helvetica 1.000 cf} 2 20 0 2753 848 pinlabel
+sce
+1 1.00 1313 848 1265 848 2 polygon
+1.00 -1 1265 848 circle
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica 1.000 cf} 2 23 0 1249 848 pinlabel
+sce
+1.00 0 1313 848 dot
+1.00 0 929 1072 dot
+1.00 0 1009 1136 dot
+1.00 0 1105 912 dot
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica 1.000 cf} 2 29 0 2289 1232 pinlabel
+(Voutn) {/Helvetica 1.000 cf} 2 29 0 2673 1232 pinlabel
+(Vcmin) {/Helvetica 1.000 cf} 2 29 0 2481 1232 pinlabel
+(Vcmin) {/Helvetica 1.000 cf} 2 29 0 2785 752 pinlabel
+(Vcmref) {/Helvetica 1.000 cf} 2 20 0 3233 752 pinlabel
+sce
+1.00 -1 1441 656 halfamp
+1.00 0 1105 560 [(21) (16.5) ] nMOS
+1.00 0 929 560 [(21) (16.5) ] nMOS
+1 1.00 1041 560 817 560 2 polygon
+1.00 -1 817 560 circle
+1.000 0.000 0.000 scb
+(Vbias) {/Helvetica 1.000 cf} 2 23 0 801 560 pinlabel
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/diffamp_test2.ps b/examples/diffamp_test2.ps
new file mode 100644
index 0000000..b11d62a
--- /dev/null
+++ b/examples/diffamp_test2.ps
@@ -0,0 +1,533 @@
+%!PS-Adobe-3.0
+%%Title: src/xcircuit-3.1.26/examples/diffamp_test2
+%%Creator: Xcircuit v3.1
+%%CreationDate: Tue Nov 11 12:51:34 2003
+%%Pages: 2
+%%BoundingBox: 178 218 434 574
+%%DocumentNeededResources: font Helvetica font Times-Roman font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.4
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--1/15/03 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.4 3
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {exec}
+ ifelse } repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {show}{exec} ifelse}
+ repeat grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/setdefaults { aload length 2 idiv {currentdict 2 index known
+ {pop pop} {def} ifelse} repeat } bind def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def bop rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/ampl_test {
+% ampl_test is_schematic
+begingate
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica cf} 2 23 0 1.00 -224 192 pinlabel
+(Vinp) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(Voutn) {/Helvetica cf} 2 20 0 1.00 -32 96 pinlabel
+(Voutp) {/Helvetica cf} 2 20 0 1.00 -32 192 pinlabel
+(Vcmref) {/Helvetica cf} 2 25 0 1.00 -160 256 pinlabel
+(Vbias) {/Helvetica cf} 2 29 0 1.00 -160 32 pinlabel
+sce
+1 1.00 -224 96 -192 96 2 polygon
+1 1.00 -224 192 -192 192 2 polygon
+1 1.00 -128 192 -32 192 2 polygon
+1 1.00 -128 96 -32 96 2 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -141 106 label
+(+) {/Symbol cf} 2 5 0 1.00 -141 186 label
+1 1.00 -32 144 -192 224 -192 64 -32 144 4 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -173 186 label
+(+) {/Symbol cf} 2 5 0 1.00 -173 106 label
+1 1.00 -160 80 -160 32 2 polygon
+1 1.00 -160 208 -160 256 2 polygon
+endgate
+} def
+
+/gnd {
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/source {
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/Vsource {
+<</value (5) >> begingate
+1.00 0 0 0 source
+(+) {/Symbol cf} 2 5 0 1.00 0 18 label
+(-) {/Symbol cf} 2 5 0 1.00 0 -18 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(v.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark value (spice:V%i %pv.p %pv.m ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (V) {hS} value {/Times-Roman cf} ctmk 20 0 1.00 48 0 label
+endgate
+} def
+
+/dot {
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/jumper {
+% trivial
+begingate
+1 1.00 0 0 10 -90.00 90.00 xcarc
+1 1.00 0 10 0 16 2 polygon
+1 1.00 0 -10 0 -16 2 polygon
+1.000 0.000 0.000 scb
+(a) {/Times-Roman cf} 2 1 0 1.00 0 16 pinlabel
+(a) {/Times-Roman cf} 2 13 0 1.00 0 -16 pinlabel
+endgate
+} def
+
+/circle {
+% trivial
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 0 0 pinlabel
+endgate
+} def
+
+%%Page: diffamp_test 1
+%%PageOrientation: Landscape
+/pgsave save def bop
+% 1203 848 offsets
+90 rotate 40 -652 translate
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 1027 832 ampl_test
+1.00 0 867 736 gnd
+1.00 0 867 800 Vsource
+1.00 0 1059 800 <</value (2.5) >> Vsource
+1 1.00 1059 864 1059 1088 867 1088 3 polygon
+1.00 0 1059 736 gnd
+1 1.00 803 928 755 928 755 864 851 864 4 polygon
+1 1.00 883 864 1059 864 2 polygon
+1.00 0 1059 864 dot
+1.00 270 867 864 jumper
+1 1.00 803 1024 723 1024 2 polygon
+-1.00 0 723 1024 circle
+1 1.00 995 928 1043 928 2 polygon
+1 1.00 995 1024 1043 1024 2 polygon
+1.00 270 1059 1024 jumper
+1.00 270 1059 928 jumper
+1 1.00 1075 1024 1139 1024 2 polygon
+1 1.00 1075 928 1139 928 2 polygon
+1.00 0 1139 1024 circle
+1.00 0 1139 928 circle
+1.000 0.000 0.000 scb
+(Vinse) {/Helvetica cf} 2 23 0 1.00 707 1024 pinlabel
+(Voutp) {/Helvetica cf} 2 20 0 1.00 1155 1024 pinlabel
+(Voutm) {/Helvetica cf} 2 20 0 1.00 1155 928 pinlabel
+sce
+1411 624 beginpath
+1411 1168 1 polyc
+1379 1168 32 0.00 90.00 arc
+515 1200 1 polyc
+
+515 1168 32 90.00 180.00 arc
+483 624 1 polyc
+515 624 32 180.00 270.00 arc
+1379 592
+1 polyc
+1379 624 32 270.00 360.00 arc
+1 1.00 endpath
+(Differential amplifier: test) {/Helvetica cf} 2 25 0 1.00 947 1232 label
+pgsave restore showpage
+
+/pMOS {
+<</p_yps1 -32 /p_xps1 16 /p_rot1 0 /p_yps 32 /p_xps 16 /p_rot 0 /width
+(3) /length (2) >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS Vdd pmos W=%v"3" L=%v"2") {/Times-Roman cf} 2 4 0 1.00
+-196 -139 infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+endgate
+} def
+
+/Resistor {
+<</p_rot 0 /p_jst 20 /value (1.0) /units (k) >> begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(r.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value (spice:R%i %pr.1 %pr.2 ) {/Times-Roman cf} ctmk 4 0 1.00 -208
+-160 infolabel
+(sim:R %pr.1 %pr.2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (W) {/Symbol cf} units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00
+32 0 label
+endgate
+} def
+
+/nMOS {
+<</p_rot1 0 /p_yps1 -32 /p_xps1 16 /p_rot 0 /p_yps 32 /p_xps 16 /width
+(3) /length (2) >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS GND nmos W=%v"3" L=%v"2") {/Times-Roman cf} 2 4 0 1.00
+-244 -139 infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+endgate
+} def
+
+/pmos4 {
+<</p_rot1 0 /p_yps1 -32 /p_xps1 16 /p_rot 0 /p_yps 32 /p_xps 16 /width
+(3) /length (2) >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width (spice:M%i %pD %pG %pS %pB pmos W=) {/Times-Roman cf}
+ctmk 4 0 1.00 -324 -139 infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+1 1.00 -32 0 16 0 2 polygon
+1.000 0.000 0.000 scb
+(B) {/Times-Roman cf} 2 20 0 1.00 16 0 pinlabel
+endgate
+} def
+
+/vdd {
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/halfamp {
+begingate
+1.00 0 128 320 <</p_yps1 32 /p_yps 64 /width (525.6) /length (1.8) >> pMOS
+-1.00 0 -16 320 <</p_xps1 48 /p_yps1 32 /p_xps 48 /p_yps 64 /width (294) /length
+(2.4) >> pMOS
+1 1.00 64 320 -544 320 2 polygon
+1.00 0 128 384 vdd
+1.00 0 -16 384 vdd
+1.00 0 128 -96 <</p_yps -32 /p_yps1 -64 /width (387) /length (1.2) >> nMOS
+1 1.00 128 -32 128 256 2 polygon
+1 1.00 48 0 128 0 2 polygon
+1.00 0 128 0 dot
+1 1.00 -16 -112 -16 -160 2 polygon
+1.00 0 -16 -160 gnd
+1.00 0 128 -160 gnd
+1 1.00 64 -96 -448 -96 2 polygon
+1 1.00 -16 -64 -16 -80 2 polygon
+1.00 0 -16 -96 jumper
+-1.00 270 -224 16 <</p_yps -160 /p_xps1 -80 /p_yps1 -160 /p_rot1 270 /p_rot 270 /p_xps
+-112 /width (73.2) /length (35.2) >> pmos4
+1 1.00 -224 0 -224 -96 2 polygon
+1 1.00 -288 16 -288 -96 2 polygon
+1 1.00 -160 16 -160 -96 2 polygon
+1 1.00 -224 80 -224 160 -16 160 3 polygon
+1.00 0 -16 160 dot
+1.00 0 -160 -96 dot
+1.00 0 -224 -96 dot
+1.00 0 -288 -96 dot
+1.00 0 -448 -96 dot
+1 1.00 -448 32 -448 -192 2 polygon
+-1.00 0 -448 96 <</p_xps1 -160 /p_yps1 48 /p_xps -160 /p_yps 80 /width (294) /length
+(3) >> pmos4
+1 1.00 -384 96 -352 96 2 polygon
+1.00 0 -352 96 circle
+1.00 0 -448 -256 <</p_xps1 32 /p_xps 32 /p_yps1 32 /p_yps 64 /width (21) /length
+(3) >> nMOS
+1.00 0 -448 -320 gnd
+1 1.00 -464 96 -560 96 2 polygon
+1 1.00 -448 160 -560 160 2 polygon
+1 1.00 -16 64 -16 256 2 polygon
+-1.00 0 -16 0 <</p_yps1 0 /width (588) /length (1.2) >> pMOS
+endgate
+} def
+
+%%Page: ampl_test 2
+%%PageOrientation: Landscape
+/pgsave save def bop
+% ampl_test is_symbol
+% 2295 762 offsets
+90 rotate -107 -503 translate
+0.6472 inchscale
+2.6000 setlinewidth
+
+1.00 0 2039 1146 <</p_yps1 32 /p_yps 64 /width (336) /length (1.8) >> pMOS
+1.00 270 2423 1290 <</p_jst 17 /p_rot 90 /value (300) >> Resistor
+-1.00 0 3159 410 <</p_yps 0 /width (21) /length (3) >> nMOS
+1.00 0 2935 410 <</p_yps1 16 /p_yps 48 /width (21) /length (3) >> nMOS
+1 1.00 3223 410 3223 474 3159 474 3159 698 4 polygon
+1.00 0 2935 762 <</p_xps1 -144 /p_yps1 -96 /p_xps -144 /p_yps -64 /width (126) /length
+(1.2) >> pmos4
+1 1.00 2935 474 2935 698 2 polygon
+-1.00 0 3159 762 <</p_xps1 -144 /p_yps1 -80 /p_xps -144 /p_yps -48 /width (126) /length
+(1.2) >> pmos4
+1 1.00 2951 762 3143 762 2 polygon
+1 1.00 2935 826 3159 826 2 polygon
+1.00 0 3047 826 dot
+1 1.00 3047 762 3047 1082 2 polygon
+1.00 0 3047 1146 <</p_yps1 0 /width (336) /length (1.8) >> pMOS
+1.00 0 3047 1210 vdd
+1.00 0 2935 346 gnd
+1.00 0 3159 346 gnd
+1 1.00 2935 474 2855 474 2855 410 3 polygon
+1 1.00 2871 410 1991 410 2 polygon
+1.00 0 2039 826 dot
+1 1.00 2039 762 2039 1082 2 polygon
+1 1.00 2871 762 2839 762 2 polygon
+1 1.00 3223 762 3255 762 2 polygon
+1.00 0 3255 762 circle
+1.00 180 2839 762 circle
+1.00 0 2039 1210 vdd
+1 1.00 2983 1146 1975 1146 2 polygon
+1.00 0 2935 474 dot
+1.00 0 2855 410 dot
+1.00 0 3047 762 dot
+1.00 0 2039 762 dot
+1.00 0 3159 474 dot
+1.00 270 2039 986 jumper
+1.00 270 2615 1290 <</p_jst 17 /p_rot 90 /value (300) >> Resistor
+1 1.00 2487 1290 2551 1290 2 polygon
+1 1.00 2519 1290 2519 1258 2 polygon
+1 1.00 2359 1290 2327 1290 2327 1258 3 polygon
+1 1.00 2679 1290 2711 1290 2711 1258 3 polygon
+1.00 0 2519 1290 dot
+1.00 90 2327 1258 circle
+1.00 90 2519 1258 circle
+1.00 90 2711 1258 circle
+1.00 0 2599 666 halfamp
+1 1.00 1415 986 1207 986 2 polygon
+-1.00 0 1143 986 <</p_yps1 0 /width (42) /length (1.8) >> pMOS
+1 1.00 1223 986 1223 922 1143 922 3 polygon
+1.00 0 1143 1050 vdd
+1.00 0 1223 986 dot
+1 1.00 1143 922 1143 634 2 polygon
+-1.00 0 967 1146 <</p_yps1 0 /width (84) /length (1.8) >> pMOS
+1 1.00 1031 1146 1975 1146 2 polygon
+1 1.00 1047 1146 1047 1082 967 1082 967 634 4 polygon
+1.00 0 967 1210 vdd
+1.00 0 1143 506 gnd
+1.00 0 967 506 gnd
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica cf} 2 20 0 1.00 2263 762 pinlabel
+(Vinp) {/Helvetica cf} 2 23 0 1.00 1815 762 pinlabel
+sce
+1 1.00 2727 858 2775 858 2 polygon
+1.00 0 2775 858 circle
+1.00 0 2727 858 dot
+1.000 0.000 0.000 scb
+(Voutn) {/Helvetica cf} 2 20 0 1.00 2791 858 pinlabel
+sce
+1 1.00 1351 858 1303 858 2 polygon
+-1.00 0 1303 858 circle
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica cf} 2 23 0 1.00 1287 858 pinlabel
+sce
+1.00 0 1351 858 dot
+1.00 0 967 1082 dot
+1.00 0 1047 1146 dot
+1.00 0 1143 922 dot
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica cf} 2 29 0 1.00 2327 1242 pinlabel
+(Voutn) {/Helvetica cf} 2 29 0 1.00 2711 1242 pinlabel
+(Vcmin) {/Helvetica cf} 2 29 0 1.00 2519 1242 pinlabel
+(Vcmin) {/Helvetica cf} 2 29 0 1.00 2823 762 pinlabel
+(Vcmref) {/Helvetica cf} 2 20 0 1.00 3271 762 pinlabel
+sce
+-1.00 0 1479 666 halfamp
+1.00 0 1143 570 <</p_yps1 16 /p_yps 48 /width (21) /length (16.5) >> nMOS
+1.00 0 967 570 <</p_yps1 32 /p_yps 64 /width (21) /length (16.5) >> nMOS
+1 1.00 1079 570 855 570 2 polygon
+-1.00 0 855 570 circle
+1.000 0.000 0.000 scb
+(Vbias) {/Helvetica cf} 2 23 0 1.00 839 570 pinlabel
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/diffamp_test3.ps b/examples/diffamp_test3.ps
new file mode 100644
index 0000000..2bcaf1d
--- /dev/null
+++ b/examples/diffamp_test3.ps
@@ -0,0 +1,535 @@
+%!PS-Adobe-3.0
+%%Title: src/xcircuit-3.1.26/examples/diffamp_test2
+%%Creator: Xcircuit v3.1
+%%CreationDate: Tue Nov 11 12:51:34 2003
+%%Pages: 2
+%%BoundingBox: 178 218 434 574
+%%DocumentNeededResources: font Helvetica font Times-Roman font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.4
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--1/15/03 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.4 3
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {dup type
+ /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse}
+ ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {show} {
+ dup type /arraytype eq {exec} {12 string cvs show} ifelse} ifelse}
+ repeat grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/setdefaults { aload length 2 idiv {currentdict 2 index known
+ {pop pop} {def} ifelse} repeat } bind def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def bop rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/ampl_test {
+% ampl_test is_schematic
+begingate
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica cf} 2 23 0 1.00 -224 192 pinlabel
+(Vinp) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(Voutn) {/Helvetica cf} 2 20 0 1.00 -32 96 pinlabel
+(Voutp) {/Helvetica cf} 2 20 0 1.00 -32 192 pinlabel
+(Vcmref) {/Helvetica cf} 2 25 0 1.00 -160 256 pinlabel
+(Vbias) {/Helvetica cf} 2 29 0 1.00 -160 32 pinlabel
+sce
+1 1.00 -224 96 -192 96 2 polygon
+1 1.00 -224 192 -192 192 2 polygon
+1 1.00 -128 192 -32 192 2 polygon
+1 1.00 -128 96 -32 96 2 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -141 106 label
+(+) {/Symbol cf} 2 5 0 1.00 -141 186 label
+1 1.00 -32 144 -192 224 -192 64 -32 144 4 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -173 186 label
+(+) {/Symbol cf} 2 5 0 1.00 -173 106 label
+1 1.00 -160 80 -160 32 2 polygon
+1 1.00 -160 208 -160 256 2 polygon
+endgate
+} def
+
+/gnd {
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/source {
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/Vsource {
+<</value (5) >> begingate
+1.00 0 0 0 source
+(+) {/Symbol cf} 2 5 0 1.00 0 18 label
+(-) {/Symbol cf} 2 5 0 1.00 0 -18 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(v.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark value (spice:V%i %pv.p %pv.m ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (V) {hS} value {/Times-Roman cf} ctmk 20 0 1.00 48 0 label
+endgate
+} def
+
+/dot {
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/jumper {
+% trivial
+begingate
+1 1.00 0 0 10 -90.00 90.00 xcarc
+1 1.00 0 10 0 16 2 polygon
+1 1.00 0 -10 0 -16 2 polygon
+1.000 0.000 0.000 scb
+(a) {/Times-Roman cf} 2 1 0 1.00 0 16 pinlabel
+(a) {/Times-Roman cf} 2 13 0 1.00 0 -16 pinlabel
+endgate
+} def
+
+/circle {
+% trivial
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 0 0 pinlabel
+endgate
+} def
+
+%%Page: diffamp_test 1
+%%PageOrientation: Landscape
+/pgsave save def bop
+% 1203 848 offsets
+90 rotate 40 -652 translate
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 1027 832 ampl_test
+1.00 0 867 736 gnd
+1.00 0 867 800 Vsource
+1.00 0 1059 800 <</value (2.5) >> Vsource
+1 1.00 1059 864 1059 1088 867 1088 3 polygon
+1.00 0 1059 736 gnd
+1 1.00 803 928 755 928 755 864 851 864 4 polygon
+1 1.00 883 864 1059 864 2 polygon
+1.00 0 1059 864 dot
+1.00 270 867 864 jumper
+1 1.00 803 1024 723 1024 2 polygon
+-1.00 0 723 1024 circle
+1 1.00 995 928 1043 928 2 polygon
+1 1.00 995 1024 1043 1024 2 polygon
+1.00 270 1059 1024 jumper
+1.00 270 1059 928 jumper
+1 1.00 1075 1024 1139 1024 2 polygon
+1 1.00 1075 928 1139 928 2 polygon
+1.00 0 1139 1024 circle
+1.00 0 1139 928 circle
+1.000 0.000 0.000 scb
+(Vinse) {/Helvetica cf} 2 23 0 1.00 707 1024 pinlabel
+(Voutp) {/Helvetica cf} 2 20 0 1.00 1155 1024 pinlabel
+(Voutm) {/Helvetica cf} 2 20 0 1.00 1155 928 pinlabel
+sce
+1411 624 beginpath
+1411 1168 1 polyc
+1379 1168 32 0.00 90.00 arc
+515 1200 1 polyc
+
+515 1168 32 90.00 180.00 arc
+483 624 1 polyc
+515 624 32 180.00 270.00 arc
+1379 592
+1 polyc
+1379 624 32 270.00 360.00 arc
+1 1.00 endpath
+(Differential amplifier: test) {/Helvetica cf} 2 25 0 1.00 947 1232 label
+pgsave restore showpage
+
+/pMOS {
+<</p_yps1 -32 /p_xps1 16 /p_rot1 0 /p_yps 32 /p_xps 16 /p_rot 0 /width
+(3) /length (2) >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS Vdd pmos W=%v"3" L=%v"2") {/Times-Roman cf} 2 4 0 1.00
+-196 -139 infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+endgate
+} def
+
+/Resistor {
+<</p_rot 0 /p_jst 20 /value (1.0) /units (k) >> begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(r.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value (spice:R%i %pr.1 %pr.2 ) {/Times-Roman cf} ctmk 4 0 1.00 -208
+-160 infolabel
+(sim:R %pr.1 %pr.2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (W) {/Symbol cf} units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00
+32 0 label
+endgate
+} def
+
+/nMOS {
+<</p_rot1 0 /p_yps1 -32 /p_xps1 16 /p_rot 0 /p_yps 32 /p_xps 16 /width
+3 /length 2 >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS GND nmos W=%v"3" L=%v"2") {/Times-Roman cf} 2 4 0 1.00
+-244 -139 infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+endgate
+} def
+
+/pmos4 {
+<</p_rot1 0 /p_yps1 -32 /p_xps1 16 /p_rot 0 /p_yps 32 /p_xps 16 /width
+(3) /length (2) >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width (spice:M%i %pD %pG %pS %pB pmos W=) {/Times-Roman cf}
+ctmk 4 0 1.00 -324 -139 infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+sce
+mark width (W=) {/Times-Roman cf} ctmk 20 p_rot 1.00 p_xps p_yps label
+mark length (L=) {/Times-Roman cf} ctmk 20 p_rot1 1.00 p_xps1 p_yps1 label
+1 1.00 -32 0 16 0 2 polygon
+1.000 0.000 0.000 scb
+(B) {/Times-Roman cf} 2 20 0 1.00 16 0 pinlabel
+endgate
+} def
+
+/vdd {
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/halfamp {
+begingate
+1.00 0 128 320 <</p_yps1 32 /p_yps 64 /width (525.6) /length (1.8) >> pMOS
+-1.00 0 -16 320 <</p_xps1 48 /p_yps1 32 /p_xps 48 /p_yps 64 /width (294) /length
+(2.4) >> pMOS
+1 1.00 64 320 -544 320 2 polygon
+1.00 0 128 384 vdd
+1.00 0 -16 384 vdd
+1.00 0 128 -96 <</p_yps -32 /p_yps1 -64 /width 387 /length 1.2 >> nMOS
+1 1.00 128 -32 128 256 2 polygon
+1 1.00 48 0 128 0 2 polygon
+1.00 0 128 0 dot
+1 1.00 -16 -112 -16 -160 2 polygon
+1.00 0 -16 -160 gnd
+1.00 0 128 -160 gnd
+1 1.00 64 -96 -448 -96 2 polygon
+1 1.00 -16 -64 -16 -80 2 polygon
+1.00 0 -16 -96 jumper
+-1.00 270 -224 16 <</p_yps -160 /p_xps1 -80 /p_yps1 -160 /p_rot1 270 /p_rot 270 /p_xps
+-112 /width (73.2) /length (35.2) >> pmos4
+1 1.00 -224 0 -224 -96 2 polygon
+1 1.00 -288 16 -288 -96 2 polygon
+1 1.00 -160 16 -160 -96 2 polygon
+1 1.00 -224 80 -224 160 -16 160 3 polygon
+1.00 0 -16 160 dot
+1.00 0 -160 -96 dot
+1.00 0 -224 -96 dot
+1.00 0 -288 -96 dot
+1.00 0 -448 -96 dot
+1 1.00 -448 32 -448 -192 2 polygon
+-1.00 0 -448 96 <</p_xps1 -160 /p_yps1 48 /p_xps -160 /p_yps 80 /width (294) /length
+(3) >> pmos4
+1 1.00 -384 96 -352 96 2 polygon
+1.00 0 -352 96 circle
+1.00 0 -448 -256 <</p_xps1 32 /p_xps 32 /p_yps1 32 /p_yps 64 /width 21 /length
+3 >> nMOS
+1.00 0 -448 -320 gnd
+1 1.00 -464 96 -560 96 2 polygon
+1 1.00 -448 160 -560 160 2 polygon
+1 1.00 -16 64 -16 256 2 polygon
+-1.00 0 -16 0 <</p_yps1 0 /width (588) /length (1.2) >> pMOS
+endgate
+} def
+
+%%Page: ampl_test 2
+%%PageOrientation: Landscape
+/pgsave save def bop
+% ampl_test is_symbol
+% 2295 762 offsets
+90 rotate -107 -503 translate
+0.6472 inchscale
+2.6000 setlinewidth
+
+1.00 0 2039 1146 <</p_yps1 32 /p_yps 64 /width (336) /length (1.8) >> pMOS
+1.00 270 2423 1290 <</p_jst 17 /p_rot 90 /value (300) >> Resistor
+-1.00 0 3159 410 <</p_yps 0 /width 21 /length 3 >> nMOS
+1.00 0 2935 410 <</p_yps1 16 /p_yps 48 /width 21 /length 3 >> nMOS
+1 1.00 3223 410 3223 474 3159 474 3159 698 4 polygon
+1.00 0 2935 762 <</p_xps1 -144 /p_yps1 -96 /p_xps -144 /p_yps -64 /width (126) /length
+(1.2) >> pmos4
+1 1.00 2935 474 2935 698 2 polygon
+-1.00 0 3159 762 <</p_xps1 -144 /p_yps1 -80 /p_xps -144 /p_yps -48 /width (126) /length
+(1.2) >> pmos4
+1 1.00 2951 762 3143 762 2 polygon
+1 1.00 2935 826 3159 826 2 polygon
+1.00 0 3047 826 dot
+1 1.00 3047 762 3047 1082 2 polygon
+1.00 0 3047 1146 <</p_yps1 0 /width (336) /length (1.8) >> pMOS
+1.00 0 3047 1210 vdd
+1.00 0 2935 346 gnd
+1.00 0 3159 346 gnd
+1 1.00 2935 474 2855 474 2855 410 3 polygon
+1 1.00 2871 410 1991 410 2 polygon
+1.00 0 2039 826 dot
+1 1.00 2039 762 2039 1082 2 polygon
+1 1.00 2871 762 2839 762 2 polygon
+1 1.00 3223 762 3255 762 2 polygon
+1.00 0 3255 762 circle
+1.00 180 2839 762 circle
+1.00 0 2039 1210 vdd
+1 1.00 2983 1146 1975 1146 2 polygon
+1.00 0 2935 474 dot
+1.00 0 2855 410 dot
+1.00 0 3047 762 dot
+1.00 0 2039 762 dot
+1.00 0 3159 474 dot
+1.00 270 2039 986 jumper
+1.00 270 2615 1290 <</p_jst 17 /p_rot 90 /value (300) >> Resistor
+1 1.00 2487 1290 2551 1290 2 polygon
+1 1.00 2519 1290 2519 1258 2 polygon
+1 1.00 2359 1290 2327 1290 2327 1258 3 polygon
+1 1.00 2679 1290 2711 1290 2711 1258 3 polygon
+1.00 0 2519 1290 dot
+1.00 90 2327 1258 circle
+1.00 90 2519 1258 circle
+1.00 90 2711 1258 circle
+1.00 0 2599 666 halfamp
+1 1.00 1415 986 1207 986 2 polygon
+-1.00 0 1143 986 <</p_yps1 0 /width (42) /length (1.8) >> pMOS
+1 1.00 1223 986 1223 922 1143 922 3 polygon
+1.00 0 1143 1050 vdd
+1.00 0 1223 986 dot
+1 1.00 1143 922 1143 634 2 polygon
+-1.00 0 967 1146 <</p_yps1 0 /width (84) /length (1.8) >> pMOS
+1 1.00 1031 1146 1975 1146 2 polygon
+1 1.00 1047 1146 1047 1082 967 1082 967 634 4 polygon
+1.00 0 967 1210 vdd
+1.00 0 1143 506 gnd
+1.00 0 967 506 gnd
+1.000 0.000 0.000 scb
+(Vinn) {/Helvetica cf} 2 20 0 1.00 2263 762 pinlabel
+(Vinp) {/Helvetica cf} 2 23 0 1.00 1815 762 pinlabel
+sce
+1 1.00 2727 858 2775 858 2 polygon
+1.00 0 2775 858 circle
+1.00 0 2727 858 dot
+1.000 0.000 0.000 scb
+(Voutn) {/Helvetica cf} 2 20 0 1.00 2791 858 pinlabel
+sce
+1 1.00 1351 858 1303 858 2 polygon
+-1.00 0 1303 858 circle
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica cf} 2 23 0 1.00 1287 858 pinlabel
+sce
+1.00 0 1351 858 dot
+1.00 0 967 1082 dot
+1.00 0 1047 1146 dot
+1.00 0 1143 922 dot
+1.000 0.000 0.000 scb
+(Voutp) {/Helvetica cf} 2 29 0 1.00 2327 1242 pinlabel
+(Voutn) {/Helvetica cf} 2 29 0 1.00 2711 1242 pinlabel
+(Vcmin) {/Helvetica cf} 2 29 0 1.00 2519 1242 pinlabel
+(Vcmin) {/Helvetica cf} 2 29 0 1.00 2823 762 pinlabel
+(Vcmref) {/Helvetica cf} 2 20 0 1.00 3271 762 pinlabel
+sce
+-1.00 0 1479 666 halfamp
+1.00 0 1143 570 <</p_yps1 16 /p_yps 48 /width 21 /length 16.5 >> nMOS
+1.00 0 967 570 <</p_yps1 32 /p_yps 64 /width 21 /length 16.5 >> nMOS
+1 1.00 1079 570 855 570 2 polygon
+-1.00 0 855 570 circle
+1.000 0.000 0.000 scb
+(Vbias) {/Helvetica cf} 2 23 0 1.00 839 570 pinlabel
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/envelope.ps b/examples/envelope.ps
new file mode 100644
index 0000000..f5e17c5
--- /dev/null
+++ b/examples/envelope.ps
@@ -0,0 +1,343 @@
+%!PS-Adobe-3.0
+%%Title: examples/envelope
+%%Creator: Xcircuit v2.3
+%%CreationDate: Tue May 15 15:08:31 2001
+%%Pages: 1
+%%BoundingBox: -4 -4 616 796
+%%DocumentNeededResources: font Helvetica font Times-Roman font HelveticaISO
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--5/15/01 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.3 1
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale /rotval exch def /just exch def
+ just 16 and 0 gt {0 1 dtransform gsave pagemat setmatrix idtransform
+ exch grestore 1 0 dtransform gsave pagemat setmatrix idtransform
+ exch grestore dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs 0 array def
+ /fscale 1.0 def /kY 0 def
+ gsave dup 1 add copy 0 exch {exch dup type /stringtype eq {true
+ charpath flattenpath} {exec} ifelse } repeat pop pathbbox grestore
+ 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and 0 gt {exch pop
+ neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt {exch pop
+ neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def rotval rotate Kn currentpoint translate
+ /Bline 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+/Helvetica findfont dup length dict begin
+{1 index /FID ne {def} {pop pop} ifelse} forall
+/Encoding ISOLatin1Encoding def currentdict end
+/HelveticaISO exch definefont pop
+
+% XCircuit output starts here.
+
+/rose {
+% -132 -196 267 388 bbox
+begingate
+0.125 0.541 0.125 scb
+60 -176 beginpath
+44 -168 36 -144 28 -128 curveto
+-4 -112 -44 -96 -52 -104 curveto
+-60 -112 -124 -120
+-132 -144 curveto
+-116 -144 -124 -136 -100 -152 curveto
+36 -168 28 -180 24 -176 16 -188 12 -184
+4 -192 0 -188 -8 -196 -12 -192 -20 -196 -24 -192 -32 -196 -36 -192 -48 -192 -48
+-188 -60 -188 -60 -184 -68 -184 -68 -180 -76 -176 -72 -172 -84 -168 -80 -164
+-92 -160 -92 -156 25 polyc
+36 -160 1 polyc
+44 -168 40 -172 60 -180 curveto
+241 1.00 endpath
+60 -144 beginpath
+68 -112 44 -88 124 -80 curveto
+140 -80 148 -200 84 -176 curveto
+60 -144 64 -164 64
+-172 72 -172 4 polyc
+241 1.00 endpath
+28 -16 beginpath
+36 -24 52 -120 60 -160 curveto
+52 -168 56 -184 64 -188 3 polyc
+44 -128 20 -16
+12 -8 curveto
+241 1.00 endpath
+52 16 beginpath
+68 16 76 0 92 0 curveto
+108 0 28 8 44 8 curveto
+241 1.00 endpath
+12 -8 beginpath
+28 -8 44 -40 60 -40 curveto
+44 -32 52 -8 44 8 curveto
+241 1.00 endpath
+-20 -16 beginpath
+-44 -40 -44 -48 -52 -56 curveto
+-52 -40 -44 -32 -44 -16 curveto
+241 1.00 endpath
+0.812 0.000 0.000 scb
+84 88 beginpath
+116 112 92 144 76 168 curveto
+44 176 28 176 20 160 curveto
+20 168 4 176 -4 176 curveto
+-4 180
+-12 184 -16 180 curveto
+-44 200 -60 184 -84 192 curveto
+-92 192 -100 184 -108 160 curveto
+-116 160
+1 polyc
+-116 160 -108 152 -124 152 curveto
+-124 116 -120 88 -108 72 curveto
+-116 80 -116 80
+-124 80 curveto
+-128 56 -136 36 -124 32 curveto
+-92 24 -76 8 -76 0 curveto
+-76 -4 -80 -4 -76 -8 curveto
+-4 -32
+52 8 52 24 curveto
+84 32 92 72 84 88 curveto
+241 1.00 endpath
+sce
+1 1.00 -108 80 -124 72 -124 152 -92 48 spline
+1 1.00 -100 160 -100 168 -68 160 -116 160 spline
+1 1.00 -116 160 -108 152 -124 152 -116 160 spline
+1 1.00 -68 152 -60 176 -20 176 -84 128 spline
+1 1.00 -4 192 -4 168 12 160 -20 176 spline
+1 1.00 20 152 44 136 60 104 12 160 spline
+1 1.00 28 176 44 176 76 168 20 160 spline
+1 1.00 92 144 116 112 84 88 76 168 spline
+1 1.00 60 96 52 80 52 24 76 120 spline
+1 1.00 92 72 84 32 52 24 84 88 spline
+1 1.00 -52 200 -60 184 -84 192 -20 184 spline
+1 1.00 -92 192 -100 184 -108 160 -84 192 spline
+1 1.00 52 8 -4 -32 -76 -8 52 24 spline
+1 1.00 28 64 -12 24 -36 32 52 72 spline
+1 1.00 68 72 4 64 -36 32 52 72 spline
+1 1.00 -20 32 -84 16 -76 -8 -36 32 spline
+1 1.00 -76 8 -92 24 -124 32 -76 0 spline
+1 1.00 -140 24 -132 48 -124 80 -108 32 spline
+1 1.00 -92 32 -76 64 -20 48 -108 32 spline
+1 1.00 -116 80 -116 80 -108 72 -124 80 spline
+1 1.00 20 168 4 176 -4 176 20 160 spline
+1 1.00 36 112 20 112 -4 56 12 136 spline
+1 1.00 28 136 36 112 60 96 12 136 spline
+1 1.00 20 120 4 152 -12 152 20 104 spline
+1 1.00 4 112 -28 160 -36 152 20 104 spline
+1 1.00 -20 152 -68 136 -60 96 -36 152 spline
+1 1.00 -44 88 -36 80 -20 80 -52 104 spline
+1 1.00 -4 72 -44 80 -44 72 12 96 spline
+1 1.00 -92 128 -92 112 -100 112 -52 128 spline
+1 1.00 -84 80 -100 64 -84 48 -100 112 spline
+1 1.00 -76 96 -100 88 -68 80 -60 104 spline
+1 1.00 -76 72 -76 64 -68 56 -84 88 spline
+1 1.00 -44 72 -44 72 -36 56 -68 80 spline
+1 1.00 -20 96 -20 96 -12 80 -28 104 spline
+1 1.00 -36 112 -44 120 -28 128 -36 104 spline
+1 1.00 -12 104 -36 104 -28 104 -12 112 spline
+1 1.00 -12 112 -28 136 -28 112 -12 112 spline
+1 1.00 -52 104 -52 112 -36 120 -52 104 spline
+1 1.00 -44 120 -52 120 -60 104 -36 128 spline
+1 1.00 -36 160 -4 144 12 128 -36 152 spline
+1 1.00 -44 -40 -44 -48 -52 -56 -20 -16 spline
+1 1.00 -44 -32 -52 -40 -52 -56 -44 -16 spline
+1 1.00 28 -8 44 -40 60 -40 12 -8 spline
+1 1.00 52 -8 44 -32 60 -40 44 8 spline
+1 1.00 68 16 76 0 92 0 52 16 spline
+1 1.00 108 0 28 8 44 8 92 0 spline
+1 1.00 20 -16 44 -128 52 -168 12 -8 spline
+1 1.00 36 -24 52 -120 60 -160 28 -16 spline
+1 1.00 68 -112 44 -88 124 -80 60 -144 spline
+1 1.00 140 -80 148 -200 84 -176 124 -80 spline
+1 1.00 100 -120 100 -128 68 -168 116 -104 spline
+1 1.00 44 -168 36 -144 28 -128 60 -176 spline
+1 1.00 -4 -112 -44 -96 -52 -104 28 -128 spline
+1 1.00 -60 -112 -124 -120 -132 -144 -52 -104 spline
+1 1.00 -116 -144 -124 -136 -100 -152 -132 -144 spline
+1 1.00 36 -168 28 -180 24 -176 16 -188 12 -184 4 -192 0 -188 -8 -196 -12 -192
+-20 -196 -24 -192 -32 -196 -36 -192 -48 -192 -48 -188 -60 -188 -60 -184 -68
+-184 -68 -180 -76 -176 -72 -172 -84 -168 -80 -164 -92 -160 -92 -156 -100 -152
+26 polygon
+1 1.00 -80 -128 -12 -136 32 -156 -116 -136 spline
+1 1.00 44 -168 40 -172 60 -180 36 -160 spline
+1 1.00 100 -120 100 -128 68 -168 116 -104 spline
+1 1.00 -80 -128 -12 -136 32 -156 -116 -136 spline
+endgate
+} def
+
+/arrowhead {
+% -12 -32 24 36 bbox
+% trivial
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/arrow {
+% -12 -40 24 80 bbox
+% trivial
+begingate
+1 0.80 0 -40 0 20 2 polygon
+1.00 0 0 40 arrowhead
+endgate
+} def
+
+%%Page: 1 1
+%%PageOrientation: Landscape
+/pgsave save def bop
+% 288 432 offsets
+90 rotate 0 -612 translate
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.000 1.000 0.525 scb
+240 1.00 768 1136 768 1248 1200 1248 1200 1136 4 polygon
+sce
+(Anywhere, USA 12345) {CR} (12345 A Street) {CR} (Return Address)
+{/Times-Roman cf} 6 16 0 0.80 864 1152 label
+0.000 0.000 1.000 scb
+0 1.00 1888 1072 1888 1232 2048 1232 2048 1072 4 polygon
+sce
+(here) {CR} (stamp) {CR} (place) {/Helvetica cf} 6 21 0 1.00 1968 1152 label
+1.000 0.647 0.000 scb
+512 1.00 0 1632 0 0 2112 0 2112 1632 4 polygon
+512 1.00 736 1296 736 336 2112 336 2112 1296 4 polygon
+sce
+(Somewhere Else, USA 01234) {CR} (123 Another Street) {CR} (Recipient Address)
+{/Times-Roman cf} 6 16 0 1.00 1232 704 label
+0.25 0 816 1192 rose
+1.00 315 928 1584 arrow
+(inch paper size) {CR} (\275 \327 11) {hS} (describes 8) {CR}
+(Outer bounding box) {/HelveticaISO cf} 8 31 0 1.00 864 1552 label
+1.00 285 688 944 arrow
+(envelope size.) {CR} (describes 5 \327 7 inch) {CR} (Inner bounding box)
+{/HelveticaISO cf} 6 31 0 1.00 608 912 label
+(output. ) {CR} (not appear in the) {CR} (Bounding boxes do) {/Helvetica cf} 6
+28 0 1.00 256 720 label
+(tray for envelopes.) {CR} (to the printer's paper) {CR}
+(is positioned according) {CR} (Inner bounding box) {/Helvetica cf} 8 28 0 1.00
+256 544 label
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/fourttest.ps b/examples/fourttest.ps
new file mode 100644
index 0000000..51aff8f
--- /dev/null
+++ b/examples/fourttest.ps
@@ -0,0 +1,292 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: fourttest
+%%Creator: Xcircuit v2.3
+%%CreationDate: Wed May 16 14:01:31 2001
+%%Pages: 1
+%%BoundingBox: 68 68 335 303
+%%DocumentNeededResources: font Helvetica font Times-Roman
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.3 1
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale /rotval exch def /just exch def
+ just 16 and 0 gt {0 1 dtransform gsave pagemat setmatrix idtransform
+ exch grestore 1 0 dtransform gsave pagemat setmatrix idtransform
+ exch grestore dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs 0 array def
+ /fscale 1.0 def /kY 0 def
+ gsave dup 1 add copy 0 exch {exch dup type /stringtype eq {true
+ charpath flattenpath} {exec} ifelse } repeat pop pathbbox grestore
+ 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and 0 gt {exch pop
+ neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt {exch pop
+ neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def rotval rotate Kn currentpoint translate
+ /Bline 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/nMOS4 {
+% -64 -64 234 128 bbox
+(3) (2) (nmos) 3 beginparm
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+sce
+mark v2 ( L=) v1 ( W=) v3 (spice:M%i %pD %pG %pS %pB ) {/Times-Roman cf} ctmk
+4 0 1.00 -244 -139 infolabel
+sce
+(sim:n %pG %pD %pS) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+mark v2 (/) v1 (W/L=) {/Times-Roman cf} ctmk 20 0 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+/dot {
+% -10 -10 20 20 bbox
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/nmos {
+% -64 -64 64 128 bbox
+begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+sce
+(spice:M%i %pD %pG %pS GND nmos) {/Times-Roman cf} 2 4 0 1.00 -244 -139
+infolabel
+sce
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/pMOS4 {
+% -64 -64 256 128 bbox
+(3) (2) (pmos) 3 beginparm
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+sce
+mark v2 ( L=) v1 ( W=) v3 (spice:M%i %pD %pG %pS %pB ) {/Times-Roman cf} ctmk
+4 0 1.00 -196 -139 infolabel
+sce
+(sim:p %pG %pD %pS) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+mark v2 (/) v1 (W/L=) {/Times-Roman cf} ctmk 20 0 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+/vdd {
+% -32 0 64 66 bbox
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 672 380 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 384 508 nMOS4
+1.00 180 608 508 nMOS4
+1 1.00 416 508 576 508 2 polygon
+1 1.00 416 508 416 444 2 polygon
+1 1.00 384 444 608 444 2 polygon
+1.00 0 416 508 dot
+1.00 0 416 444 dot
+1.00 0 496 444 dot
+1 1.00 496 444 496 380 2 polygon
+1.00 0 496 316 nmos
+1.00 0 496 252 gnd
+1 1.00 320 508 256 508 2 polygon
+1 1.00 672 508 736 508 2 polygon
+1 1.00 432 316 368 316 2 polygon
+1.000 0.000 0.000 scb
+(Bias) {/Helvetica cf} 2 23 0 1.00 368 316 pinlabel
+(V1) {/Helvetica cf} 2 23 0 1.00 256 508 pinlabel
+(V2) {/Helvetica cf} 2 20 0 1.00 736 508 pinlabel
+sce
+1.00 -181 608 636 [(12) ] pMOS4
+1.00 180 384 636 [(12) ] pMOS4
+1 1.00 352 636 352 700 2 polygon
+1 1.00 640 636 640 700 2 polygon
+1 1.00 352 700 640 700 2 polygon
+1.00 0 608 700 dot
+1.00 0 384 700 dot
+1.00 0 496 700 dot
+1 1.00 496 700 496 732 2 polygon
+1.00 0 496 732 vdd
+1 1.00 448 636 544 636 2 polygon
+1 1.00 496 636 496 572 608 572 3 polygon
+1 1.00 608 572 800 572 2 polygon
+1.000 0.000 0.000 scb
+(Out) {/Helvetica cf} 2 20 0 1.00 800 572 pinlabel
+sce
+1.00 0 496 636 dot
+1.00 0 608 572 dot
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/logic.sim b/examples/logic.sim
new file mode 100644
index 0000000..495377d
--- /dev/null
+++ b/examples/logic.sim
@@ -0,0 +1,11 @@
+| sim circuit "logic" from XCircuit v3.30
+p Pin.1 Vdd int6
+n Pin.1 GND int6
+p int6 Vdd Pin.4
+n int6 nand_1/ext13 Pin.4
+n Pin.2 GND nand_1/ext13
+p Pin.2 Vdd Pin.4
+p Pin.2 Vdd Pin.5
+n Pin.2 nand_2/ext13 Pin.5
+n Pin.3 GND nand_2/ext13
+p Pin.3 Vdd Pin.5
diff --git a/examples/logic8.ps b/examples/logic8.ps
new file mode 100644
index 0000000..cab32ed
--- /dev/null
+++ b/examples/logic8.ps
@@ -0,0 +1,387 @@
+%!PS-Adobe-3.0
+%%Title: examples/logic8
+%%Creator: Xcircuit v3.1
+%%CreationDate: Tue Apr 29 14:39:02 2003
+%%Pages: 3
+%%BoundingBox: 110 290 502 502
+%%DocumentNeededResources: font Times-Roman
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.4
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--1/15/03 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.4 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {exec}
+ ifelse } repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {show}{exec} ifelse}
+ repeat grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def bop rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/nand {
+% nand is_schematic
+begingate
+1 1.00 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 0 0 48 -90.00 90.00 xcarc
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(In.1) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(In.2) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+endgate
+} def
+
+/invert {
+% invert is_schematic
+begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 48 0 8 0.00 360.00 xcarc
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 56 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(In) {/Times-Roman cf} 2 7 0 1.00 -48 0 pinlabel
+endgate
+} def
+
+/dot {
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/circle {
+% trivial
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 0 0 pinlabel
+endgate
+} def
+
+%%Page: logic 11
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 912 848 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 944 928 nand
+1.00 0 944 1088 nand
+1.00 0 656 1120 invert
+1 1.00 720 1120 880 1120 2 polygon
+1 1.00 608 1120 560 1120 2 polygon
+1 1.00 880 1056 784 1056 784 960 880 960 4 polygon
+1 1.00 880 896 560 896 2 polygon
+1 1.00 784 960 560 960 2 polygon
+1.00 0 784 960 dot
+1 1.00 1008 1088 1136 1088 2 polygon
+1 1.00 1008 928 1136 928 2 polygon
+-1.00 0 560 1120 circle
+1.00 0 1136 1088 circle
+1.00 0 1136 928 circle
+-1.00 0 560 896 circle
+-1.00 0 560 960 circle
+(Logic Circuit) {/Times-Roman cf} 2 9 0 1.00 816 1280 label
+0 1.00 304 784 304 1328 1328 1328 1328 784 4 polygon
+1.000 0.000 0.000 scb
+(Pin.1) {/Times-Roman cf} 2 7 0 1.00 544 1120 pinlabel
+(Pin.2) {/Times-Roman cf} 2 7 0 1.00 544 960 pinlabel
+(Pin.3) {/Times-Roman cf} 2 7 0 1.00 544 896 pinlabel
+(Pin.5) {/Times-Roman cf} 2 4 0 1.00 1152 928 pinlabel
+(Pin.4) {/Times-Roman cf} 2 4 0 1.00 1152 1088 pinlabel
+pgsave restore showpage
+
+/gnd {
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/pmos {
+begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS Vdd pmos) {/Times-Roman cf} 2 4 0 1.00 -196 -139
+infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+endgate
+} def
+
+/nmos {
+begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS GND nmos) {/Times-Roman cf} 2 4 0 1.00 -244 -139
+infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/jumper {
+% trivial
+begingate
+1 1.00 0 0 10 -90.00 90.00 xcarc
+1 1.00 0 10 0 16 2 polygon
+1 1.00 0 -10 0 -16 2 polygon
+1.000 0.000 0.000 scb
+(a) {/Times-Roman cf} 2 1 0 1.00 0 16 pinlabel
+(a) {/Times-Roman cf} 2 13 0 1.00 0 -16 pinlabel
+endgate
+} def
+
+/vdd {
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+%%Page: nand 11
+%%PageOrientation: Portrait
+/pgsave save def bop
+% nand is_symbol
+% 808 1024 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 808 928 gnd
+-1.00 0 872 1248 pmos
+-1.00 0 808 992 nmos
+1.00 0 808 1120 nmos
+1.00 0 744 1248 pmos
+1 1.00 744 1184 872 1184 2 polygon
+1 1.00 744 1312 872 1312 2 polygon
+1 1.00 968 1168 968 992 872 992 3 polygon
+1 1.00 872 1184 1016 1184 2 polygon
+1 1.00 744 1120 648 1120 648 1248 680 1248 4 polygon
+1 1.00 616 1120 648 1120 2 polygon
+1 1.00 936 1248 1016 1248 2 polygon
+1.00 0 648 1120 dot
+1.00 0 808 1184 dot
+1.00 0 872 1184 dot
+1.00 0 968 1248 dot
+1.00 0 808 1312 dot
+-1.00 0 616 1120 circle
+1.00 0 1016 1248 circle
+1.00 0 1016 1184 circle
+1 1.00 968 1200 968 1248 2 polygon
+1.00 0 968 1184 jumper
+(2-Input Nand gate) {/Times-Roman cf} 2 9 0 1.00 808 1440 label
+1.00 0 840 752 nand
+1 1.00 904 752 936 752 2 polygon
+1 1.00 776 784 744 784 2 polygon
+1 1.00 776 720 744 720 2 polygon
+-1.00 0 744 720 circle
+1.00 0 936 752 circle
+-1.00 0 744 784 circle
+( Out) {/Times-Roman cf} 2 4 0 1.00 952 752 label
+(In.1 ) {/Times-Roman cf} 2 7 0 1.00 728 784 label
+(In.2 ) {/Times-Roman cf} 2 7 0 1.00 728 720 label
+(\(symbol\)) {/Times-Roman cf} 2 5 0 1.00 824 656 label
+1 1.00 312 832 1320 832 2 polygon
+0 1.00 312 608 312 1504 1320 1504 1320 608 4 polygon
+1.000 0.000 0.000 scb
+(In.1) {/Times-Roman cf} 2 7 0 1.00 600 1120 pinlabel
+(Out) {/Times-Roman cf} 2 4 0 1.00 1032 1184 pinlabel
+(In.2) {/Times-Roman cf} 2 4 0 1.00 1032 1248 pinlabel
+sce
+1.00 0 808 1312 vdd
+pgsave restore showpage
+
+%%Page: invert 11
+%%PageOrientation: Portrait
+/pgsave save def bop
+% invert is_symbol
+% 832 1176 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 832 1016 gnd
+1.00 0 832 1080 nmos
+1.00 0 832 1208 pmos
+1 1.00 768 1208 768 1208 736 1208 736 1080 768 1080 5 polygon
+1 1.00 832 1144 928 1144 2 polygon
+1 1.00 736 1144 672 1144 2 polygon
+1.00 0 736 1144 dot
+1.00 0 832 1144 dot
+-1.00 0 672 1144 circle
+1.00 0 928 1144 circle
+(Inverter) {/Times-Roman cf} 2 9 0 1.00 832 1400 label
+1 1.00 864 792 896 792 2 polygon
+1 1.00 752 792 720 792 2 polygon
+1.00 0 896 792 circle
+-1.00 0 720 792 circle
+( Out) {/Times-Roman cf} 2 4 0 1.00 912 792 label
+(In ) {/Times-Roman cf} 2 7 0 1.00 704 792 label
+(\(symbol\)) {/Times-Roman cf} 2 5 0 1.00 816 696 label
+1 1.00 512 888 1120 888 2 polygon
+0 1.00 512 648 512 1464 1120 1464 1120 648 4 polygon
+1.00 0 800 792 invert
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 2 4 0 1.00 944 1144 pinlabel
+(In) {/Times-Roman cf} 2 7 0 1.00 656 1144 pinlabel
+sce
+1.00 0 832 1272 vdd
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/panzoom.py b/examples/panzoom.py
new file mode 100644
index 0000000..20587a2
--- /dev/null
+++ b/examples/panzoom.py
@@ -0,0 +1,19 @@
+# The followin Python script replaces the zoom in/out operators
+# with a pan function followed by a zoom. The range of the zoom
+# can be adjusted by this method, too.
+
+def panzoomin():
+ T=getcursor()
+ pan(T)
+ zoom(1.5)
+
+def panzoomout():
+ T=getcursor()
+ pan(T)
+ zoom(0.66667)
+
+unbind("Z", "Zoom In")
+unbind("z", "Zoom Out")
+
+bind("Z", "panzoomin")
+bind("z", "panzoomout")
diff --git a/examples/prelude.ps b/examples/prelude.ps
new file mode 100644
index 0000000..235156d
--- /dev/null
+++ b/examples/prelude.ps
@@ -0,0 +1,936 @@
+%!PS-Adobe-3.0
+%%Title: prelude
+%%Creator: Xcircuit v1.6
+%%CreationDate: Thu Aug 28 13:10:40 1997
+%%Pages: 1
+%%BoundingBox: 32 35 578 756
+%%DocumentNeededResources: font Times-BoldItalic font Times-Bold
+%%+ font Times-Roman
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 1.6
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--8/8/97 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 1.6 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def
+ findfont fscale scalefont setfont } def
+/Ss { gsave 0.67 dup scale gsave mty neg rmoveto
+ glevel 1 add /glevel exch def } def
+/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto
+ glevel 1 add /glevel exch def } def
+/ns { currentpoint transform % preserve x position!
+ glevel {grestore} repeat /glevel 0 def
+ itransform pop currentpoint pop sub 0 rmoveto } def
+/ul { showflag 1 eq { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { showflag 1 eq { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/bs { gsave true charpath flattenpath pathbbox pop exch pop sub
+ grestore 0 rmoveto } def
+/textx { dup 2 mul 1 add copy 0 exch
+ { exch exec exch stringwidth pop add } repeat neg ns } def
+/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch
+ pop exch sub exch pop neg grestore } def
+/texty { gsave 2 copy pop exec mty } def
+/tcenter { textx grestore 0.5 mul 0 rmoveto } def
+/tright { textx grestore 0 rmoveto } def
+/tmiddle { texty 0.5 mul rmoveto } def
+/ttop { texty rmoveto } def
+/tshow { { exec show } repeat ns } def
+
+/label { gsave translate 0 0 moveto rotate /just exch def
+ /glevel 0 def /showflag 0 def
+ just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} if
+ just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} if
+ /showflag 1 def tshow grestore } def
+
+/begingate { gsave translate 0 0 moveto dup 0 lt {neg 1 sub -1 1 scale} if
+ rotate dup scale } bind def
+/endgate { grestore } bind def
+
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave tmpa pathbbox clip transform neg exch neg 4 2 roll transform
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ [1 0 0 1 0 0] setmatrix { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt { newpath } { stroke } ifelse grestore } def
+/scb { gsave setrgbcolor } bind def /sce { grestore } bind def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def
+/inchscale {0.375 mul dup scale} def
+/cmscale {0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/hd {
+% -31 -15 38 30 bbox
+begingate
+6 9 beginpath
+-2 25 -38 9 -30 -9 curveto
+-22 -25 14 -9 6 9 curveto
+241 1.00 endpath
+endgate
+} def
+
+/qn {
+% -38 1 38 127 bbox
+begingate
+1.00 0 -7 16 hd
+1 1.00 0 18 0 128 2 polygon
+endgate
+} def
+
+/qnd {
+% -40 -96 38 127 bbox
+begingate
+1.00 180 -40 32 qn
+endgate
+} def
+
+/wn {
+% -44 0 48 32 bbox
+begingate
+-28 32 beginpath
+-48 32 -28 0 -12 0 curveto
+-52 0 -52 32 -28 32 curveto
+12 32 12 0 -12 0 curveto
+8 0 -12 32 -28 32 curveto
+241 1.00 endpath
+endgate
+} def
+
+/lines {
+% 0 -64 3552 128 bbox
+begingate
+1 1.00 0 -32 3552 -32 2 polygon
+1 1.00 0 64 3552 64 2 polygon
+1 1.00 0 0 3552 0 2 polygon
+1 1.00 0 32 3552 32 2 polygon
+1 1.00 0 -64 3552 -64 2 polygon
+endgate
+} def
+
+/br1 {
+% -33 -160 34 256 bbox
+begingate
+0 96 beginpath
+-76 52 60 -100 -32 -160 curveto
+44 -116 -92 36 0 96 curveto
+241 1.00 endpath
+endgate
+} def
+
+/bar {
+% 0 -256 0 512 bbox
+begingate
+1 1.50 0 256 0 -256 2 polygon
+endgate
+} def
+
+/tclef {
+% -44 -42 83 210 bbox
+begingate
+1 1.00 -2 -26 16 180.00 360.00 xcarc
+241 1.00 -8 -26 10 0.00 360.00 xcarc
+1 1.00 14 -26 -4 112 2 polygon
+-4 12 beginpath
+-20 20 -16 50 12 50 curveto
+42 50 36 0 4 0 curveto
+48 0 52 64 12 64 curveto
+-20 64 -28 20 -4 12 curveto
+241 1.00 endpath
+4 0 beginpath
+-24 0 -32 16 -32 32 curveto
+-32 80 30 84 30 140 curveto
+30 170 -10 140 -4 112 curveto
+-10 156 12 164 22 168 curveto
+28 158 30 152 30 140 curveto
+30 108 -44 92 -44 40 curveto
+-44 8 -16 0 4 0 curveto
+241 1.00 endpath
+endgate
+} def
+
+/bclef {
+% -28 -68 79 100 bbox
+begingate
+1 1.00 0 5 27 90.00 192.00 xcarc
+241 1.00 48 16 3 0.00 360.00 xcarc
+241 1.00 48 -15 3 0.00 360.00 xcarc
+241 1.00 -17 3 10 0.00 360.00 xcarc
+36 -4 beginpath
+36 -44 8 -60 -28 -68 curveto
+40 -52 32 32 0 32 curveto
+28 32 36 12 36 -4 curveto
+241 1.00 endpath
+endgate
+} def
+
+/flt {
+% -8 -2 23 73 bbox
+begingate
+1 1.00 -8 71 -8 -1 2 polygon
+-8 -2 beginpath
+32 22 12 46 -8 30 curveto
+2 40 20 22 -8 -2 curveto
+241 1.00 endpath
+endgate
+} def
+
+/keyBf {
+% -42 -51 56 121 bbox
+begingate
+1.00 0 -18 -17 flt
+1.00 0 14 31 flt
+endgate
+} def
+
+/staff {
+% 15 -275 3601 571 bbox
+begingate
+1.00 0 64 -192 lines
+1.00 0 64 192 lines
+1.00 -181 48 -160 br1
+1.00 0 48 160 br1
+1.00 0 64 0 bar
+1.00 0 3616 0 bar
+1.00 0 144 128 tclef
+1.00 0 128 -160 bclef
+1.00 0 240 -224 keyBf
+1.00 0 240 192 keyBf
+endgate
+} def
+
+/hhd {
+% -39 -1 38 34 bbox
+begingate
+6 28 beginpath
+16 12 -20 -12 -30 4 curveto
+-24 -6 12 20 6 28 curveto
+-4 44 -40 20 -30 4 curveto
+-36 12 0 38 6 28 curveto
+241 1.00 endpath
+endgate
+} def
+
+/hn {
+% -39 -1 39 129 bbox
+begingate
+1 1.00 0 23 0 128 2 polygon
+1.00 0 -8 0 hhd
+endgate
+} def
+
+/flg {
+% 0 -52 40 128 bbox
+begingate
+0 76 beginpath
+0 32 68 8 28 -52 curveto
+64 0 0 32 0 32 curveto
+240 1.00 endpath
+endgate
+} def
+
+/en {
+% -38 1 78 153 bbox
+begingate
+1.00 0 0 0 qn
+1.00 0 0 78 flg
+endgate
+} def
+
+/shp {
+% -16 -28 32 88 bbox
+begingate
+240 1.00 -16 24 16 32 16 40 -16 32 4 polygon
+240 1.00 -16 -8 16 0 16 8 -16 0 4 polygon
+1 1.00 -8 56 -8 -28 2 polygon
+1 1.00 8 -24 8 60 2 polygon
+endgate
+} def
+
+/lnt {
+% -4 -14 64 28 bbox
+begingate
+1 1.75 -4 0 60 0 2 polygon
+endgate
+} def
+
+/hnt {
+% -52 -1 64 129 bbox
+begingate
+1.00 0 -48 16 lnt
+1.00 0 0 0 hn
+endgate
+} def
+
+/hr {
+% -24 0 44 16 bbox
+begingate
+240 1.00 -24 0 -24 16 20 16 20 0 4 polygon
+endgate
+} def
+
+/qstem1 {
+% -52 -96 64 127 bbox
+begingate
+1.00 180 -40 32 qn
+1.00 0 -48 16 lnt
+endgate
+} def
+
+/er {
+% -30 -8 27 50 bbox
+begingate
+1 1.30 -3 39 -20 -8 2 polygon
+241 1.00 -24 36 6 0.00 360.00 xcarc
+1 1.00 -18 44 16 237.00 337.00 xcarc
+endgate
+} def
+
+/qstem2 {
+% -55 -96 64 127 bbox
+begingate
+1.00 180 -40 32 qn
+1.00 0 -52 0 lnt
+endgate
+} def
+
+/qr {
+% -15 -50 29 100 bbox
+begingate
+1 1.00 3 41 -1 49 2 polygon
+1 1.00 14 -34 -14 6 2 polygon
+8 -26 beginpath
+-2 -12 -30 -22 -6 -50 curveto
+-20 -36 -4 -24 14 -34 curveto
+241 1.00 endpath
+-14 6 beginpath
+-10 30 6 34 -2 50 curveto
+10 26 1 polyc
+-2 14 -6 -6 0 -14 curveto
+241 1.00 endpath
+endgate
+} def
+
+/dot {
+% -10 -10 20 20 bbox
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+endgate
+} def
+
+/en2 {
+% -40 -130 40 161 bbox
+begingate
+1.00 180 -40 32 qn
+1.00 -181 -40 -54 flg
+endgate
+} def
+
+/nat {
+% -14 -32 22 94 bbox
+begingate
+240 1.00 -14 -8 8 0 8 8 -14 0 4 polygon
+240 1.00 -14 24 8 32 8 40 -14 32 4 polygon
+1 1.00 -14 62 -14 -8 2 polygon
+1 1.00 8 -32 8 40 2 polygon
+endgate
+} def
+
+/four {
+% -24 -32 48 64 bbox
+begingate
+1 1.00 -24 -10 24 -10 2 polygon
+12 -24 beginpath
+20 -24 8 180.00 270.00 arc
+-10 -32 1 polyc
+-10 -24 8 -90.00 0.00 arc
+12 -24 12 18 -2 2 3 polyc
+241 1.00 endpath
+-24 -10 beginpath
+-16 0 -6 20 -6 28 curveto
+-22 -10 14 32 2 polyc
+241 1.00 endpath
+endgate
+} def
+
+/wnt {
+% -53 0 64 32 bbox
+begingate
+1.00 0 -49 16 lnt
+1.00 0 0 0 wn
+endgate
+} def
+
+/hnd {
+% -40 -96 39 129 bbox
+begingate
+1.00 180 -40 32 hn
+endgate
+} def
+
+/ent {
+% -52 -130 64 161 bbox
+begingate
+1.00 0 0 0 en2
+1.00 0 -48 16 lnt
+endgate
+} def
+
+/qstem3 {
+% -52 1 64 127 bbox
+begingate
+1.00 0 0 0 qn
+1.00 0 -48 16 lnt
+endgate
+} def
+
+/qstem4 {
+% -49 1 64 127 bbox
+begingate
+1.00 0 0 0 qn
+1.00 0 -45 32 lnt
+endgate
+} def
+
+%%Page: 1 1
+/pgsave save def bop
+% -7 154 offsets
+0.4000 inchscale
+2.6000 setlinewidth
+
+1 1.00 3753 4858 3753 4890 2 polygon
+1 1.00 3641 4842 3641 4874 2 polygon
+1 1.00 3417 4858 3417 4794 2 polygon
+1 1.00 1049 3594 1049 3610 2 polygon
+1 1.00 1217 3498 1217 3458 2 polygon
+1 1.00 2041 4730 2041 4794 2 polygon
+1 1.00 2169 4778 2169 4810 2 polygon
+1 1.00 2665 3978 2665 4074 2 polygon
+1 1.00 2377 3978 2377 4026 2 polygon
+1 1.00 1881 3962 1881 4058 2 polygon
+1 1.00 1593 3962 1593 4010 2 polygon
+1 1.00 3481 3946 3481 4042 2 polygon
+1 1.00 3193 3946 3193 3994 2 polygon
+1 1.00 1745 3162 1745 3258 2 polygon
+1 1.00 1481 3162 1481 3210 2 polygon
+1 1.00 2641 3178 2641 3274 2 polygon
+1 1.00 2377 3178 2377 3226 2 polygon
+1 1.00 953 3242 953 3290 2 polygon
+1 1.00 689 3242 689 3258 2 polygon
+1 1.00 769 3194 769 3274 2 polygon
+1 1.00 1929 4394 1929 4362 2 polygon
+1 1.00 3457 3226 3457 3306 2 polygon
+1 1.00 3633 3194 3633 3298 2 polygon
+1 1.00 3721 3290 3721 3306 2 polygon
+1 1.00 569 2426 569 2498 2 polygon
+1 1.00 753 2458 745 2466 2 polygon
+1 1.00 841 2426 841 2466 2 polygon
+1 1.00 3369 3274 3369 3258 2 polygon
+1 1.00 3281 3194 3281 3250 2 polygon
+1 1.00 3121 1966 3121 1942 2 polygon
+1 1.00 3033 1954 3033 1978 2 polygon
+1 1.00 1945 1146 1945 1186 2 polygon
+1 1.00 1393 1162 1393 1130 2 polygon
+1 1.00 1169 1146 1169 1130 2 polygon
+1 1.00 617 938 617 906 2 polygon
+1 1.00 729 938 729 946 2 polygon
+1 1.00 953 954 953 986 2 polygon
+1 1.00 1081 906 1081 914 2 polygon
+1 1.00 1305 922 1305 954 2 polygon
+1 1.00 1193 938 1193 954 2 polygon
+1 1.00 1577 1194 1577 1218 2 polygon
+1 1.00 3017 505 3017 553 2 polygon
+1 1.00 985 2746 985 2722 2 polygon
+1 1.00 1161 2746 1161 2722 2 polygon
+1 1.00 1425 906 1425 962 2 polygon
+1 1.00 1081 914 1081 970 2 polygon
+496 1.00 1705 4730 1705 4746 1801 4730 1801 4714 4 polygon
+496 1.00 1401 4794 1401 4810 1497 4794 1497 4778 4 polygon
+496 1.00 1401 4762 1401 4778 1497 4762 1497 4746 4 polygon
+496 1.00 1097 4826 1097 4842 1193 4826 1193 4810 4 polygon
+496 1.00 1097 4794 1097 4810 1193 4794 1193 4778 4 polygon
+496 1.00 1705 4762 1705 4778 1801 4762 1801 4746 4 polygon
+496 1.00 2617 4794 2617 4810 2729 4826 2729 4810 4 polygon
+496 1.00 809 4842 809 4858 905 4842 905 4826 4 polygon
+496 1.00 3001 4842 3001 4858 3097 4842 3097 4826 4 polygon
+496 1.00 3001 4874 3001 4890 3097 4874 3097 4858 4 polygon
+496 1.00 3193 4874 3193 4890 3305 4842 3305 4826 4 polygon
+496 1.00 3417 4842 3417 4858 3753 4890 3753 4874 4 polygon
+240 1.00 617 4058 617 4074 921 4026 921 4010 4 polygon
+496 1.00 809 4874 809 4890 905 4874 905 4858 4 polygon
+496 1.00 617 3642 617 3658 729 3690 729 3674 4 polygon
+496 1.00 1217 3458 1217 3474 1313 3514 1313 3498 4 polygon
+496 1.00 1929 4762 1929 4778 2297 4842 2297 4826 4 polygon
+496 1.00 1049 3602 1049 3618 1145 3658 1145 3642 4 polygon
+496 1.00 1921 3474 1921 3490 2113 3530 2113 3514 4 polygon
+497 1.00 2377 4010 2377 4026 2665 4074 2665 4058 4 polygon
+496 1.00 2705 3490 2705 3506 2897 3546 2897 3530 4 polygon
+497 1.00 1593 3994 1593 4010 1881 4058 1881 4042 4 polygon
+496 1.00 3193 3978 3193 3994 3481 4042 3481 4026 4 polygon
+496 1.00 3521 3458 3521 3474 3713 3514 3713 3498 4 polygon
+496 1.00 609 1290 609 1306 953 1370 953 1354 4 polygon
+496 1.00 689 3258 689 3274 953 3290 953 3274 4 polygon
+496 1.00 1481 3194 1481 3210 1745 3258 1745 3242 4 polygon
+496 1.00 1865 2674 1865 2690 2041 2730 2041 2714 4 polygon
+496 1.00 2697 2722 2697 2738 2873 2778 2873 2762 4 polygon
+496 1.00 2377 3210 2377 3226 2641 3274 2641 3258 4 polygon
+496 1.00 3457 3290 3457 3306 3721 3306 3721 3290 4 polygon
+496 1.00 569 2482 569 2498 841 2466 841 2450 4 polygon
+496 1.00 953 2434 953 2450 1209 2490 1209 2474 4 polygon
+496 1.00 3193 3226 3193 3242 3369 3274 3369 3258 4 polygon
+496 1.00 2705 2442 2705 2458 2897 2490 2897 2474 4 polygon
+496 1.00 2569 1938 2569 1954 2865 2010 2865 1994 4 polygon
+496 1.00 2201 2090 2201 2106 2505 2154 2505 2138 4 polygon
+521 1970 beginpath
+505 1930 465 1914 425 1930 curveto
+465 1906 505 1922 521 1970 curveto
+241 1.00 endpath
+496 1.00 1345 2042 1345 2058 1649 2106 1649 2090 4 polygon
+496 1.00 1721 1890 1721 1906 2017 1962 2017 1946 4 polygon
+496 1.00 3033 1954 3033 1970 3329 1922 3329 1906 4 polygon
+496 1.00 3465 2122 3465 2138 3785 2090 3785 2074 4 polygon
+496 1.00 3017 538 3017 554 3353 506 3353 490 4 polygon
+1.00 0 1081 1226 qnd
+1 1.00 1081 538 1081 546 2 polygon
+496 1.00 985 2722 985 2738 1161 2738 1161 2722 4 polygon
+496 1.00 1577 1194 1577 1210 1945 1162 1945 1146 4 polygon
+496 1.00 617 930 617 946 953 994 953 978 4 polygon
+1 1.00 2793 536 2793 568 2 polygon
+496 1.00 1849 2394 1849 2410 2057 2450 2057 2434 4 polygon
+496 1.00 2113 1354 2113 1370 2449 1322 2449 1306 4 polygon
+496 1.00 1081 954 1081 970 1425 962 1425 946 4 polygon
+1.00 0 3545 362 wn
+1.00 0 217 3738 staff
+1.00 0 3081 2762 wn
+1.00 0 569 1994 hn
+1.00 0 665 4714 qn
+1.00 0 2873 4714 en
+1.00 0 3345 4634 shp
+1.00 0 1401 4682 qn
+1.00 0 1497 4666 qn
+1.00 0 1273 4714 en
+1.00 0 1577 4682 en
+1.00 0 1129 4698 shp
+1.00 0 1097 4714 qn
+1.00 0 1193 4698 qn
+1.00 0 1737 4634 shp
+1.00 0 1705 4650 qn
+1.00 0 1801 4634 qn
+1.00 0 2425 4698 qn
+1.00 0 2617 4682 qn
+1.00 0 2729 4698 qn
+1.00 0 2425 4394 hnt
+1.00 0 2409 4314 hr
+1.00 0 1929 4378 hn
+1.00 0 1929 4234 hn
+1.00 0 2777 4506 bar
+1.00 180 2833 4410 hn
+1.00 180 2833 4682 hn
+1.00 0 665 4234 wn
+1.00 180 2833 4714 hn
+1.00 180 3377 4666 hn
+1.00 0 809 4762 qn
+1.00 0 905 4746 qn
+1.00 0 985 4762 en
+1.00 0 841 4746 shp
+1.00 0 3001 4762 qn
+1.00 0 3097 4746 qn
+1.00 0 3033 4746 shp
+1.00 0 3193 4762 qn
+1.00 0 3305 4714 qn
+1.00 0 3417 4666 qn
+1.00 0 3529 4730 qn
+1.00 0 3641 4714 qn
+1.00 0 3753 4730 qn
+1.00 180 3601 4362 qn
+1.00 0 3417 4394 qstem1
+1.00 0 3569 4330 shp
+1.00 0 617 3946 qn
+1.00 0 729 3930 qn
+1.00 0 825 3914 qn
+1.00 0 921 3898 qn
+1.00 0 1049 3930 qn
+1.00 0 1257 3914 qn
+1.00 0 1849 4506 bar
+1.00 0 1417 3738 bar
+1.00 180 577 3930 hn
+1.00 180 577 3898 hn
+1.00 180 1009 3930 qn
+1.00 180 1009 3898 qn
+1.00 180 1217 3914 qn
+1.00 180 1217 3866 qn
+1.00 0 665 4874 er
+1.00 0 617 3530 qn
+1.00 0 729 3562 qn
+1.00 0 825 3642 qstem2
+1.00 0 545 3866 shp
+1.00 0 1049 3466 qn
+1.00 0 1145 3530 qn
+1.00 180 1217 3610 qn
+1.00 180 1313 3626 qn
+1.00 0 1929 4650 qn
+1.00 0 2169 4650 qn
+1.00 0 2297 4714 qn
+1.00 0 2041 4602 qn
+1.00 0 1401 3738 bar
+1.00 0 2709 1674 qr
+1.00 0 2201 3738 bar
+1.00 0 2265 3914 er
+1.00 0 2377 3850 qn
+1.00 0 2569 3930 qn
+1.00 0 2665 3850 qn
+1.00 0 2473 3898 qn
+1.00 180 2705 3626 qn
+1.00 180 2801 3642 qn
+1.00 0 2505 3546 hr
+1.00 0 2753 3930 qr
+1.00 0 2785 3914 dot
+1.00 0 1513 3914 er
+1.00 0 1505 3610 en2
+1.00 0 1593 3834 qn
+1.00 0 1785 3914 qn
+1.00 0 1881 3834 qn
+1.00 0 1689 3882 qn
+1.00 180 1921 3610 qn
+1.00 180 2017 3626 qn
+1.00 180 2113 3642 qn
+1.00 0 1721 3546 hr
+1.00 0 1977 3930 qr
+1.00 0 2009 3914 dot
+1.00 0 3001 3738 bar
+1.00 0 3081 3914 er
+1.00 0 3081 3594 en2
+1.00 0 3385 3898 qn
+1.00 0 3289 3866 qn
+1.00 180 3521 3594 qn
+1.00 180 3617 3610 qn
+1.00 180 3713 3626 qn
+1.00 0 3329 3546 hr
+1.00 0 3593 3930 qr
+1.00 0 3625 3914 dot
+1.00 0 1353 3146 er
+1.00 0 1353 2810 en2
+1.00 0 1657 3114 qn
+1.00 0 1569 3082 qn
+1.00 180 1865 2810 qn
+1.00 180 1953 2826 qn
+1.00 180 2041 2842 qn
+1.00 0 1585 2778 hr
+1.00 0 1865 3162 qr
+1.00 0 1897 3146 dot
+1.00 0 577 3146 er
+1.00 0 569 2842 en2
+1.00 0 689 3114 qn
+1.00 0 865 3146 qn
+1.00 0 953 3114 qn
+1.00 0 769 3066 qn
+1.00 180 985 2874 qn
+1.00 180 1073 2858 qn
+1.00 180 1161 2874 qn
+1.00 0 753 2778 hr
+1.00 0 1073 3162 qr
+1.00 0 1105 3146 dot
+1.00 0 2249 3146 er
+1.00 0 2249 2826 en2
+1.00 0 2553 3130 qn
+1.00 0 2465 3098 qn
+1.00 180 2697 2858 qn
+1.00 180 2785 2874 qn
+1.00 0 2441 2778 hr
+1.00 0 2761 3162 qr
+1.00 0 2793 3146 dot
+1.00 0 2161 2970 bar
+1.00 0 217 2970 staff
+1.00 0 217 4506 staff
+1.00 0 665 4378 wn
+1.00 0 2969 2970 bar
+1.00 0 3049 3146 er
+1.00 0 3457 3098 qn
+1.00 0 3545 3178 qn
+1.00 0 3633 3066 qn
+1.00 0 3721 3162 qn
+1.00 0 657 3562 shp
+1.00 180 1585 762 qn
+1.00 0 1281 2970 bar
+1.00 0 1209 2362 qn
+1.00 0 1361 2346 hn
+1.00 0 569 2298 qn
+1.00 0 649 2362 qn
+1.00 0 753 2330 qn
+1.00 0 841 2298 qn
+1.00 0 953 2314 qn
+1.00 0 1041 2330 qn
+1.00 0 1129 2346 qn
+1.00 0 897 2314 nat
+1.00 0 969 2010 hr
+1.00 0 2089 2202 bar
+1.00 0 2937 2202 bar
+1.00 0 3193 3098 qn
+1.00 0 3281 3066 qn
+1.00 0 3369 3130 qn
+1.00 0 3121 3098 shp
+1.00 0 1361 2378 hn
+1.00 0 2201 2346 hn
+1.00 0 1361 2298 hn
+1.00 0 1297 2378 nat
+1.00 0 2137 2314 nat
+1.00 0 1953 2298 qn
+1.00 0 2057 2314 qn
+1.00 0 1993 2314 nat
+1.00 0 1737 2378 er
+1.00 0 2705 2330 qn
+1.00 0 2809 2346 qn
+1.00 0 2897 2362 qn
+1.00 0 2585 2378 er
+1.00 0 3081 2362 hn
+1.00 0 3081 2330 hn
+1.00 0 3081 2298 hn
+1.00 0 689 2330 shp
+1.00 0 3393 2346 shp
+1.00 0 2201 2314 hn
+1.00 0 3465 2314 hn
+1.00 0 3465 2346 hn
+1.00 0 217 2202 staff
+1.00 0 2969 2330 shp
+1.00 0 2745 2074 nat
+1.00 180 2569 2074 qn
+1.00 180 2665 2090 qn
+1.00 180 2769 2106 qn
+1.00 0 3009 2298 shp
+1.00 0 2201 1978 qn
+1.00 0 2297 1994 qn
+1.00 0 2409 2010 qn
+1.00 0 2505 2026 qn
+1.00 0 2345 2010 nat
+1.00 0 1801 2010 nat
+1.00 0 1345 1930 qn
+1.00 0 1441 1946 qn
+1.00 0 1553 1962 qn
+1.00 0 1649 1978 qn
+1.00 180 2017 2074 qn
+1.00 180 1721 2026 qn
+1.00 180 1825 2042 qn
+1.00 180 1921 2058 qn
+1.00 0 1489 1962 nat
+1.00 0 1249 2202 bar
+1.00 0 2561 1434 bar
+1.00 0 3009 2074 nat
+1.00 180 3329 2074 qn
+1.00 180 3033 2106 qn
+1.00 180 3121 2090 qn
+1.00 180 3225 2058 qn
+1.00 0 3601 1978 shp
+1.00 0 3465 2010 qn
+1.00 0 3561 1994 qn
+1.00 0 3673 1978 qn
+1.00 0 3785 1962 qn
+1.00 0 3721 1962 nat
+1.00 0 3297 2042 shp
+1.00 180 1945 1290 qn
+1.00 0 1617 1578 hn
+1.00 0 3193 2026 shp
+1.00 0 2113 1578 hn
+1.00 0 1617 1530 hn
+1.00 0 2113 1514 hnt
+1.00 0 2729 1546 wn
+1.00 0 1081 1290 hn
+1.00 0 2729 1258 wn
+1.00 0 2729 1178 wn
+1.00 0 2985 1562 qn
+1.00 0 3289 1594 qn
+1.00 0 3593 1626 qn
+1.00 0 2657 1258 shp
+1.00 0 2909 1562 shp
+1.00 0 1145 1242 nat
+1.00 0 609 1178 qn
+1.00 0 721 1194 qn
+1.00 0 849 1210 qn
+1.00 0 953 1242 qn
+1.00 180 1393 1290 qn
+1.00 180 1169 1274 qn
+1.00 180 1281 1258 qn
+1.00 0 1497 1434 bar
+1.00 0 617 1594 qn
+1.00 0 849 1578 qn
+1.00 0 1089 1578 qn
+1.00 0 1321 1562 qn
+1.00 180 577 1578 hn
+1.00 180 1049 1562 hn
+1.00 0 617 1322 hnt
+1.00 0 217 1434 staff
+1.00 0 553 1546 nat
+1.00 180 577 762 hn
+1.00 180 1041 778 hn
+1.00 0 1081 522 hnt
+1.00 0 617 778 qn
+1.00 0 729 810 qn
+1.00 0 841 842 qn
+1.00 0 953 826 qn
+1.00 0 1081 778 qn
+1.00 0 1193 810 qn
+1.00 0 1305 794 qn
+1.00 0 1425 778 qn
+1.00 0 617 394 hn
+1.00 0 1081 410 hn
+1.00 0 617 506 hn
+1.00 0 1625 762 hn
+1.00 0 2073 762 hn
+1.00 0 2073 794 hn
+1.00 0 1497 634 bar
+1.00 0 2457 634 bar
+1.00 180 1577 1338 qn
+1.00 180 1697 1322 qn
+1.00 180 1817 1306 qn
+1.00 0 1737 554 qstem1
+1.00 0 1849 538 qstem2
+1.00 0 2681 1530 lnt
+1.00 0 1977 522 qstem1
+1.00 0 1625 554 er
+1.00 0 2569 458 er
+1.00 180 1585 458 hn
+1.00 0 1849 730 qr
+1.00 0 785 1210 shp
+1.00 0 2489 762 shp
+1.00 0 2681 426 qn
+1.00 0 2793 410 qn
+1.00 0 2905 426 qn
+1.00 0 1553 762 shp
+1.00 0 2057 458 er
+1.00 0 2169 426 qn
+1.00 0 2281 442 qn
+1.00 0 2393 426 qn
+1.00 0 2449 1194 qn
+1.00 0 2113 1242 qn
+1.00 0 2225 1226 qn
+1.00 0 2337 1210 qn
+1.00 0 3353 378 qn
+1.00 0 3017 378 qn
+1.00 0 3129 410 qn
+1.00 0 3241 394 qn
+1.00 0 2569 362 wn
+1.00 0 2569 250 wn
+1.00 0 2521 346 lnt
+1.00 0 2521 314 lnt
+1.00 0 2521 282 lnt
+1.00 0 2569 730 wn
+1.00 0 2569 762 wn
+1.00 0 2569 794 wn
+1.00 0 3545 778 wn
+1.00 0 3545 698 wn
+1.00 0 3497 346 lnt
+1.00 0 3497 314 lnt
+1.00 0 3545 730 wn
+1.00 0 217 634 staff
+1.00 0 3545 250 wn
+1.00 0 3497 282 lnt
+1.00 0 3497 730 lnt
+1.00 0 3417 634 bar
+1.00 0 3817 634 bar
+1.00 0 537 1322 shp
+(f) {/Times-BoldItalic 2.250 cf} 1 5 0 569 4506 label
+(Prelude in g-minor) {/Times-Bold 3.000 cf} 1 9 0 1977 4938 label
+(Tempo I) {/Times-BoldItalic 2.000 cf} 1 0 0 377 994 label
+(Andante) {/Times-BoldItalic 2.000 cf} 1 0 0 289 4898 label
+(rit . . .) {/Times-BoldItalic 2.000 cf} 1 0 0 2937 1410 label
+(rit . . .) {/Times-BoldItalic 2.000 cf} 1 0 0 3009 626 label
+(Allegretto) {/Times-BoldItalic 2.000 cf} 1 0 0 1417 4074 label
+(Tim Edwards 1992) {/Times-Roman 2.000 cf} 1 11 0 3833 4938 label
+697 4410 beginpath
+857 4474 1721 4474 1865 4402 curveto
+1721 4466 857 4466 697 4410 curveto
+241 1.00 endpath
+697 4218 beginpath
+857 4154 1721 4154 1865 4226 curveto
+1721 4162 857 4162 697 4218 curveto
+241 1.00 endpath
+3129 2762 beginpath
+3217 2714 3657 2714 3817 2754 curveto
+3657 2706 3217 2706 3129 2762 curveto
+241 1.00 endpath
+496 1.00 2169 554 2169 570 2393 570 2393 554 4 polygon
+496 1.00 2681 554 2681 570 2905 570 2905 554 4 polygon
+1.00 0 537 4282 four
+1.00 0 537 4730 four
+1.00 0 537 4666 four
+1.00 0 537 4346 four
+1 1.00 3329 1906 3329 1950 2 polygon
+1.00 0 2729 1482 wnt
+1.00 0 2201 2282 hnt
+1.00 0 2425 4618 hnd
+1.00 0 665 4650 hnd
+1.00 0 2281 3626 ent
+1.00 0 2937 3626 qstem1
+1.00 0 3481 3818 qstem3
+1.00 0 3193 3818 qstem3
+1.00 0 1745 3034 qstem4
+1.00 0 1481 3034 qstem4
+1.00 0 2641 3050 qstem3
+1.00 0 2377 3050 qstem3
+1.00 0 2913 2858 qstem1
+1.00 0 2905 2090 qstem1
+496 1.00 1041 1114 1041 1130 1393 1146 1393 1130 4 polygon
+1 1.00 617 522 617 538 2 polygon
+496 1.00 1697 458 1697 474 1937 442 1937 426 4 polygon
+1.00 0 1689 538 lnt
+1.00 0 1849 2282 qstem3
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/systemd1.lgf b/examples/systemd1.lgf
new file mode 100644
index 0000000..4fe9415
--- /dev/null
+++ b/examples/systemd1.lgf
@@ -0,0 +1,2544 @@
+-5
+f s
+n 48
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+33 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+33 0
+
+32 0
+
+33 0
+
+32 0
+
+33 0
+
+33 0
+
+32 0
+
+33 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+32 0
+
+33 0
+
+32 0
+
+s 17
+2 Gnd
+1 Vdd
+3 Voff
+22 Iin
+4 Vc
+29 Iout
+23 a1
+28 a2
+30 c1
+31 Iy
+20 Vx
+24 apc
+25 a2nc
+12 xc
+21 Voutc
+17 Vout
+18 VQ
+w 76
+3289 3344 3298 3344 11 U
+3289 3337 3298 3337 41 U
+3285 3333 3289 3333 41 U
+3310 3343 3316 3343 43 U
+3306 3368 3312 3368 42 U
+3415 3293 3419 3293 23 U
+3413 3289 3419 3289 23 U
+3415 3301 3419 3301 24 U
+3413 3297 3419 3297 24 U
+3423 3301 3427 3301 25 U
+3427 3312 3432 3312 28 U
+3427 3305 3433 3305 25 U
+3395 3294 3399 3294 30 U
+3379 3282 3381 3282 18 U
+3345 3282 3348 3282 3 U
+3363 3282 3366 3282 4 U
+3316 3364 3319 3364 19 U
+3302 3350 3340 3350 20 U
+3341 3334 3345 3334 14 U
+3341 3326 3345 3326 13 U
+3380 3363 3388 3363 9 U
+3341 3357 3392 3357 8 U
+3355 3334 3359 3334 21 U
+3402 3356 3405 3356 35 U
+3409 3353 3418 3353 6 U
+3392 3360 3398 3360 8 U
+3345 3330 3351 3330 14 U
+3345 3322 3351 3322 13 U
+3323 3360 3355 3360 15 U
+3409 3346 3418 3346 7 U
+3418 3342 3422 3342 7 U
+3378 3344 3392 3344 12 U
+3353 3338 3367 3338 21 U
+3353 3345 3367 3345 17 U
+3355 3351 3398 3351 15 U
+3302 3347 3302 3350 20 U
+3285 3347 3285 3350 3 U
+3295 3341 3295 3353 11 U
+3289 3333 3289 3337 41 U
+3285 3314 3285 3317 1 U
+3285 3325 3285 3333 41 U
+3316 3333 3316 3347 43 U
+3319 3363 3319 3364 19 U
+3316 3353 3316 3365 19 U
+3306 3347 3306 3368 42 U
+3319 3350 3319 3357 20 U
+3334 3370 3334 3371 44 U
+3419 3289 3419 3293 23 U
+3419 3297 3419 3301 24 U
+3427 3301 3427 3305 25 U
+3431 3309 3431 3314 28 U
+3399 3290 3399 3294 30 U
+3379 3282 3379 3285 18 U
+3345 3282 3345 3285 3 U
+3334 3377 3334 3380 18 U
+3334 3350 3334 3362 20 U
+3341 3353 3341 3357 8 U
+3345 3330 3345 3334 14 U
+3345 3322 3345 3326 13 U
+3392 3354 3392 3360 8 U
+3365 3342 3365 3359 17 U
+3371 3348 3371 3349 3 U
+3355 3348 3355 3360 15 U
+3359 3334 3359 3338 21 U
+3380 3348 3380 3363 9 U
+3398 3359 3398 3360 8 U
+3398 3351 3398 3353 15 U
+3405 3356 3405 3361 35 U
+3413 3350 3413 3360 6 U
+3422 3356 3422 3359 3 U
+3392 3340 3392 3348 12 U
+3371 3330 3371 3334 1 U
+3418 3342 3418 3346 7 U
+3341 3346 3341 3347 26 U
+3341 3333 3341 3338 14 U
+3363 3282 3363 3284 4 U
+p 13
+3316 3343 4 42
+3295 3344 1 38
+3431 3312 11 51
+3316 3364 17 44
+3334 3350 18 56
+3319 3350 18 46
+3392 3357 22 60
+3413 3353 25 69
+3392 3344 32 71
+3359 3338 33 64
+3365 3345 34 61
+3341 3334 19 75
+3355 3351 35 63
+l 1
+3318 3304 18 Bandpass filter
+b 5
+3407 3280 3440 3327
+3390 3280 3405 3308
+3374 3280 3388 3301
+3341 3280 3372 3299
+3317 3303 3337 3307
+g 143
+NPN1
+3420 3353 0 188 0 0 17
+6 5 3
+U1.125260918
+X
+U1E-14
+U0.930873092
+X
+U1E-15
+U0.500390581
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.14850E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.27215E+00
+-1.00000E+06
+ 1.00000E-15
+ 5.24432E-01
+-1.00000E+06
+ 1.00000E-15
+
+NFET7T
+3422 3346 0 43 0 0 19
+7 7 5
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.965
+U0.679
+U21.288
+ 2.70816E+00
+-1.00000E+06
+ 3.30402E-15
+ 2.70816E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.27215E+00
+-1.00000E+06
+ 9.43200E-15
+
+NFET7T
+3413 3346 2 189 0 0 19
+7 6 1
+U5.000
+X
+U3.304E-15
+U2.791
+X
+U9.432E-15
+U5.000
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.939
+U0.679
+U22.060
+ 2.70816E+00
+-1.00000E+06
+ 3.30402E-15
+ 1.14850E+00
+-1.00000E+06
+ 9.43200E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+NPN1
+3390 3363 0 81 0 0 17
+9 8 2
+U0.458459496
+X
+U1E-14
+U0.282339174
+X
+U1E-15
+U0
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 4.34136E-01
+-1.00000E+06
+ 1.00000E-14
+ 3.14502E-01
+-1.00000E+06
+ 1.00000E-15
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-15
+
+NPN1
+3287 3344 4 4 0 0 17
+11 10 3
+U1.130248205
+X
+U1E-14
+U0.895305914
+X
+U1E-15
+U0.500395802
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.15598E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.21654E+00
+-1.00000E+06
+ 1.00000E-15
+ 5.24432E-01
+-1.00000E+06
+ 1.00000E-15
+
+NFET7T
+3380 3344 2 83 0 0 19
+12 9 1
+U0.309
+X
+U3.304E-15
+U0.427
+X
+U9.432E-15
+U5.000
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.770
+U0.679
+U20.860
+ 1.80170E+00
+-1.00000E+06
+ 3.30402E-15
+ 4.34136E-01
+-1.00000E+06
+ 9.43200E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+PFET7T
+3341 3330 2 218 0 0 19
+14 14 13
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.067
+U0.693
+U17.580
+ 3.34433E+00
+-1.00000E+06
+ 3.08301E-15
+ 3.34433E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.26713E+00
+-1.00000E+06
+ 1.69200E-14
+
+NPN1
+3390 3351 0 206 0 0 17
+15 12 8
+U0.72539595
+X
+U1E-14
+U1.427390435
+X
+U1E-15
+U0.321844213
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 7.17181E-01
+-1.00000E+06
+ 1.00000E-14
+ 1.80170E+00
+-1.00000E+06
+ 1.00000E-15
+ 3.14502E-01
+-1.00000E+06
+ 1.00000E-15
+
+NPN1
+3357 3345 4 18 0 0 17
+17 16 15
+U1.119359496
+X
+U1E-14
+U1.442569946
+X
+U1E-15
+U0.685717452
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.12865E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.80290E+00
+-1.00000E+06
+ 1.00000E-15
+ 7.17181E-01
+-1.00000E+06
+ 1.00000E-15
+
+VDIFF
+3363 3288 0 52 0 0 23
+4 2
+B0
+U50
+V0
+U1
+U0
+U5
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U2.5
+U1
+U1000
+R0
+U0
+U0.999996413
+X
+U1E-14
+U0
+X
+U1E-14
+ 1.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28318E-01
+ TRUE
+FALSE
+ 1.00000E+00
+ 0.00000E+00
+ TRUE
+FALSE
+
+FROM
+3339 3380 4 20 0 17 0
+18
+
+TO
+3386 3282 0 44 0 17 0
+18
+
+NPN1
+3321 3360 4 119 0 0 17
+15 20 19
+U0.685718355
+X
+U1E-14
+U0.720118143
+X
+U1E-15
+U0.365953503
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 7.17181E-01
+-1.00000E+06
+ 1.00000E-14
+ 7.22620E-01
+-1.00000E+06
+ 1.00000E-15
+ 3.19446E-01
+-1.00000E+06
+ 1.00000E-15
+
+FROM
+3350 3342 4 94 0 14 0
+12
+
+NFET7T
+3341 3342 2 95 0 0 19
+12 26 14
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.923
+U0.679
+U16.876
+ 1.80170E+00
+-1.00000E+06
+ 3.30402E-15
+ 1.07161E+00
+-1.00000E+06
+ 9.43200E-15
+ 3.34433E+00
+-1.00000E+06
+ 9.43200E-15
+
+ISCOPE
+3339 3336 1 248 0 0 2
+14 27
+U2.389893225264E-9
+C2.390nA
+
+TO
+3348 3345 4 4 0 16 0
+17
+
+TO
+3348 3338 4 3 0 15 0
+21
+
+TO
+3373 3344 4 92 0 14 0
+12
+
+VDD
+3422 3334 0 191 0 2 0
+1
+
+FROM
+3431 3338 4 192 0 9 0
+30
+
+PFET7T
+3422 3338 2 190 0 0 19
+30 7 1
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.694
+U22.233
+ 3.33277E+00
+-1.00000E+06
+ 3.08301E-15
+ 2.70816E+00
+-1.00000E+06
+ 1.69200E-14
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+
+VDD
+3371 3330 0 13 0 2 0
+1
+
+MMETER
+3319 3348 0 53 0 0 2
+20
+U0.722620174
+C0.723V
+
+ISCOPE
+3336 3369 0 54 0 0 2
+44 32
+U5.9071934653691E-10
+C590.719pA
+
+FROM
+3383 3336 0 25 0 12 0
+24
+
+PFET7T
+3392 3336 0 22 0 0 19
+24 33 12
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.066
+U0.693
+U17.512
+ 3.35936E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.27133E+00
+-1.00000E+06
+ 1.69200E-14
+ 1.80170E+00
+-1.00000E+06
+ 1.69200E-14
+
+FROM
+3383 3328 0 131 0 7 0
+23
+
+PFET7T
+3392 3328 0 41 0 0 19
+23 1 33
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.690
+U16.351
+ 4.27384E+00
+-1.00000E+06
+ 3.08301E-15
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.27133E+00
+-1.00000E+06
+ 1.69200E-14
+
+VDD
+3392 3324 0 62 0 2 0
+1
+
+ISCOPE
+3400 3351 0 252 0 0 2
+15 34
+U2.3771444404939E-9
+C2.377nA
+
+NPN1
+3400 3356 4 72 0 0 17
+35 15 8
+U0.720640402
+X
+U1E-14
+U0.685697758
+X
+U1E-15
+U0.282241418
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 7.23183E-01
+-1.00000E+06
+ 1.00000E-14
+ 7.17181E-01
+-1.00000E+06
+ 1.00000E-15
+ 3.14502E-01
+-1.00000E+06
+ 1.00000E-15
+
+NFET7T
+3405 3346 2 203 0 0 19
+7 36 1
+U5.000
+X
+U3.304E-15
+U2.791
+X
+U9.432E-15
+U5.000
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U1.070
+U0.679
+U17.904
+ 2.70816E+00
+-1.00000E+06
+ 3.30402E-15
+ 1.81349E+00
+-1.00000E+06
+ 9.43200E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+NPN1
+3407 3353 4 187 0 0 17
+6 36 35
+U1.12521612
+X
+U1E-14
+U1.493282106
+X
+U1E-15
+U0.720640454
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.14850E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.81349E+00
+-1.00000E+06
+ 1.00000E-15
+ 7.23183E-01
+-1.00000E+06
+ 1.00000E-15
+
+FROM
+3427 3359 4 197 0 3 0
+3
+
+VDD
+3405 3342 0 204 0 2 0
+1
+
+VDD
+3413 3342 0 193 0 2 0
+1
+
+GND
+3405 3375 0 202 0 1 0
+2
+
+FROM
+3396 3372 0 201 0 8 0
+28
+
+NPN1
+3403 3372 0 200 0 0 17
+28 37 2
+U0.403977185
+X
+U1E-14
+U0.70911367
+X
+U1E-15
+U0
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 4.04024E-01
+-1.00000E+06
+ 1.00000E-14
+ 7.20694E-01
+-1.00000E+06
+ 1.00000E-15
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-15
+
+FROM
+3396 3365 0 199 0 13 0
+25
+
+NFET7T
+3405 3365 0 198 0 0 19
+25 35 37
+U5.000
+X
+U3.304E-15
+U2.791
+X
+U9.432E-15
+U5.000
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.843
+U0.679
+U17.111
+ 1.48838E+00
+-1.00000E+06
+ 3.30402E-15
+ 7.23183E-01
+-1.00000E+06
+ 9.43200E-15
+ 7.20694E-01
+-1.00000E+06
+ 9.43200E-15
+
+GND
+3413 3368 0 196 0 1 0
+2
+
+FROM
+3422 3364 4 195 0 5 0
+4
+
+NFET7T
+3413 3364 2 194 0 0 19
+4 2 6
+U0.900
+X
+U2.202E-15
+U0.000
+X
+U9.432E-15
+U1.125
+X
+U9.432E-15
+U8.000
+U2.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U11.063
+ 1.00000E+00
+-1.00000E+06
+ 2.20268E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.14850E+00
+-1.00000E+06
+ 9.43200E-15
+
+MMETER
+3377 3355 1 247 0 0 2
+8
+U0.314502493
+C0.315V
+
+FROM
+3371 3367 0 78 0 5 0
+4
+
+GND
+3380 3371 0 79 0 1 0
+2
+
+NFET7T
+3380 3367 0 77 0 0 19
+4 9 2
+U0.900
+X
+U2.202E-15
+U0.419
+X
+U9.432E-15
+U0.000
+X
+U9.432E-15
+U8.000
+U2.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U11.063
+ 1.00000E+00
+-1.00000E+06
+ 2.20268E-15
+ 4.34136E-01
+-1.00000E+06
+ 9.43200E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+GND
+3365 3367 0 21 0 1 0
+2
+
+FROM
+3356 3363 0 20 0 5 0
+4
+
+NFET7T
+3365 3363 0 19 0 0 19
+4 17 2
+U0.900
+X
+U2.202E-15
+U1.103
+X
+U9.432E-15
+U0.000
+X
+U9.432E-15
+U8.000
+U2.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U11.063
+ 1.00000E+00
+-1.00000E+06
+ 2.20268E-15
+ 1.12865E+00
+-1.00000E+06
+ 9.43200E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+GND
+3351 3368 0 55 0 1 0
+2
+
+CAPFLOAT
+3351 3364 0 14 0 0 7
+15 2
+U2E-12
+U0.727026253
+X
+U1E-14
+U0
+X
+U1E-14
+ 7.17181E-01
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+
+VDD
+3355 3318 0 8 0 2 0
+1
+
+PFET7T
+3355 3322 0 244 0 0 19
+13 1 38
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.691
+U16.393
+ 4.26713E+00
+-1.00000E+06
+ 3.08301E-15
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.26600E+00
+-1.00000E+06
+ 1.69200E-14
+
+PFET7T
+3355 3330 0 219 0 0 19
+14 38 21
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.067
+U0.693
+U17.573
+ 3.34433E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.26600E+00
+-1.00000E+06
+ 1.69200E-14
+ 2.68259E+00
+-1.00000E+06
+ 1.69200E-14
+
+NFET7T
+3355 3338 2 22 0 0 19
+21 16 21
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U1.068
+U0.679
+U17.811
+ 2.68259E+00
+-1.00000E+06
+ 3.30402E-15
+ 1.80290E+00
+-1.00000E+06
+ 9.43200E-15
+ 2.68259E+00
+-1.00000E+06
+ 9.43200E-15
+
+FROM
+3376 3349 4 11 0 3 0
+3
+
+NPN1
+3369 3345 0 17 0 0 17
+17 39 3
+U1.119364269
+X
+U1E-14
+U0.987105103
+X
+U1E-15
+U0.500357518
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.12865E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.39395E+00
+-1.00000E+06
+ 1.00000E-15
+ 5.24432E-01
+-1.00000E+06
+ 1.00000E-15
+
+TO
+3381 3330 0 18 0 6 0
+29
+
+ISCOPE
+3373 3332 0 9 0 0 2
+1 29
+U6.9183571242761E-6
+C6.918uA
+
+NFET7T
+3371 3338 0 16 0 0 19
+21 1 39
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.990
+U0.679
+U20.366
+ 2.68259E+00
+-1.00000E+06
+ 3.30402E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.39395E+00
+-1.00000E+06
+ 9.43200E-15
+
+VDD
+3365 3334 0 6 0 2 0
+1
+
+NFET7T
+3365 3338 0 15 0 0 19
+21 1 17
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.935
+U0.679
+U22.025
+ 2.68259E+00
+-1.00000E+06
+ 3.30402E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.12865E+00
+-1.00000E+06
+ 9.43200E-15
+
+MMETER
+3394 3345 0 253 0 0 2
+12
+U1.801702251
+C1.802V
+
+VDD
+3380 3340 0 84 0 2 0
+1
+
+GND
+3392 3366 0 76 0 1 0
+2
+
+VDD
+3341 3318 0 220 0 2 0
+1
+
+PFET7T
+3341 3322 2 243 0 0 19
+13 13 1
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.691
+U16.393
+ 4.26713E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.26713E+00
+-1.00000E+06
+ 1.69200E-14
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+
+TO
+3345 3350 0 216 0 11 0
+20
+
+NPN1
+3339 3350 0 246 0 0 17
+20 26 8
+U0.72011832
+X
+U1E-14
+U0.752257365
+X
+U1E-15
+U0.282340291
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 7.22620E-01
+-1.00000E+06
+ 1.00000E-14
+ 1.07161E+00
+-1.00000E+06
+ 1.00000E-15
+ 3.14502E-01
+-1.00000E+06
+ 1.00000E-15
+
+NFET7T
+3302 3337 0 15 0 0 19
+41 1 40
+U2.537
+X
+U3.304E-15
+U5.000
+X
+U9.432E-15
+U1.685
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U1.069
+U0.679
+U17.970
+ 2.71806E+00
+-1.00000E+06
+ 3.30402E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.81280E+00
+-1.00000E+06
+ 9.43200E-15
+
+NPN1
+3300 3344 0 83 0 0 17
+11 40 20
+U1.130246157
+X
+U1E-14
+U1.490170458
+X
+U1E-15
+U0.718844008
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 1.15598E+00
+-1.00000E+06
+ 1.00000E-14
+ 1.81280E+00
+-1.00000E+06
+ 1.00000E-15
+ 7.22620E-01
+-1.00000E+06
+ 1.00000E-15
+
+NFET7T
+3306 3343 2 47 0 0 19
+43 42 1
+U1.572
+X
+U3.304E-15
+U0.398
+X
+U9.432E-15
+U5.000
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.766
+U0.679
+U20.831
+ 1.78159E+00
+-1.00000E+06
+ 3.30402E-15
+ 4.18662E-01
+-1.00000E+06
+ 9.43200E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+IDIFF
+3415 3305 0 99 0 0 23
+24 2
+B0
+U0.1
+V0
+U2E-9
+U0
+U1E-7
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U5E-9
+U1E-9
+U1000
+R0
+U0
+U3.359362762
+X
+U1E-14
+U0
+X
+U1E-14
+ 3.35936E+00
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28318E-01
+ TRUE
+FALSE
+ 0.00000E+00
+ TRUE
+FALSE
+
+NPN1
+3314 3350 0 58 0 0 17
+20 43 19
+U0.718859349
+X
+U1E-14
+U1.423409013
+X
+U1E-15
+U0.315354501
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 7.22620E-01
+-1.00000E+06
+ 1.00000E-14
+ 1.78159E+00
+-1.00000E+06
+ 1.00000E-15
+ 3.19446E-01
+-1.00000E+06
+ 1.00000E-15
+
+FROM
+3325 3366 0 212 0 13 0
+25
+
+NFET7T
+3334 3366 0 211 0 0 19
+25 20 44
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.843
+U0.679
+U17.102
+ 1.48838E+00
+-1.00000E+06
+ 3.30402E-15
+ 7.22620E-01
+-1.00000E+06
+ 9.43200E-15
+ 7.22103E-01
+-1.00000E+06
+ 9.43200E-15
+
+FROM
+3325 3374 0 86 0 8 0
+28
+
+NPN1
+3332 3374 0 6 0 0 17
+28 44 18
+U0.403976975
+X
+U1E-14
+U0.708734662
+X
+U1E-15
+U1.008518613718E-7
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 4.04024E-01
+-1.00000E+06
+ 1.00000E-14
+ 7.22103E-01
+-1.00000E+06
+ 1.00000E-15
+ 3.00000E-02
+-1.00000E+06
+ 1.00000E-15
+
+PFET7T
+3316 3329 0 22 0 0 19
+24 45 43
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.066
+U0.693
+U17.512
+ 3.35936E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.27130E+00
+-1.00000E+06
+ 1.69200E-14
+ 1.78159E+00
+-1.00000E+06
+ 1.69200E-14
+
+NUMBERS
+3316 3286 0 2 0 0 16
+
+U5
+U0.1
+U7
+U-2
+U1E-6
+U1E-20
+U1E-40
+U1E-5
+U1E-40
+U1E-9
+U2
+I2
+I30
+R2
+U0.1
+U1E-14
+FALSE
+ TRUE
+
+TIME
+3290 3286 0 1 90 0 0
+
+
+TO
+3371 3282 0 54 0 5 0
+4
+
+GND
+3363 3292 0 53 0 1 0
+2
+
+TO
+3353 3282 0 13 0 3 0
+3
+
+VDIFF
+3345 3289 0 22 0 0 23
+3 2
+B0
+U5
+V0
+U0.5
+U0
+U5
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U2.5
+U1
+U1000
+R0
+U0
+U0.500416859
+X
+U1E-14
+U0
+X
+U1E-14
+ 5.24432E-01
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28318E-01
+ TRUE
+FALSE
+ 5.00000E-01
+ 0.00000E+00
+ TRUE
+FALSE
+
+GND
+3345 3293 0 23 0 1 0
+2
+
+VDIFF
+3379 3289 0 21 0 0 23
+18 2
+B0
+U50
+V0
+U0.03
+U0
+U5
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U2.5
+U1
+U1000
+R0
+U0
+U0.032156937
+X
+U1E-14
+U0
+X
+U1E-14
+ 3.00000E-02
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28254E-01
+ TRUE
+FALSE
+ 3.00000E-02
+ 0.00000E+00
+ TRUE
+FALSE
+
+GND
+3379 3293 0 217 0 1 0
+2
+
+PFET7T
+3395 3290 2 44 0 0 19
+30 30 1
+U3.545
+X
+U3.083E-15
+U3.545
+X
+U1.692E-14
+U5.000
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.694
+U22.233
+ 3.33277E+00
+-1.00000E+06
+ 3.08301E-15
+ 3.33277E+00
+-1.00000E+06
+ 1.69200E-14
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+
+VDD
+3395 3286 0 7 0 2 0
+1
+
+TO
+3404 3290 0 6 0 9 0
+30
+
+GND
+3395 3302 0 4 0 1 0
+2
+
+IDIFF
+3395 3298 0 3 0 0 23
+30 2
+B0
+U0.1
+V0
+U1.5E-5
+U0
+U1E-7
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U5E-9
+U1E-9
+U1000
+R0
+U0
+U3.332770057
+X
+U1E-14
+U0
+X
+U1E-14
+ 3.33277E+00
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28318E-01
+ TRUE
+FALSE
+ 0.00000E+00
+ TRUE
+FALSE
+
+NFET7T
+3431 3318 2 68 0 0 19
+4 2 28
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U18.563
+ 1.00000E+00
+-1.00000E+06
+ 3.30402E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 4.04024E-01
+-1.00000E+06
+ 9.43200E-15
+
+FROM
+3440 3318 4 10 0 5 0
+4
+
+GND
+3431 3322 0 9 0 1 0
+2
+
+PFET7T
+3423 3297 0 27 0 0 19
+24 48 25
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.066
+U0.693
+U17.509
+ 3.35936E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.27085E+00
+-1.00000E+06
+ 1.69200E-14
+ 1.48838E+00
+-1.00000E+06
+ 1.69200E-14
+
+NPN1
+3425 3312 4 4 0 0 17
+28 46 2
+X
+X
+X
+X
+X
+X
+X
+X
+X
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 4.04024E-01
+-1.00000E+06
+ 1.00000E-14
+ 8.18331E-01
+-1.00000E+06
+ 1.00000E-15
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-15
+
+VDD
+3431 3301 0 11 0 2 0
+1
+
+TO
+3438 3305 0 33 0 13 0
+25
+
+NFET7T
+3431 3305 0 7 0 0 19
+25 1 28
+U1.556
+X
+U3.304E-15
+U5.000
+X
+U9.432E-15
+U0.386
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.762
+U0.679
+U19.090
+ 1.48838E+00
+-1.00000E+06
+ 3.30402E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 4.04024E-01
+-1.00000E+06
+ 9.43200E-15
+
+TO
+3437 3312 0 93 0 8 0
+28
+
+NFET7T
+3423 3305 2 32 0 0 19
+25 46 25
+U1.553
+X
+U3.304E-15
+U0.898
+X
+U9.432E-15
+U1.553
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.866
+U0.679
+U16.500
+ 1.48838E+00
+-1.00000E+06
+ 3.30402E-15
+ 8.18331E-01
+-1.00000E+06
+ 9.43200E-15
+ 1.48838E+00
+-1.00000E+06
+ 9.43200E-15
+
+GND
+3423 3315 0 80 0 1 0
+2
+
+ISCOPE
+3425 3283 0 6 0 0 2
+1 47
+U2.0003423157496E-9
+C2.000nA
+
+TO
+3408 3297 4 28 0 12 0
+24
+
+TO
+3408 3289 4 115 0 7 0
+23
+
+PFET7T
+3423 3289 0 42 0 0 19
+23 1 48
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.690
+U16.351
+ 4.27384E+00
+-1.00000E+06
+ 3.08301E-15
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.27085E+00
+-1.00000E+06
+ 1.69200E-14
+
+VDD
+3423 3285 0 77 0 2 0
+1
+
+GND
+3415 3309 0 87 0 1 0
+2
+
+PFET7T
+3415 3297 2 26 0 0 19
+24 24 23
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-1.066
+U0.693
+U17.528
+ 3.35936E+00
+-1.00000E+06
+ 3.08301E-15
+ 3.35936E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.27384E+00
+-1.00000E+06
+ 1.69200E-14
+
+PFET7T
+3415 3289 2 43 0 0 19
+23 23 1
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.690
+U16.351
+ 4.27384E+00
+-1.00000E+06
+ 3.08301E-15
+ 4.27384E+00
+-1.00000E+06
+ 1.69200E-14
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+
+VDD
+3415 3285 0 84 0 2 0
+1
+
+NFET7T
+3295 3357 0 65 0 0 19
+4 11 2
+U0.900
+X
+U2.202E-15
+U1.132
+X
+U9.432E-15
+U0.000
+X
+U9.432E-15
+U8.000
+U2.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U11.063
+ 1.00000E+00
+-1.00000E+06
+ 2.20268E-15
+ 1.15598E+00
+-1.00000E+06
+ 9.43200E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+NFET7T
+3306 3372 0 64 0 0 19
+4 42 2
+U0.900
+X
+U2.202E-15
+U0.261
+X
+U9.432E-15
+U0.000
+X
+U9.432E-15
+U8.000
+U2.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.641
+U0.679
+U11.063
+ 1.00000E+00
+-1.00000E+06
+ 2.20268E-15
+ 4.18662E-01
+-1.00000E+06
+ 9.43200E-15
+ 0.00000E+00
+-1.00000E+06
+ 9.43200E-15
+
+GND
+3295 3361 0 18 0 1 0
+2
+
+FROM
+3286 3357 0 19 0 5 0
+4
+
+GND
+3306 3376 0 6 0 1 0
+2
+
+FROM
+3297 3372 0 7 0 5 0
+4
+
+NPN1
+3314 3368 0 70 0 0 17
+42 19 2
+U0.41003593
+X
+U1E-14
+U0.365138733
+X
+U1E-15
+U0
+X
+U1E-15
+U5E-17
+U5E-17
+U100
+U0.26
+U1.28E-16
+U0.025
+U0.8
+U20
+ 4.18662E-01
+-1.00000E+06
+ 1.00000E-14
+ 3.19446E-01
+-1.00000E+06
+ 1.00000E-15
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-15
+
+MMETER
+3314 3359 1 17 0 0 2
+19
+U0.31944623
+C0.319V
+
+TO
+3329 3353 0 19 0 10 0
+31
+
+ISCOPE
+3321 3355 0 18 0 0 2
+20 31
+U1.5272699597252E-9
+C1.527nA
+
+GND
+3316 3371 0 71 0 1 0
+2
+
+FROM
+3307 3329 0 25 0 12 0
+24
+
+PFET7T
+3316 3321 0 41 0 0 19
+23 1 45
+X
+X
+U3.083E-15
+X
+X
+U1.692E-14
+X
+X
+U1.692E-14
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U-0.876
+U0.690
+U16.351
+ 4.27384E+00
+-1.00000E+06
+ 3.08301E-15
+ 5.00000E+00
+-1.00000E+06
+ 1.69200E-14
+ 4.27130E+00
+-1.00000E+06
+ 1.69200E-14
+
+FROM
+3307 3321 0 131 0 7 0
+23
+
+VDD
+3316 3317 0 62 0 2 0
+1
+
+VDD
+3306 3339 0 4 0 2 0
+1
+
+VDD
+3285 3314 0 11 0 2 0
+1
+
+TO
+3295 3313 0 123 0 4 0
+22
+
+IDIFF
+3285 3321 0 10 0 0 23
+1 41
+B0
+U0.1
+V2
+U1E-6
+U0
+U1E-7
+U6E-4
+U3E-4
+U3E-4
+U6E-4
+U2E-3
+U0
+U2E-5
+U1E-6
+U6750
+R0
+U0
+U5
+X
+U1E-14
+U2.31118392
+X
+U1E-14
+ 5.00000E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.71806E+00
+-1.00000E+06
+ 1.00000E-14
+ 2.28318E-01
+ TRUE
+FALSE
+ 0.00000E+00
+ TRUE
+FALSE
+
+ISCOPE
+3287 3315 0 122 0 0 2
+1 22
+U2.0792211834923E-5
+C20.792uA
+
+NFET7T
+3285 3337 2 21 0 0 19
+41 10 41
+U2.543
+X
+U3.304E-15
+U1.146
+X
+U9.432E-15
+U2.543
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.953
+U0.679
+U21.697
+ 2.71806E+00
+-1.00000E+06
+ 3.30402E-15
+ 1.21654E+00
+-1.00000E+06
+ 9.43200E-15
+ 2.71806E+00
+-1.00000E+06
+ 9.43200E-15
+
+VDD
+3295 3333 0 16 0 2 0
+1
+
+NFET7T
+3295 3337 0 14 0 0 19
+41 1 11
+X
+X
+U3.304E-15
+X
+X
+U9.432E-15
+X
+X
+U9.432E-15
+U6.000
+U4.000
+U3.6E-5
+U3.6E-5
+U1.000
+U1.000
+U0.000
+U0.941
+U0.679
+U22.075
+ 2.71806E+00
+-1.00000E+06
+ 3.30402E-15
+ 5.00000E+00
+-1.00000E+06
+ 9.43200E-15
+ 1.15598E+00
+-1.00000E+06
+ 9.43200E-15
+
+FROM
+3290 3350 4 12 0 3 0
+3
+
+VDD
+3302 3333 0 82 0 2 0
+1
+
+CAPFLOAT
+3302 3354 0 14 0 0 7
+20 2
+U2E-12
+U0.726832342
+X
+U1E-14
+U0
+X
+U1E-14
+ 7.22620E-01
+-1.00000E+06
+ 1.00000E-14
+ 0.00000E+00
+-1.00000E+06
+ 1.00000E-14
+
+GND
+3302 3358 0 55 0 1 0
+2
+
+h 5
+143 9 Iout
+V2
+B1
+I3
+V0
+U2E-6
+U1.5E-5
+U1E-15
+U0
+U6.918E-6
+53 9 Iin
+V4
+B1
+I3
+V0
+U2E-6
+U2E-5
+U1E-15
+U0
+U2.079E-5
+233 9 Iout2
+V1
+B1
+I3
+V0
+U2E-6
+U1E-5
+U1E-15
+U0
+U4.006E-6
+323 9 Iout3
+V0
+B1
+I3
+V0
+U2E-6
+U0
+U1E-15
+U0
+U2.529E-6
+413 9 Iout4
+V3
+B1
+I3
+V0
+U2E-6
+U0
+U1E-15
+U0
+U7.098E-4
+.
diff --git a/examples/test.py b/examples/test.py
new file mode 100644
index 0000000..771a3b4
--- /dev/null
+++ b/examples/test.py
@@ -0,0 +1,48 @@
+#-----------------------------------------------------------
+# Test of the python interpreter and use of animation in
+# xcircuit. Execute this script using menu option
+# "File/Execute Script", if Python has been compiled in.
+#-----------------------------------------------------------
+
+from math import pi,sin,cos
+
+def move(h1, x, y):
+ d = {"position": (x, y)}
+ setattr(h1, d)
+
+def newarc(x, y, r):
+ h1=newelement("Arc")
+ d = {"radius": r, "minor axis": r, "position": (x, y)}
+ setattr(h1, d)
+ return h1
+
+x = y = 0
+x2 = y2 = 0
+bigrx = 400
+bigry = 200
+nsteps = 200
+step = 2 * pi / (nsteps - 1)
+
+set("grid","off")
+set("axis","off")
+set("snap","off")
+
+h1 = newarc(x, y, 100)
+h2 = newarc(x2, y2, 85)
+
+pause(0.5)
+for i in range(0,nsteps):
+ x2 = x
+ y2 = y
+ x = int(round(bigrx * sin(i * step)))
+ y = int(round(bigry * cos(i * step)))
+ move(h1, x, y)
+ move(h2, x2, y2)
+# pause(0.01)
+ refresh();
+
+set("grid","on")
+set("axis","on")
+set("snap","on")
+
+#-----------------------------------------------------------
diff --git a/examples/threestage.ps b/examples/threestage.ps
new file mode 100644
index 0000000..7cf2d40
--- /dev/null
+++ b/examples/threestage.ps
@@ -0,0 +1,352 @@
+%!PS-Adobe-3.0
+%%Title: threestage
+%%Creator: Xcircuit v2.3
+%%CreationDate: Thu Jun 21 10:14:16 2001
+%%Pages: 2
+%%BoundingBox: 79 62 522 313
+%%DocumentNeededResources: font Times-Roman font Symbol
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.3 1
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale /rotval exch def /just exch def
+ just 16 and 0 gt {0 1 dtransform gsave pagemat setmatrix idtransform
+ exch grestore 1 0 dtransform gsave pagemat setmatrix idtransform
+ exch grestore dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs 0 array def
+ /fscale 1.0 def /kY 0 def
+ gsave dup 1 add copy 0 exch {exch dup type /stringtype eq {true
+ charpath flattenpath} {exec} ifelse } repeat pop pathbbox grestore
+ 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and 0 gt {exch pop
+ neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt {exch pop
+ neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def rotval rotate Kn currentpoint translate
+ /Bline 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 1024 and 0 gt {2 setlinecap} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/samp {
+% -80 -80 160 160 bbox
+% samp is_schematic
+begingate
+0 1.00 -80 -80 -80 80 80 0 3 polygon
+1 1.00 0 -40 0 -80 2 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -61 50 label
+(+) {/Symbol cf} 2 5 0 1.00 -61 -46 label
+1.000 0.000 0.000 scb
+(in.m) {/Times-Roman cf} 2 7 0 1.00 -80 48 pinlabel
+(in.p) {/Times-Roman cf} 2 7 0 1.00 -80 -48 pinlabel
+(out) {/Times-Roman cf} 2 4 0 1.00 80 0 pinlabel
+(bias) {/Times-Roman cf} 2 13 0 1.00 0 -80 pinlabel
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/circle {
+% -6 -12 28 24 bbox
+% trivial
+begingate
+1 1.00 16 0 6 0.00 360.00 xcarc
+1 1.00 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 0 0 pinlabel
+endgate
+} def
+
+/capacitor {
+% -32 -64 64 128 bbox
+begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(c.1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(c.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+sce
+(spice:C%i %pc.1 %pc.2 1.0P) {/Times-Roman cf} 2 0 0 1.00 -208 -160 infolabel
+sce
+(sim:c %pc.1 %pc.2) {/Times-Roman cf} 2 0 0 1.00 -208 -208 infolabel
+endgate
+} def
+
+/dot {
+% -10 -10 20 20 bbox
+% trivial
+begingate
+248 1.00 0 0 6 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(x) {/Times-Roman cf} 2 29 0 1.00 0 0 pinlabel
+endgate
+} def
+
+%%Page: threestage 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 433 318 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 481 590 samp
+1.00 0 769 590 samp
+1.00 0 1057 590 samp
+1 1.00 481 510 481 286 1057 286 1057 510 4 polygon
+1 1.00 769 510 769 286 2 polygon
+1 1.00 561 590 609 590 609 542 689 542 4 polygon
+1 1.00 849 590 897 590 897 542 977 542 4 polygon
+1 1.00 1137 590 1185 590 1185 542 3 polygon
+1.00 0 1185 414 gnd
+1.00 0 897 414 gnd
+1.00 0 609 414 gnd
+1 1.00 609 590 609 702 369 702 369 638 401 638 5 polygon
+1 1.00 401 542 337 542 2 polygon
+1 1.00 689 638 657 638 657 702 897 702 897 590 5 polygon
+1 1.00 977 638 945 638 945 702 1185 702 1185 590 5 polygon
+1.00 -1 337 542 circle
+1 1.00 1185 590 1233 590 2 polygon
+1.00 0 1233 590 circle
+1.000 0.000 0.000 scb
+(Input) {/Times-Roman cf} 2 7 0 1.00 321 542 pinlabel
+(Output) {/Times-Roman cf} 2 4 0 1.00 1249 590 pinlabel
+(Bias) {/Times-Roman cf} 2 13 0 1.00 769 222 pinlabel
+sce
+1 1.00 769 286 769 238 2 polygon
+1.00 270 769 238 circle
+0.635 0.125 0.953 scb
+(Three-stage cascaded lowpass filter) {/Times-Roman cf} 2 0 0 1.00 497 798
+label
+sce
+1.00 0 609 478 capacitor
+1.00 0 897 478 capacitor
+1.00 0 1185 478 capacitor
+1.00 0 609 590 dot
+1.00 0 609 542 dot
+1.00 0 769 286 dot
+1.00 0 897 590 dot
+1.00 0 897 542 dot
+1.00 0 1185 590 dot
+pgsave restore showpage
+
+/nmos {
+% -64 -64 64 128 bbox
+begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+sce
+(spice:M%i %pD %pG %pS GND nmos) {/Times-Roman cf} 2 4 0 1.00 -244 -139
+infolabel
+sce
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/pmos {
+% -64 -64 64 128 bbox
+begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+sce
+(spice:M%i %pD %pG %pS Vdd pmos) {/Times-Roman cf} 2 4 0 1.00 -196 -139
+infolabel
+sce
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+endgate
+} def
+
+/vdd {
+% -32 0 64 66 bbox
+% trivial
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+1.000 0.000 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+%%Page: samp 2
+%%PageOrientation: Portrait
+/pgsave save def bop
+% samp is_symbol
+% 685 449 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.000 0.000 0.000 scb
+(in.m) {/Times-Roman cf} 2 4 0 1.00 973 513 pinlabel
+(in.p) {/Times-Roman cf} 2 7 0 1.00 621 513 pinlabel
+(out) {/Times-Roman cf} 2 4 0 1.00 973 577 pinlabel
+(bias) {/Times-Roman cf} 2 7 0 1.00 719 353 pinlabel
+sce
+1.00 0 797 289 gnd
+1025 1.00 701 449 893 449 2 polygon
+1025 1.00 765 641 829 641 2 polygon
+1025 1.00 797 641 797 577 701 577 3 polygon
+1025 1.00 893 577 957 577 2 polygon
+1.00 0 957 513 circle
+1.00 0 957 577 circle
+1.00 -1 637 513 circle
+1.00 -1 735 353 circle
+1025 1.00 797 417 797 449 2 polygon
+1.00 0 797 353 nmos
+1.00 0 893 641 pmos
+1.00 0 701 513 nmos
+1.00 -1 893 513 nmos
+1.00 -1 701 641 pmos
+1.00 0 797 449 dot
+1.00 0 893 577 dot
+1.00 0 701 577 dot
+1.00 0 797 641 dot
+1.00 0 701 705 vdd
+1.00 0 893 705 vdd
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/vcoblock.ps b/examples/vcoblock.ps
new file mode 100644
index 0000000..a14f01e
--- /dev/null
+++ b/examples/vcoblock.ps
@@ -0,0 +1,332 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: vcoblock
+%%Creator: Xcircuit v2.3
+%%CreationDate: Thu Jun 21 10:22:03 2001
+%%Pages: 1
+%%BoundingBox: 68 68 529 537
+%%DocumentNeededResources: font Times-Roman font Times-Italic
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.3
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.3 1
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale /rotval exch def /just exch def
+ just 16 and 0 gt {0 1 dtransform gsave pagemat setmatrix idtransform
+ exch grestore 1 0 dtransform gsave pagemat setmatrix idtransform
+ exch grestore dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale }
+ if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs 0 array def
+ /fscale 1.0 def /kY 0 def
+ gsave dup 1 add copy 0 exch {exch dup type /stringtype eq {true
+ charpath flattenpath} {exec} ifelse } repeat pop pathbbox grestore
+ 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and 0 gt {exch pop
+ neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt {exch pop
+ neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add} ifelse
+ /showflag 1 def rotval rotate Kn currentpoint translate
+ /Bline 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def
+ {dup type /stringtype eq {show}{exec} ifelse} repeat grestore } def
+/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def }
+ { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto dup 0 lt
+ {neg 1 sub -1 1 scale} if rotate dup scale } bind def
+/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch
+ 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def
+/beginparm { -1 1 {makeparm exch def} for
+ dup type /arraytype eq { aload length -1 1 {makeparm exch def}
+ for } if begingate } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/insertion {/PSobj save def /showpage {} def bop translate} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/arrowhead {
+% -12 -32 24 36 bbox
+% trivial
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/npn {
+% -64 -64 72 128 bbox
+begingate
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 240 0 -48 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+sce
+(spice:Q%i %pC %pB %pE npn) {/Times-Roman cf} 2 4 0 1.00 -244 -139 infolabel
+sce
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/invert {
+% -48 -40 112 80 bbox
+% trivial
+begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 48 0 8 0.00 360.00 xcarc
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 56 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(In) {/Times-Roman cf} 2 7 0 1.00 -48 0 pinlabel
+endgate
+} def
+
+/polarized {
+% -32 -64 64 128 bbox
+begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+1.000 0.000 0.000 scb
+(t) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(b) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+sce
+(spice:C%i %pt %pb 1.0P) {/Times-Roman cf} 2 0 0 1.00 -208 -160 infolabel
+sce
+(sim:e %pt %pb %pb) {/Times-Roman cf} 2 0 0 1.00 -208 -208 infolabel
+endgate
+} def
+
+/source {
+% -32 -64 64 128 bbox
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/isource {
+% -32 -64 64 128 bbox
+begingate
+1.00 0 0 0 source
+1 0.75 0 20 0 -8 2 polygon
+0.80 180 0 -20 arrowhead
+1.000 0.000 0.000 scb
+(i.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(i.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+endgate
+} def
+
+/diode {
+% -8 -48 36 96 bbox
+begingate
+248 1.00 -18 -16 0 16 18 -16 3 polygon
+1 1.00 0 -48 0 -16 2 polygon
+1 1.00 0 48 0 16 2 polygon
+1 1.00 -18 16 18 16 2 polygon
+1.000 0.000 0.000 scb
+(d.m) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(d.p) {/Times-Roman cf} 2 13 0 1.00 0 -48 pinlabel
+endgate
+} def
+
+/gnd {
+% -32 -60 64 68 bbox
+% trivial
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+1.000 0.000 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+%%Page: vcoblock 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 626 494 offsets
+1.6800 inchscale
+2.6000 setlinewidth
+
+1 1.00 466 686 274 686 2 polygon
+1 1.00 338 462 402 462 2 polygon
+1 1.00 370 462 370 558 2 polygon
+1 1.00 370 558 274 558 2 polygon
+1 1.00 274 590 274 526 2 polygon
+1 1.00 466 590 466 526 2 polygon
+1 1.00 274 398 274 366 2 polygon
+1 1.00 274 366 466 366 2 polygon
+1 1.00 466 366 466 398 2 polygon
+1 1.00 370 206 370 174 2 polygon
+1 1.00 370 814 370 846 2 polygon
+1 1.00 338 846 402 846 2 polygon
+1 1.00 658 622 658 494 2 polygon
+1 1.00 658 494 770 558 2 polygon
+1 1.00 770 558 658 622 2 polygon
+1 1.00 466 558 658 558 2 polygon
+1 1.00 666 582 698 582 2 polygon
+1 1.00 698 582 698 534 2 polygon
+1 1.00 714 534 682 534 2 polygon
+1 1.00 682 534 682 582 2 polygon
+1 1.00 786 558 834 558 2 polygon
+1 1.00 834 558 834 270 2 polygon
+1 1.00 434 270 530 270 2 polygon
+1 1.00 642 270 834 270 2 polygon
+4 1.00 258 190 258 334 450 334 450 190 4 polygon
+4 1.00 194 702 194 814 434 814 434 702 4 polygon
+4 1.00 514 190 514 334 642 334 642 190 4 polygon
+4 1.00 130 382 130 526 482 526 482 382 4 polygon
+4 1.00 114 174 114 590 498 590 498 174 4 polygon
+4 1.00 642 478 642 734 802 734 802 478 4 polygon
+0 1.00 778 558 8 0.00 360.00 xcarc
+(C) {/Times-Italic cf} 2 7 0 1.00 546 494 label
+(Current) {/Times-Roman cf} 2 3 0 0.80 322 766 label
+(Source) {/Times-Roman cf} 2 3 0 0.80 322 734 label
+(Current) {/Times-Roman cf} 2 3 0 0.80 258 462 label
+(Mirror) {/Times-Roman cf} 2 3 0 0.80 258 430 label
+(Switch) {/Times-Roman cf} 2 3 0 0.80 370 254 label
+(Inverter) {/Times-Roman cf} 2 1 0 0.80 578 206 label
+(Schmitt) {/Times-Roman cf} 2 1 0 0.80 722 670 label
+(Trigger) {/Times-Roman cf} 2 1 0 0.80 722 638 label
+(Current) {/Times-Roman cf} 2 0 0 0.80 130 302 label
+(Steering) {/Times-Roman cf} 2 0 0 0.80 130 270 label
+(Network) {/Times-Roman cf} 2 0 0 0.80 130 238 label
+(Inverting) {/Times-Roman cf} 2 1 0 0.75 722 702 label
+1 1.00 370 334 370 366 2 polygon
+248 1.00 370 462 6 0.00 360.00 xcarc
+248 1.00 370 366 6 0.00 360.00 xcarc
+248 1.00 274 558 6 0.00 360.00 xcarc
+248 1.00 466 558 6 0.00 360.00 xcarc
+248 1.00 594 558 6 0.00 360.00 xcarc
+248 1.00 370 686 6 0.00 360.00 xcarc
+1.00 0 466 462 npn
+1.00 -1 274 462 npn
+1.00 -1 370 270 npn
+1.00 -1 594 270 invert
+1.00 0 594 494 polarized
+1.00 0 370 750 isource
+1.00 -181 466 638 diode
+1.00 -181 274 638 diode
+1.00 0 370 174 gnd
+1.00 0 594 430 gnd
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/examples/xc_remote.sh b/examples/xc_remote.sh
new file mode 100755
index 0000000..8c21f80
--- /dev/null
+++ b/examples/xc_remote.sh
@@ -0,0 +1,24 @@
+#!/usr/local/bin/wish8.5
+#
+# Usage: xc_remote <filename>
+#
+# This script attempts to communicate with an existing xcircuit
+# application. If none exists, it starts a new xcircuit process.
+# If one exists, then it forces xcircuit to create a new window,
+# and the file <filename> is loaded into it as a new page.
+
+exec xhost -
+foreach host [lrange [split [exec xhost] \n] 1 end] {
+ exec xhost -$host
+}
+set appname "tkcon.tcl #2"
+if {[catch {send $appname xcircuit::forkwindow}]} {
+ exec xcircuit [lindex $argv 0] &
+} else {
+ send $appname {config focus [lindex [config windownames] 0]}
+ set npages [send $appname page links total]
+ incr npages
+ send $appname page $npages goto -force
+ send $appname page load [lindex $argv 0]
+}
+exit
diff --git a/examples/xcclock.ps b/examples/xcclock.ps
new file mode 100644
index 0000000..0e4ce7d
--- /dev/null
+++ b/examples/xcclock.ps
@@ -0,0 +1,181 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: xcclock
+%%Creator: Xcircuit v3.1
+%%CreationDate: Fri Jan 16 09:10:05 2004
+%%Pages: 1
+%%BoundingBox: 68 68 514 364
+%%DocumentNeededResources: font Helvetica font Helvetica-Bold
+%%+ font Helvetica-Oblique font Courier
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 3.1
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--1/5/04 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 3.1 0
+%
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg /rotval exch def
+ /just exch def just 384 and 0 gt {/mshow {pop} def} {/mshow {show}
+ def} ifelse just 16 and 0 gt {gsave rotval rotate 0 1 dtransform
+ gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform
+ gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt
+ {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval
+ rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse
+ exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and
+ 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def
+ /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def
+ /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate
+ {exch dup type /stringtype eq {true charpath flattenpath} {dup type
+ /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse}
+ ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just
+ 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5
+ mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4
+ and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg}
+ ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint
+ translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale
+ 1.0 def /kY 0 def {dup type /stringtype eq {mshow} {dup type
+ /arraytype eq {exec} {12 string cvs mshow} ifelse} ifelse} repeat
+ grestore } def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array
+ astore def gsave sce translate 0 0 moveto neg rotate dup abs scale
+ } bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end} bind def
+
+/hlevel 0 def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore} def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def
+/psinsertion {/PSobj save def /showpage {} def bop rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+%%BeginDocumentSetup
+
+
+%%EndDocumentSetup
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+%%PageBoundingBox: 0 0 582 432
+/pgsave save def bop
+<</date (Fri Jan 16 09:10:05 AM EST 2004) (clock format [clock seconds]) pop >> begin
+1.0000 inchscale
+2.6000 setlinewidth 640 416 translate
+
+1.000 0.000 0.000 scb
+mark date (Today is: ) {/Helvetica cf} ctmk 16 0 1.00 -320 -32 label
+sce
+0 1.00 -448 -224 -448 544 720 544 720 -224 4 polygon
+( timedrefresh) {CR} ( }) {CR} ( after 1000 timedrefresh) {CR}
+( refresh;) {CR} ( proc timedrefresh {} {) {/Courier cf} {CR} {CR}
+(Do this in the TCL console:) {/Helvetica-Oblique cf} 14 16 0 1.00 -432 192
+label
+(The XCircuit clock) {/Helvetica-Bold cf} 2 16 0 1.00 -432 496 label
+0 1.00 -336 -64 -336 32 512 32 512 -64 4 polygon
+end pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/filelist.c b/filelist.c
new file mode 100644
index 0000000..62fd93c
--- /dev/null
+++ b/filelist.c
@@ -0,0 +1,893 @@
+/*-------------------------------------------------------------------------*/
+/* filelist.c --- Xcircuit routines for the filelist widget */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <ctype.h> /* For isspace() */
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#include <unistd.h>
+#define direct dirent
+#elif !defined(_MSC_VER)
+#include <sys/dir.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#endif
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#include "Xw/WorkSpace.h"
+#include "Xw/TextEdit.h"
+#include "Xw/Toggle.h"
+#endif
+#endif
+
+#if defined(XC_WIN32) && defined(TCL_WRAPPER)
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*-------------------------------------------------------------------------*/
+/* Local definitions */
+/*-------------------------------------------------------------------------*/
+
+#define INITDIRS 10
+
+/*-------------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*-------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+extern Display *dpy;
+extern XCWindowData *areawin;
+extern ApplicationData appdata;
+extern int *appcolors;
+extern short popups; /* total number of popup windows */
+extern char _STR2[250];
+extern char _STR[150];
+extern Globaldata xobjs;
+
+Pixmap flistpix = (Pixmap)NULL; /* For file-selection widget */
+short flstart, flfiles, flcurrent;
+int flcurwidth;
+
+GC hgc = NULL, sgc = NULL;
+char *cwdname = NULL;
+fileliststruct *files;
+
+#if !defined(XC_WIN32) || defined(TCL_WRAPPER)
+
+/*-------------------------------------------------------------------------*/
+/* Compare two filenames (for use by qsort()) */
+/*-------------------------------------------------------------------------*/
+
+int fcompare(const void *a, const void *b)
+{
+ return (strcmp((char *)(((fileliststruct *)a)->filename),
+ (char *)(((fileliststruct *)b)->filename)));
+}
+
+/*-------------------------------------------------------------------------*/
+/* Routines for drawing a box around the currently selected file */
+/*-------------------------------------------------------------------------*/
+
+void dragfilebox(xcWidget w, caddr_t clientdata, XMotionEvent *event)
+{
+ short filenum;
+ int twidth;
+ Window lwin = xcWindow(w);
+
+ filenum = (event->y - 10 + FILECHARHEIGHT) / FILECHARHEIGHT + flstart - 1;
+ if (filenum < 0) filenum = 0;
+ else if (filenum >= flfiles) filenum = flfiles - 1;
+
+ if (filenum == flcurrent) return;
+
+ if (flcurrent >= 0) /* erase previous box */
+ XDrawRectangle(dpy, lwin, areawin->gc, 5,
+ 10 + FILECHARHEIGHT * (flcurrent
+ - flstart), flcurwidth + 10, FILECHARHEIGHT);
+
+ if (files == NULL) return;
+
+ twidth = XTextWidth(appdata.filefont, files[filenum].filename,
+ strlen(files[filenum].filename));
+ XDrawRectangle(dpy, lwin, areawin->gc, 5,
+ 10 + FILECHARHEIGHT * (filenum
+ - flstart), twidth + 10, FILECHARHEIGHT);
+
+ flcurrent = filenum;
+ flcurwidth = twidth;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Begin tracking the cursor position relative to the files in the list */
+/*-------------------------------------------------------------------------*/
+
+void startfiletrack(xcWidget w, caddr_t clientdata, XCrossingEvent *event)
+{
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(w, PointerMotionMask,
+ (Tk_EventProc *)xctk_dragfilebox, (ClientData)w);
+#else
+ xcAddEventHandler(w, PointerMotionMask, False, (xcEventHandler)dragfilebox, NULL);
+#endif
+
+ XSetFunction(dpy, areawin->gc, GXcopy);
+ XSetForeground(dpy, areawin->gc, AUXCOLOR);
+ XSetLineAttributes(dpy, areawin->gc, 1, LineSolid, CapRound, JoinMiter);
+
+ /* draw initial box */
+
+ flcurrent = -1;
+ dragfilebox(w, NULL, (XMotionEvent *)event);
+
+ XSetFunction(dpy, areawin->gc, GXxor);
+ XSetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Stop tracking the cursor and return to default state */
+/*-------------------------------------------------------------------------*/
+
+void endfiletrack(xcWidget w, caddr_t clientdata, XCrossingEvent *event)
+{
+ Window lwin = xcWindow(w);
+
+ XDrawRectangle(dpy, lwin, areawin->gc, 5,
+ 10 + FILECHARHEIGHT * (flcurrent
+ - flstart), flcurwidth + 10, FILECHARHEIGHT);
+
+#ifdef TCL_WRAPPER
+ Tk_DeleteEventHandler(w, PointerMotionMask,
+ (Tk_EventProc *)xctk_dragfilebox, (ClientData)w);
+#else
+ xcRemoveEventHandler(w, PointerMotionMask, False,
+ (xcEventHandler)dragfilebox, NULL);
+#endif
+
+ /* Restore graphics state values */
+ XSetForeground(dpy, areawin->gc, areawin->gccolor);
+ XSetFunction(dpy, areawin->gc, areawin->gctype);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Read a crash file to find the name of the original file. */
+/*----------------------------------------------------------------------*/
+
+char *getcrashfilename()
+{
+ FILE *fi;
+ char temp[256];
+ char *retstr = NULL, *tpos, *spos;
+ int slen;
+
+ if ((fi = fopen(_STR2, "r")) != NULL) {
+ while (fgets(temp, 255, fi) != NULL) {
+ if ((tpos = strstr(temp, "Title:")) != NULL) {
+ ridnewline(temp);
+ tpos += 7;
+ if ((spos = strrchr(temp, '/')) != NULL)
+ tpos = spos + 1;
+ retstr = (char *)malloc(1 + strlen(tpos));
+ strcpy(retstr, tpos);
+ }
+ else if ((tpos = strstr(temp, "CreationDate:")) != NULL) {
+ ridnewline(temp);
+ tpos += 14;
+ slen = strlen(retstr);
+ retstr = (char *)realloc(retstr, 4 + slen + strlen(tpos));
+ sprintf(retstr + slen, " (%s)", tpos);
+ break;
+ }
+ }
+ fclose(fi);
+ }
+ return retstr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Crash recovery: load the file, and link the tempfile name to it. */
+/*----------------------------------------------------------------------*/
+
+void crashrecover()
+{
+ if (xobjs.tempfile != NULL) {
+ unlink(xobjs.tempfile);
+ free(xobjs.tempfile);
+ }
+ xobjs.tempfile = strdup(_STR2);
+
+ startloadfile(-1);
+}
+
+/*----------------------------------------------------------------------*/
+/* Look for any files left over from a crash. */
+/*----------------------------------------------------------------------*/
+
+void findcrashfiles()
+{
+ DIR *cwd;
+ struct direct *dp;
+ struct stat sbuf;
+#ifndef _MSC_VER
+ uid_t userid = getuid();
+#endif
+ time_t recent = 0;
+ char *snptr;
+ int pid;
+
+ cwd = opendir(xobjs.tempdir);
+ if (cwd == NULL) return; /* No tmp directory, no tmp files! */
+
+ while ((dp = readdir(cwd)) != NULL) {
+ sprintf(_STR, "%s/%s", xobjs.tempdir, dp->d_name);
+ snptr = _STR + strlen(xobjs.tempdir) + 1;
+ if (!strncmp(snptr, "XC", 2)) {
+ char *dotptr = strchr(snptr, '.');
+ pid = -1;
+ if (dotptr && dotptr > snptr + 2) {
+ *dotptr = '\0';
+ if (sscanf(snptr + 2, "%d", &pid) != 1)
+ pid = -1;
+ *dotptr = '.';
+ }
+ if ((!stat(_STR, &sbuf))
+#ifndef _MSC_VER
+ && (sbuf.st_uid == userid)
+#endif
+ ) {
+ if ((recent == 0) || (sbuf.st_ctime > recent)) {
+
+ /* Check if the PID belongs to an active process */
+ /* by sending a CONT signal and checking if */
+ /* there was no error result. */
+
+#ifndef _MSC_VER
+ if (pid != -1)
+ if (kill((pid_t)pid, SIGCONT) == 0)
+ continue;
+#endif
+
+ recent = sbuf.st_ctime;
+ strcpy(_STR2, _STR);
+ }
+ }
+ }
+ }
+ closedir(cwd);
+
+ if (recent > 0) { /* There exists at least one temporary file */
+ /* belonging to this user. Ask to recover */
+ /* the most recent one. */
+
+ /* Warn user of existing tempfile, and ask user if file */
+ /* should be recovered immediately. */
+
+#ifdef TCL_WRAPPER
+ char *cfile = getcrashfilename();
+
+ sprintf(_STR, ".query.title.field configure -text "
+ "\"Recover file \'%s\'?\"",
+ (cfile == NULL) ? "(unknown)" : cfile);
+ Tcl_Eval(xcinterp, _STR);
+ Tcl_Eval(xcinterp, ".query.bbar.okay configure -command "
+ "{filerecover; wm withdraw .query}; wm deiconify .query");
+ if (cfile != NULL) free(cfile);
+#else
+ getfile(NULL, (pointertype)RECOVER, NULL); /* Crash recovery mode */
+#endif
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Match a filename extension against the file filter list. */
+/*----------------------------------------------------------------------*/
+
+#if !defined(XC_WIN32) || defined(TCL_WRAPPER)
+
+Boolean match_filter(char *fname, char *filter)
+{
+ char *dotptr = strrchr(fname, '.');
+ char *filtptr, *endptr;
+ int filtlen, extlen;
+
+ if (filter == NULL) return False;
+ if (dotptr == NULL) return False;
+
+ /* New 11/08: Empty string for filter is a wildcard match, the same */
+ /* as turning off the filter. */
+
+ if (filter[0] == '\0') return True;
+
+ dotptr++;
+ extlen = strlen(dotptr);
+ filtptr = filter;
+
+ while (*filtptr != '\0') {
+ endptr = filtptr;
+ while (*endptr != '\0' && !isspace(*endptr)) endptr++;
+ filtlen = (int)(endptr - filtptr);
+ if (filtlen == extlen)
+ if (!strncmp(dotptr, filtptr, extlen))
+ return True;
+
+ filtptr = endptr;
+ while (*filtptr != '\0' && isspace(*filtptr)) filtptr++;
+ }
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Make a list of the files in the list widget window */
+/*----------------------------------------------------------------------*/
+
+void listfiles(xcWidget w, popupstruct *okaystruct, caddr_t calldata)
+{
+ XGCValues values;
+#ifndef TCL_WRAPPER
+ Arg wargs[2];
+#endif
+ DIR *cwd;
+ char *filter;
+ Window lwin = xcWindow(w);
+ short allocd = INITDIRS;
+ short n = 0;
+ struct direct *dp;
+ struct stat statbuf;
+ int pixheight;
+ Dimension textwidth, textheight;
+
+ filter = okaystruct->filter;
+
+ if (sgc == NULL) {
+ values.foreground = FOREGROUND;
+ values.font = appdata.filefont->fid;
+ values.function = GXcopy;
+ values.graphics_exposures = False;
+ sgc = XCreateGC(dpy, lwin, GCForeground | GCFont | GCFunction
+ | GCGraphicsExposures, &values);
+ }
+
+#ifdef TCL_WRAPPER
+ textwidth = Tk_Width(w);
+ textheight = Tk_Height(w);
+#else
+ XtnSetArg(XtNwidth, &textwidth);
+ XtnSetArg(XtNheight, &textheight);
+ XtGetValues(w, wargs, n);
+#endif
+
+ /* Generate a new flistpix pixmap if currently nonexistent */
+
+ if (!flistpix) {
+
+ /* get list of files in the current directory (cwd) */
+
+ if (files == NULL)
+ files = (fileliststruct *) malloc (INITDIRS * sizeof(fileliststruct));
+ flfiles = 0;
+ if (cwdname == NULL) {
+ cwdname = (char *) malloc (sizeof(char));
+ cwdname[0] = '\0';
+ }
+ if (cwdname[0] == '\0')
+ cwd = opendir(".");
+ else
+ cwd = opendir(cwdname);
+
+ /* If current directory cannot be accessed for some reason, */
+ /* print "Invalid Directory" to the file list window. */
+
+ if (cwd == NULL) {
+ XSetForeground(dpy, sgc, BACKGROUND);
+ XFillRectangle(dpy, lwin, sgc, 0, 0, textwidth, textheight);
+ XSetForeground(dpy, sgc, AUXCOLOR);
+ XDrawString(dpy, lwin, sgc, 10, textheight / 2,
+ "(Invalid Directory)", 19);
+ return;
+ }
+ else {
+
+ /* write the contents of the current directory into the */
+ /* array "filenames[]" (except for current directory ".") */
+
+ while ((dp = readdir(cwd)) != NULL) {
+ /* don't put current directory in list */
+ if (!strcmp(dp->d_name, ".")) continue;
+
+ /* record the type of file */
+
+ sprintf(_STR2, "%s%s", cwdname, dp->d_name);
+ if (stat(_STR2, &statbuf)) continue;
+ if ((statbuf.st_mode & S_IFDIR) != 0) /* is a directory */
+ files[flfiles].filetype = DIRECTORY;
+ else if (match_filter(dp->d_name, filter))
+ files[flfiles].filetype = MATCH;
+ else {
+ if (xobjs.filefilter)
+ continue;
+ else
+ files[flfiles].filetype = NONMATCH;
+ }
+
+ /* save the filename */
+
+ files[flfiles].filename = (char *) malloc ((strlen(dp->d_name) +
+ ((files[flfiles].filetype == DIRECTORY) ? 2 : 1)) * sizeof(char));
+ strcpy(files[flfiles].filename, dp->d_name);
+ if (files[flfiles].filetype == DIRECTORY)
+ strcat(files[flfiles].filename, "/");
+ if (++flfiles == allocd) {
+ allocd += INITDIRS;
+ files = (fileliststruct *) realloc(files,
+ allocd * sizeof(fileliststruct));
+ }
+ }
+ }
+ closedir(cwd);
+
+ /* sort the files[] array into alphabetical order (like "ls") */
+
+ qsort((void *)files, (size_t)flfiles, sizeof(fileliststruct), fcompare);
+
+ pixheight = flfiles * FILECHARHEIGHT + 25;
+ if (pixheight < textheight) pixheight = textheight;
+
+ flistpix = XCreatePixmap(dpy, areawin->window, textwidth, pixheight,
+ DefaultDepthOfScreen(xcScreen(w)));
+
+ /* Write the filenames onto the pixmap */
+
+ XSetForeground(dpy, sgc, BACKGROUND);
+ XFillRectangle(dpy, flistpix, sgc, 0, 0, textwidth, pixheight);
+ XSetForeground(dpy, sgc, FOREGROUND);
+ for (n = 0; n < flfiles; n++) {
+ switch (files[n].filetype) {
+ case DIRECTORY:
+ XSetForeground(dpy, sgc, SELECTCOLOR);
+ break;
+ case MATCH:
+ XSetForeground(dpy, sgc, FILTERCOLOR);
+ break;
+ case NONMATCH:
+ XSetForeground(dpy, sgc, FOREGROUND);
+ break;
+ }
+ XDrawString(dpy, flistpix, sgc, 10, 10 + FILECHARASCENT + n * FILECHARHEIGHT,
+ files[n].filename, strlen(files[n].filename));
+ }
+ }
+
+ /* Copy the pixmap of filenames into the file list window */
+
+ XSetForeground(dpy, sgc, BACKGROUND);
+ XFillRectangle(dpy, lwin, sgc, 0, 0, textwidth, textheight);
+ XCopyArea(dpy, flistpix, lwin, sgc, 0, flstart * FILECHARHEIGHT,
+ textwidth, textheight, 0, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Generate a new pixmap for writing the filelist and set the scrollbar */
+/* size accordingly. */
+/*-------------------------------------------------------------------------*/
+
+void newfilelist(xcWidget w, popupstruct *okaystruct)
+{
+ short n;
+
+#ifdef TCL_WRAPPER
+ int bval;
+ int result;
+ char *cstr = (char *)Tcl_GetVar2(xcinterp, "XCOps", "filter", 0);
+ if (cstr == NULL) {
+ Wprintf("Error: No variable $XCOps(filter) in Tcl!");
+ return;
+ }
+ result = Tcl_GetBoolean(xcinterp, cstr, &bval);
+ if (result != TCL_OK) {
+ Wprintf("Error: Bad variable $XCOps(filter) in Tcl!");
+ return;
+ }
+ xobjs.filefilter = bval;
+#else
+ xcWidget textw = okaystruct->textw;
+#endif
+
+ for (n = 0; n < flfiles; n++)
+ free(files[n].filename);
+ free(files);
+ if (flistpix != (Pixmap)NULL) XFreePixmap(dpy, flistpix);
+ files = NULL;
+ flistpix = (Pixmap)NULL;
+ flstart = 0;
+ listfiles(w, okaystruct, NULL);
+#ifdef TCL_WRAPPER
+ showlscroll(Tk_NameToWindow(xcinterp, ".filelist.listwin.sb", w), NULL, NULL);
+ Tcl_Eval(xcinterp, ".filelist.textent.txt delete 0 end");
+ sprintf(_STR2, ".filelist.textent.txt insert 0 %s", cwdname);
+ Tcl_Eval(xcinterp, _STR2);
+#else
+ showlscroll(XtNameToWidget(xcParent(w), "LScroll"), NULL, NULL);
+ XwTextClearBuffer(textw);
+ XwTextInsert(textw, cwdname);
+ XwTextResize(textw);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+/* Button press handler for file list window */
+/*-------------------------------------------------------------------------*/
+
+void fileselect(xcWidget w, popupstruct *okaystruct, XButtonEvent *event)
+{
+ Window lwin = xcWindow(w);
+ Dimension textwidth, textheight;
+ short filenum;
+ char *tbuf, *ebuf;
+
+#ifdef TCL_WRAPPER
+ textwidth = Tk_Width(w);
+ textheight = Tk_Height(w);
+#else
+ Arg wargs[2];
+ short n = 0;
+ xcWidget textw = okaystruct->textw;
+
+ XtnSetArg(XtNwidth, &textwidth);
+ XtnSetArg(XtNheight, &textheight);
+ XtGetValues(w, wargs, n);
+#endif
+
+ flcurrent = -1;
+
+ if (files == NULL) return; /* shouldn't happen */
+
+ /* third mouse button cancels selection and reverts buffer to cwd name */
+
+ if (event->button == Button3) {
+ newfilelist(w, okaystruct);
+ return;
+ }
+
+ filenum = (event->y - 10 + FILECHARHEIGHT) / FILECHARHEIGHT + flstart - 1;
+ if (filenum < 0) filenum = 0;
+ else if (filenum >= flfiles) filenum = flfiles - 1;
+
+ /* Attempt to enter invalid directory. . . treat like button 3 */
+
+ if (filenum < 0) {
+ newfilelist(w, okaystruct);
+ return;
+ }
+
+ /* check if this file is a directory or not */
+
+ if (strchr(files[filenum].filename, '/') == NULL) {
+
+ /* highlight the entry. . . */
+
+ XSetForeground(dpy, sgc, AUXCOLOR);
+ XDrawString(dpy, flistpix, sgc, 10, 10 + FILECHARASCENT + filenum * FILECHARHEIGHT,
+ files[filenum].filename, strlen(files[filenum].filename));
+ XCopyArea(dpy, flistpix, lwin, sgc, 0, flstart * FILECHARHEIGHT,
+ textwidth, textheight, 0, 0);
+
+ /* . . .and append it to the text field */
+
+#ifdef TCL_WRAPPER
+ Tcl_Eval(xcinterp, ".filelist.textent.txt get");
+ ebuf = (char *)Tcl_GetStringResult(xcinterp);
+ tbuf = (char *)malloc((strlen(ebuf) +
+ strlen(files[filenum].filename) + 6) * sizeof(char));
+#else
+ ebuf = (char *)XwTextCopyBuffer(textw);
+ tbuf = (char *)malloc((XwTextGetLastPos(textw)
+ + strlen(files[filenum].filename) + 5) * sizeof(char));
+#endif
+ strcpy(tbuf, ebuf);
+
+ /* add a comma if there is already text in the destination buffer */
+
+ if (tbuf[0] != '\0') {
+ if (tbuf[strlen(tbuf) - 1] != '/') strcat(tbuf, ",");
+ }
+ else {
+ if (cwdname != NULL) {
+ if (cwdname[0] != '\0') {
+ tbuf = (char *)realloc(tbuf, (strlen(cwdname) +
+ strlen(files[filenum].filename) + 5) * sizeof(char));
+ strcpy(tbuf, cwdname);
+ }
+ }
+ }
+ strcat(tbuf, files[filenum].filename);
+#ifdef TCL_WRAPPER
+ Tcl_Eval(xcinterp, ".filelist.textent.txt delete 0 end");
+ sprintf(_STR2, ".filelist.textent.txt insert 0 %s", tbuf);
+ Tcl_Eval(xcinterp, _STR2);
+#else
+ XwTextClearBuffer(textw);
+ XwTextInsert(textw, tbuf);
+ XwTextResize(textw);
+#endif
+ free(tbuf);
+ }
+ else { /* move to new directory */
+
+ if (!strcmp(files[filenum].filename, "../")) {
+ char *cptr, *sptr = cwdname;
+ if (!strcmp(cwdname, "/")) return; /* no way up from root dir. */
+ while(strstr(sptr, "../") != NULL) sptr += 3;
+ if ((cptr = strrchr(sptr, '/')) != NULL) {
+ *cptr = '\0';
+ if ((cptr = strrchr(sptr, '/')) != NULL) *(cptr + 1) = '\0';
+ else *sptr = '\0';
+ }
+ else {
+ cwdname = (char *)realloc(cwdname, (strlen(cwdname) +
+ 4) * sizeof(char));
+ strcat(cwdname, "../");
+ }
+ }
+ else {
+ cwdname = (char *)realloc(cwdname, (strlen(cwdname) +
+ strlen(files[filenum].filename) + 1) * sizeof(char));
+ strcat(cwdname, files[filenum].filename);
+ }
+ newfilelist(w, okaystruct);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Scrollbar handler for file list widget */
+/*-------------------------------------------------------------------------*/
+
+void showlscroll(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ Window swin = xcWindow(w);
+ Dimension swidth, sheight;
+ int pstart, pheight, finscr;
+
+#ifdef TCL_WRAPPER
+ swidth = Tk_Width(w);
+ sheight = Tk_Height(w);
+#else
+
+ Arg wargs[2];
+ short n = 0;
+
+ XtnSetArg(XtNwidth, &swidth);
+ XtnSetArg(XtNheight, &sheight);
+ XtGetValues(w, wargs, n);
+#endif
+
+ XClearWindow(dpy, swin);
+
+ if (flfiles > 0) { /* no files, no bar */
+
+ finscr = sheight / FILECHARHEIGHT;
+ if (finscr > flfiles) finscr = flfiles;
+
+ pstart = (flstart * sheight) / flfiles;
+ pheight = (finscr * sheight) / flfiles;
+
+ XSetForeground(dpy, sgc, BARCOLOR);
+ XFillRectangle(dpy, swin, sgc, 0, pstart, swidth, pheight);
+ }
+ flcurrent = -1;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Button Motion handler for moving the scrollbar up and down */
+/*-------------------------------------------------------------------------*/
+
+void draglscroll(xcWidget w, popupstruct *okaystruct, XButtonEvent *event)
+{
+ Dimension sheight;
+ int phheight, finscr, flsave = flstart;
+ xcWidget filew = okaystruct->filew;
+
+#ifdef TCL_WRAPPER
+ sheight = Tk_Height(w);
+#else
+ Arg wargs[1];
+ short n = 0;
+
+ XtnSetArg(XtNheight, &sheight);
+ XtGetValues(w, wargs, n);
+#endif
+
+ finscr = sheight / FILECHARHEIGHT;
+ if (finscr > flfiles) finscr = flfiles;
+
+ /* center scrollbar on pointer vertical position */
+
+ phheight = (finscr * sheight) / (flfiles * 2);
+ flstart = (event->y > phheight) ? ((event->y - phheight) * flfiles) / sheight : 0;
+ if (flstart > (flfiles - finscr + 2)) flstart = (flfiles - finscr + 2);
+
+ if (flstart != flsave) {
+ showlscroll(w, NULL, NULL);
+ listfiles(filew, okaystruct, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Set/unset the file filtering function */
+/*----------------------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+void setfilefilter(xcWidget w, popupstruct *okaystruct, caddr_t calldata)
+{
+ xobjs.filefilter = (xobjs.filefilter) ? False : True;
+
+ /* Force regeneration of the file list */
+
+ newfilelist(okaystruct->filew, okaystruct);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Generate the file list window */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void genfilelist(xcWidget parent, popupstruct *okaystruct, Dimension width)
+{
+ xcWidget listarea, lscroll, entertext;
+
+ entertext = okaystruct->textw;
+ listarea = Tk_NameToWindow(xcinterp, ".filelist.listwin.win", parent);
+
+ xcAddEventHandler(listarea, ButtonPressMask, False,
+ (xcEventHandler)fileselect, okaystruct);
+ xcAddEventHandler(listarea, EnterWindowMask, False,
+ (xcEventHandler)startfiletrack, NULL);
+ xcAddEventHandler(listarea, LeaveWindowMask, False,
+ (xcEventHandler)endfiletrack, NULL);
+ flstart = 0;
+ okaystruct->filew = listarea;
+
+ lscroll = Tk_NameToWindow(xcinterp, ".filelist.listwin.sb", parent);
+
+ Tk_CreateEventHandler(lscroll, Button1MotionMask | Button2MotionMask,
+ (Tk_EventProc *)xctk_draglscroll, (ClientData)okaystruct);
+
+ /* force new file list, in case the highlight filter changed */
+
+ if (flistpix != (Pixmap)NULL) XFreePixmap(dpy, flistpix);
+ flistpix = (Pixmap)NULL;
+}
+
+#else
+
+void genfilelist(xcWidget parent, popupstruct *okaystruct, Dimension width)
+{
+ Arg wargs[8];
+ xcWidget listarea, lscroll, entertext, dofilter;
+ short n = 0;
+ int wwidth;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, FILECHARHEIGHT - 10);
+ XtnSetArg(XtNwidth, width - SBARSIZE - 40);
+ XtnSetArg(XtNheight, LISTHEIGHT - FILECHARHEIGHT);
+ XtnSetArg(XtNfont, appdata.filefont);
+
+ entertext = okaystruct->textw;
+
+ listarea = XtCreateManagedWidget("Filelist", XwworkSpaceWidgetClass,
+ parent, wargs, n); n = 0;
+ XtAddCallback(listarea, XtNexpose, (XtCallbackProc)listfiles, okaystruct);
+
+ xcAddEventHandler(listarea, ButtonPressMask, False,
+ (xcEventHandler)fileselect, okaystruct);
+ xcAddEventHandler(listarea, EnterWindowMask, False,
+ (xcEventHandler)startfiletrack, NULL);
+ xcAddEventHandler(listarea, LeaveWindowMask, False,
+ (xcEventHandler)endfiletrack, NULL);
+ flstart = 0;
+ okaystruct->filew = listarea;
+
+ XtnSetArg(XtNx, width - SBARSIZE - 20);
+ XtnSetArg(XtNy, FILECHARHEIGHT - 10);
+ XtnSetArg(XtNwidth, SBARSIZE);
+ XtnSetArg(XtNheight, LISTHEIGHT - FILECHARHEIGHT);
+ XtnSetArg(XtNfont, appdata.xcfont);
+
+ lscroll = XtCreateManagedWidget("LScroll", XwworkSpaceWidgetClass,
+ parent, wargs, n); n = 0;
+
+ XtAddCallback(lscroll, XtNexpose, (XtCallbackProc)showlscroll, NULL);
+ xcAddEventHandler(lscroll, Button1MotionMask | Button2MotionMask,
+ False, (xcEventHandler)draglscroll, okaystruct);
+
+ /* Add a toggle widget to turn file filtering on/off */
+
+ wwidth = XTextWidth(appdata.xcfont, "filter", strlen("filter"));
+ XtnSetArg(XtNx, width - wwidth - 50);
+ XtnSetArg(XtNy, LISTHEIGHT + 10);
+ XtnSetArg(XtNset, xobjs.filefilter);
+ XtnSetArg(XtNsquare, True);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNlabelLocation, XwLEFT);
+ dofilter = XtCreateManagedWidget("Filter", XwtoggleWidgetClass,
+ parent, wargs, n); n = 0;
+ XtAddCallback(dofilter, XtNselect, (XtCallbackProc)setfilefilter, okaystruct);
+ XtAddCallback(dofilter, XtNrelease, (XtCallbackProc)setfilefilter, okaystruct);
+
+ /* force new file list, in case the highlight filter changed */
+
+ if (flistpix != (Pixmap)NULL) XFreePixmap(dpy, flistpix);
+ flistpix = (Pixmap)NULL;
+}
+
+#endif /* TCL_WRAPPER */
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Look for a directory name in a string and update cwdname accordingly */
+/*-------------------------------------------------------------------------*/
+
+int lookdirectory(char *lstring, int nchars)
+{
+ int slen;
+ DIR *cwd = NULL;
+
+ xc_tilde_expand(lstring, nchars);
+ slen = strlen(lstring);
+
+ if (lstring[slen - 1] == '/' || ((cwd=opendir(lstring)) != NULL)) {
+ if (cwd) closedir(cwd);
+ if (lstring[slen - 1] != '/') strcat(lstring, "/");
+ cwdname = (char *)realloc(cwdname, (slen + 2) * sizeof(char));
+ strcpy(cwdname, lstring);
+ return(1);
+ }
+ return(0);
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/files.c b/files.c
new file mode 100644
index 0000000..900b032
--- /dev/null
+++ b/files.c
@@ -0,0 +1,6907 @@
+/*-----------------------------------------------------------------------*/
+/* files.c --- file handling routines for xcircuit */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifndef XC_WIN32
+#include <pwd.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef XC_WIN32
+#include <unistd.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#else
+#include <winsock2.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/TextEdit.h" /* for XwTextCopyBuffer() */
+#endif
+#endif
+
+/*------------------------------------------------------------------------*/
+/* Local includes */
+/*------------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+#ifdef ASG
+extern void Route(XCWindowData *, Boolean);
+extern int ReadSpice(FILE *);
+#endif
+
+/*------------------------------------------------------------------------*/
+/* Useful (local) defines */
+/*------------------------------------------------------------------------*/
+
+#define OUTPUTWIDTH 80 /* maximum text width of output */
+
+#define S_OBLIQUE 13 /* position of Symbol-Oblique in font array */
+
+#define VEPS 1e-3
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+extern char _STR2[250], _STR[150];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern fontinfo *fonts;
+extern short fontcount;
+extern Cursor appcursors[NUM_CURSORS];
+extern XtAppContext app;
+extern Display *dpy;
+extern Window win;
+extern short beeper;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+
+
+/*------------------------------------------------------*/
+/* Global variable definitions */
+/*------------------------------------------------------*/
+
+Boolean load_in_progress = False;
+float version;
+
+/* Structure for remembering what names refer to the same object */
+
+aliasptr aliastop;
+
+/*------------------------------------------------------*/
+/* Simple utility---get rid of newline character */
+/*------------------------------------------------------*/
+
+char *ridnewline(char *sptr)
+{
+ char *tstrp;
+
+ for (tstrp = sptr; *tstrp != '\0' && *tstrp != '\n'; tstrp++);
+ if (*tstrp == '\n') *tstrp = '\0';
+ return tstrp;
+}
+
+/*----------------------------------------------------------------------*/
+/* Check if two filenames are equivalent. This requires separately */
+/* checking any absolute or relative pathnames in front of the filename */
+/* as well as the filename itself. */
+/*----------------------------------------------------------------------*/
+
+#define PATHSEP '/'
+
+int filecmp(char *filename1, char *filename2)
+{
+ char *root1, *root2, *path1, *path2, *end1, *end2;
+ int rval;
+ struct stat statbuf;
+ ino_t inode1;
+ const char *cwdname = ".";
+
+ if (filename1 == NULL || filename2 == NULL) return 1;
+
+ if (!strcmp(filename1, filename2)) return 0; /* exact match */
+
+ root1 = strrchr(filename1, PATHSEP);
+ root2 = strrchr(filename2, PATHSEP);
+
+ if (root1 == NULL) {
+ path1 = (char *)cwdname;
+ end1 = NULL;
+ root1 = filename1;
+ }
+ else {
+ path1 = filename1;
+ end1 = root1;
+ root1++;
+ }
+
+ if (root2 == NULL) {
+ path2 = (char *)cwdname;
+ end2 = NULL;
+ root2 = filename2;
+ }
+ else {
+ path2 = filename2;
+ end2 = root2;
+ root2++;
+ }
+
+ if (strcmp(root1, root2)) return 1; /* root names don't match */
+
+ /* If we got here, one or both filenames specify a directory */
+ /* path, and the directory paths are different strings. */
+ /* However, one may be an absolute path and the other a */
+ /* relative path, so we check the inodes of the paths for */
+ /* equivalence. Note that the file itself is not assumed to */
+ /* exist. */
+
+ rval = 1;
+ if (end1 != NULL) *end1 = '\0';
+ if (stat(path1, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
+ inode1 = statbuf.st_ino;
+ if (end2 != NULL) *end2 = '\0';
+ if (stat(path2, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
+ if (inode1 == statbuf.st_ino)
+ rval = 0;
+ }
+ if (end2 != NULL) *end2 = PATHSEP;
+ }
+ if (end1 != NULL) *end1 = PATHSEP;
+ return rval;
+}
+
+/*--------------------------------------------------------------*/
+/* Make sure that a string (object or parameter name) is a */
+/* valid PostScript name. We do this by converting illegal */
+/* characters to the PostScript \ooo (octal value) form. */
+/* */
+/* This routine does not consider whether the name might be a */
+/* PostScript numeric value. This problem is taken care of by */
+/* having the load/save routines prepend '@' to parameters and */
+/* a technology namespace to object names. */
+/* */
+/* If "need_prefix" is TRUE, then prepend "@" to the result */
+/* string, unless teststring is a numerical parameter name */
+/* (p_...). */
+/*--------------------------------------------------------------*/
+
+char *create_valid_psname(char *teststring, Boolean need_prefix)
+{
+ int i, isize, ssize;
+ static char *optr = NULL;
+ char *sptr, *pptr;
+ Boolean prepend = need_prefix;
+ char illegalchars[] = {'/', '}', '{', ']', '[', ')', '(', '<', '>', ' ', '%'};
+
+ /* Check for illegal characters which have syntactical meaning in */
+ /* PostScript, and the presence of nonprintable characters or */
+ /* whitespace. */
+
+ ssize = strlen(teststring);
+ isize = ssize;
+
+ if (need_prefix && !strncmp(teststring, "p_", 2))
+ prepend = FALSE;
+ else
+ isize++;
+
+ for (sptr = teststring; *sptr != '\0'; sptr++) {
+ if ((!isprint(*sptr)) || isspace(*sptr))
+ isize += 3;
+ else {
+ for (i = 0; i < sizeof(illegalchars); i++) {
+ if (*sptr == illegalchars[i]) {
+ isize += 3;
+ break;
+ }
+ }
+ }
+ }
+ if (isize == ssize) return teststring;
+ isize++;
+
+ if (optr == NULL)
+ optr = (char *)malloc(isize);
+ else
+ optr = (char *)realloc(optr, isize);
+
+ pptr = optr;
+
+ if (prepend) *pptr++ = '@';
+
+ for (sptr = teststring; *sptr != '\0'; sptr++) {
+ if ((!isprint(*sptr)) || isspace(*sptr)) {
+ sprintf(pptr, "\\%03o", *sptr);
+ pptr += 4;
+ }
+ else {
+ for (i = 0; i < sizeof(illegalchars); i++) {
+ if (*sptr == illegalchars[i]) {
+ sprintf(pptr, "\\%03o", *sptr);
+ pptr += 4;
+ break;
+ }
+ }
+ if (i == sizeof(illegalchars))
+ *pptr++ = *sptr;
+ }
+ }
+ *pptr++ = '\0';
+ return optr;
+}
+
+/*------------------------------------------------------*/
+/* Turn a PostScript string with possible backslash */
+/* escapes into a normal character string. */
+/* */
+/* if "spacelegal" is TRUE, we are parsing a PostScript */
+/* string in parentheses () where whitespace is legal. */
+/* If FALSE, we are parsing a PostScript name where */
+/* whitespace is illegal, and any whitespace should be */
+/* considered the end of the name. */
+/* */
+/* "dest" is ASSUMED to be large enough to hold the */
+/* result. "dest" is always equal to or smaller than */
+/* "src" in length. "size" should be the maximum size */
+/* of the string, or 1 less that the allocated memory, */
+/* allowing for a final NULL byte to be added. */
+/* */
+/* The fact that "dest" is always smaller than or equal */
+/* to "src" means that parse_ps_string(a, a, ...) is */
+/* legal. */
+/* */
+/* Return 0 if the result is empty, 1 otherwise. */
+/*------------------------------------------------------*/
+
+int parse_ps_string(char *src, char *dest, int size, Boolean spacelegal, Boolean strip)
+{
+ char *sptr = src;
+ char *tptr = dest;
+ int tmpdig, rval = 0;
+
+ /* Strip leading "@", inserted by XCircuit to */
+ /* prevent conflicts with PostScript reserved */
+ /* keywords or numbers. */
+
+ if (strip && (*sptr == '@')) sptr++;
+
+ for (;; sptr++) {
+ if ((*sptr == '\0') || (isspace(*sptr) && !spacelegal)) {
+ *tptr = '\0';
+ break;
+ }
+ else {
+ if (*sptr == '\\') {
+ sptr++;
+ if (*sptr >= '0' && *sptr < '8') {
+ sscanf(sptr, "%3o", &tmpdig);
+ *tptr++ = (u_char)tmpdig;
+ sptr += 2;
+ }
+ else
+ *tptr++ = *sptr;
+ }
+ else
+ *tptr++ = *sptr;
+ rval = 1;
+ }
+ if ((int)(tptr - dest) > size) {
+ Wprintf("Warning: Name \"%s\" in input exceeded buffer length!\n", src);
+ *tptr = '\0';
+ return rval;
+ }
+ }
+ return rval;
+}
+
+/*------------------------------------------------------*/
+/* Free memory allocated to a label string */
+/*------------------------------------------------------*/
+
+void freelabel(stringpart *string)
+{
+ stringpart *strptr = string, *tmpptr;
+
+ while (strptr != NULL) {
+ if (strptr->type == TEXT_STRING || strptr->type == PARAM_START)
+ free(strptr->data.string);
+ tmpptr = strptr->nextpart;
+ free(strptr);
+ strptr = tmpptr;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Free memory for a single element */
+/*------------------------------------------------------*/
+
+void free_single(genericptr genobj)
+{
+ objinstptr geninst;
+ oparamptr ops, fops;
+
+ if (IS_POLYGON(genobj)) free(((polyptr)(genobj))->points);
+ else if (IS_LABEL(genobj)) freelabel(((labelptr)(genobj))->string);
+ else if (IS_GRAPHIC(genobj)) freegraphic((graphicptr)(genobj));
+ else if (IS_PATH(genobj)) free(((pathptr)(genobj))->plist);
+ else if (IS_OBJINST(genobj)) {
+ geninst = (objinstptr)genobj;
+ ops = geninst->params;
+ while (ops != NULL) {
+ /* Don't try to free data from indirect parameters */
+ /* (That's not true---all data are copied by epsubstitute) */
+ /* if (find_indirect_param(geninst, ops->key) == NULL) { */
+ switch(ops->type) {
+ case XC_STRING:
+ freelabel(ops->parameter.string);
+ break;
+ case XC_EXPR:
+ free(ops->parameter.expr);
+ break;
+ }
+ /* } */
+ free(ops->key);
+ fops = ops;
+ ops = ops->next;
+ free(fops);
+ }
+ }
+ free_all_eparams(genobj);
+}
+
+/*---------------------------------------------------------*/
+/* Reset an object structure by freeing all alloc'd memory */
+/*---------------------------------------------------------*/
+
+void reset(objectptr localdata, short mode)
+{
+ /* short i; (jdk) */
+
+ if (localdata->polygons != NULL || localdata->labels != NULL)
+ destroynets(localdata);
+
+ localdata->valid = False;
+
+ if (localdata->parts > 0) {
+ genericptr *genobj;
+
+ if (mode != SAVE) {
+
+ for (genobj = localdata->plist; genobj < localdata->plist
+ + localdata->parts; genobj++)
+
+ /* (*genobj == NULL) only on library pages */
+ /* where the instances are kept in the library */
+ /* definition, and are only referenced on the page. */
+
+ if (*genobj != NULL) {
+ free_single(*genobj);
+ free(*genobj);
+ }
+ }
+ free(localdata->plist);
+
+ removeparams(localdata);
+
+ initmem(localdata);
+ if (mode == DESTROY)
+ free(localdata->plist);
+ }
+}
+
+/*---------------------------------------------------------*/
+
+void pagereset(short rpage)
+{
+ /* free alloc'd filename */
+
+ if (xobjs.pagelist[rpage]->filename != NULL)
+ free(xobjs.pagelist[rpage]->filename);
+ xobjs.pagelist[rpage]->filename = (char *)NULL;
+
+ if (xobjs.pagelist[rpage]->background.name != NULL)
+ free(xobjs.pagelist[rpage]->background.name);
+ xobjs.pagelist[rpage]->background.name = (char *)NULL;
+
+ clearselects();
+
+ /* New pages pick up their properties from page 0, which can be changed */
+ /* from the .xcircuitrc file on startup (or loaded from a script). */
+ /* Thanks to Norman Werner (norman.werner@student.uni-magdeburg.de) for */
+ /* pointing out this more obvious way of doing the reset, and providing */
+ /* a patch. */
+
+ xobjs.pagelist[rpage]->wirewidth = xobjs.pagelist[0]->wirewidth;
+ xobjs.pagelist[rpage]->orient = xobjs.pagelist[0]->orient;
+ xobjs.pagelist[rpage]->pmode = xobjs.pagelist[0]->pmode;
+ xobjs.pagelist[rpage]->outscale = xobjs.pagelist[0]->outscale;
+ xobjs.pagelist[rpage]->drawingscale.x = xobjs.pagelist[0]->drawingscale.x;
+ xobjs.pagelist[rpage]->drawingscale.y = xobjs.pagelist[0]->drawingscale.y;
+ xobjs.pagelist[rpage]->gridspace = xobjs.pagelist[0]->gridspace;
+ xobjs.pagelist[rpage]->snapspace = xobjs.pagelist[0]->snapspace;
+ xobjs.pagelist[rpage]->coordstyle = xobjs.pagelist[0]->coordstyle;
+ xobjs.pagelist[rpage]->margins = xobjs.pagelist[0]->margins;
+
+ if (xobjs.pagelist[rpage]->coordstyle == CM) {
+ xobjs.pagelist[rpage]->pagesize.x = 595;
+ xobjs.pagelist[rpage]->pagesize.y = 842; /* A4 */
+ }
+ else {
+ xobjs.pagelist[rpage]->pagesize.x = 612; /* letter */
+ xobjs.pagelist[rpage]->pagesize.y = 792;
+ }
+}
+
+/*---------------------------------------------------------*/
+
+void initmem(objectptr localdata)
+{
+ localdata->parts = 0;
+ localdata->plist = (genericptr *)malloc(sizeof(genericptr));
+ localdata->hidden = False;
+ localdata->changes = 0;
+ localdata->params = NULL;
+
+ localdata->viewscale = 0.5;
+
+ /* Object should not reference the window: this needs to be rethunk! */
+ if (areawin != NULL) {
+ localdata->pcorner.x = -areawin->width;
+ localdata->pcorner.y = -areawin->height;
+ }
+ localdata->bbox.width = 0;
+ localdata->bbox.height = 0;
+ localdata->bbox.lowerleft.x = 0;
+ localdata->bbox.lowerleft.y = 0;
+
+ localdata->highlight.netlist = NULL;
+ localdata->highlight.thisinst = NULL;
+ localdata->schemtype = PRIMARY;
+ localdata->symschem = NULL;
+ localdata->netnames = NULL;
+ localdata->polygons = NULL;
+ localdata->labels = NULL;
+ localdata->ports = NULL;
+ localdata->calls = NULL;
+ localdata->valid = False;
+ localdata->traversed = False;
+}
+
+/*--------------------------------------------------------------*/
+/* Exhaustively compare the contents of two objects and return */
+/* true if equivalent, false if not. */
+/*--------------------------------------------------------------*/
+
+Boolean elemcompare(genericptr *compgen, genericptr *gchk)
+{
+ Boolean bres;
+ switch(ELEMENTTYPE(*compgen)) {
+ case(ARC):
+ bres = (TOARC(compgen)->position.x == TOARC(gchk)->position.x &&
+ TOARC(compgen)->position.y == TOARC(gchk)->position.y &&
+ TOARC(compgen)->style == TOARC(gchk)->style &&
+ TOARC(compgen)->width == TOARC(gchk)->width &&
+ abs(TOARC(compgen)->radius) == abs(TOARC(gchk)->radius) &&
+ TOARC(compgen)->yaxis == TOARC(gchk)->yaxis &&
+ TOARC(compgen)->angle1 == TOARC(gchk)->angle1 &&
+ TOARC(compgen)->angle2 == TOARC(gchk)->angle2);
+ break;
+ case(SPLINE):
+ bres = (TOSPLINE(compgen)->style == TOSPLINE(gchk)->style &&
+ TOSPLINE(compgen)->width == TOSPLINE(gchk)->width &&
+ TOSPLINE(compgen)->ctrl[0].x == TOSPLINE(gchk)->ctrl[0].x &&
+ TOSPLINE(compgen)->ctrl[0].y == TOSPLINE(gchk)->ctrl[0].y &&
+ TOSPLINE(compgen)->ctrl[1].x == TOSPLINE(gchk)->ctrl[1].x &&
+ TOSPLINE(compgen)->ctrl[1].y == TOSPLINE(gchk)->ctrl[1].y &&
+ TOSPLINE(compgen)->ctrl[2].x == TOSPLINE(gchk)->ctrl[2].x &&
+ TOSPLINE(compgen)->ctrl[2].y == TOSPLINE(gchk)->ctrl[2].y &&
+ TOSPLINE(compgen)->ctrl[3].x == TOSPLINE(gchk)->ctrl[3].x &&
+ TOSPLINE(compgen)->ctrl[3].y == TOSPLINE(gchk)->ctrl[3].y);
+ break;
+ case(POLYGON): {
+ int i;
+ if (TOPOLY(compgen)->style == TOPOLY(gchk)->style &&
+ TOPOLY(compgen)->width == TOPOLY(gchk)->width &&
+ TOPOLY(compgen)->number == TOPOLY(gchk)->number) {
+ for (i = 0; i < TOPOLY(compgen)->number; i++) {
+ if (TOPOLY(compgen)->points[i].x != TOPOLY(gchk)->points[i].x
+ || TOPOLY(compgen)->points[i].y != TOPOLY(gchk)->points[i].y)
+ break;
+ }
+ bres = (i == TOPOLY(compgen)->number);
+ }
+ else bres = False;
+ }break;
+ }
+ return bres;
+}
+
+/*--------------------------------------------------------------*/
+/* Compare any element with any other element. */
+/*--------------------------------------------------------------*/
+
+Boolean compare_single(genericptr *compgen, genericptr *gchk)
+{
+ Boolean bres = False;
+
+ if ((*gchk)->type == (*compgen)->type) {
+ switch(ELEMENTTYPE(*compgen)) {
+ case(OBJINST):{
+ objinst *newobj = TOOBJINST(compgen);
+ objinst *oldobj = TOOBJINST(gchk);
+ bres = (newobj->position.x == oldobj->position.x &&
+ newobj->position.y == oldobj->position.y &&
+ newobj->rotation == oldobj->rotation &&
+ newobj->scale == oldobj->scale &&
+ newobj->style == oldobj->style &&
+ newobj->thisobject == oldobj->thisobject);
+ } break;
+ case(LABEL):
+ bres = (TOLABEL(compgen)->position.x == TOLABEL(gchk)->position.x &&
+ TOLABEL(compgen)->position.y == TOLABEL(gchk)->position.y &&
+ TOLABEL(compgen)->rotation == TOLABEL(gchk)->rotation &&
+ TOLABEL(compgen)->scale == TOLABEL(gchk)->scale &&
+ TOLABEL(compgen)->justify == TOLABEL(gchk)->justify &&
+ TOLABEL(compgen)->pin == TOLABEL(gchk)->pin &&
+ !stringcomp(TOLABEL(compgen)->string, TOLABEL(gchk)->string));
+ break;
+ case(PATH): /* elements *must* be in same order for a path */
+ bres = (TOPATH(compgen)->parts == TOPATH(gchk)->parts &&
+ TOPATH(compgen)->style == TOPATH(gchk)->style &&
+ TOPATH(compgen)->width == TOPATH(gchk)->width);
+ if (bres) {
+ genericptr *pathchk, *gpath;
+ for (pathchk = TOPATH(compgen)->plist, gpath =
+ TOPATH(gchk)->plist; pathchk < TOPATH(compgen)->plist
+ + TOPATH(compgen)->parts; pathchk++, gpath++) {
+ if (!elemcompare(pathchk, gpath)) bres = False;
+ }
+ }
+ break;
+ case(ARC): case(SPLINE): case(POLYGON):
+ bres = elemcompare(compgen, gchk);
+ break;
+ }
+ }
+ return bres;
+}
+
+/*--------------------------------------------------------------------*/
+
+short objcompare(objectptr obja, objectptr objb)
+{
+ genericptr *compgen, *glist, *gchk, *remg;
+ short csize;
+ Boolean bres;
+
+ /* quick check on equivalence of number of objects */
+
+ if (obja->parts != objb->parts) return False;
+
+ /* check equivalence of parameters. Parameters need not be in any */
+ /* order; they must only match by key and value. */
+
+ if (obja->params == NULL && objb->params != NULL) return False;
+ else if (obja->params != NULL && objb->params == NULL) return False;
+ else if (obja->params != NULL || objb->params != NULL) {
+ oparamptr opsa, opsb;
+ for (opsa = obja->params; opsa != NULL; opsa = opsa->next) {
+ opsb = match_param(objb, opsa->key);
+ if (opsb == NULL) return False;
+ else if (opsa->type != opsb->type) return False;
+ switch (opsa->type) {
+ case XC_STRING:
+ if (stringcomp(opsa->parameter.string, opsb->parameter.string))
+ return False;
+ break;
+ case XC_EXPR:
+ if (strcmp(opsa->parameter.expr, opsb->parameter.expr))
+ return False;
+ break;
+ case XC_INT: case XC_FLOAT:
+ if (opsa->parameter.ivalue != opsb->parameter.ivalue)
+ return False;
+ break;
+ }
+ }
+ }
+
+ /* For the exhaustive check we must match component for component. */
+ /* Best not to assume that elements are in same order for both. */
+
+ csize = obja->parts;
+
+ glist = (genericptr *)malloc(csize * sizeof(genericptr));
+ for (compgen = objb->plist; compgen < objb->plist + csize; compgen++)
+ (*(glist + (int)(compgen - objb->plist))) = *compgen;
+ for (compgen = obja->plist; compgen < obja->plist + obja->parts;
+ compgen++) {
+ bres = False;
+ for (gchk = glist; gchk < glist + csize; gchk++) {
+ if ((*compgen)->color == (*gchk)->color)
+ bres = compare_single(compgen, gchk);
+ if (bres) {
+ csize--;
+ for (remg = gchk; remg < glist + csize; remg++)
+ *remg = *(remg + 1);
+ break;
+ }
+ }
+ }
+ free(glist);
+ if (csize != 0) return False;
+
+ /* Both objects cannot attempt to set an associated schematic/symbol to */
+ /* separate objects, although it is okay for one to make the association */
+ /* and the other not to. */
+
+ if (obja->symschem != NULL && objb->symschem != NULL)
+ if (obja->symschem != objb->symschem)
+ return False;
+
+ return(True);
+}
+
+/*------------------------*/
+/* scale renormalization */
+/*------------------------*/
+
+float getpsscale(float value, short page)
+{
+ if (xobjs.pagelist[page]->coordstyle != CM)
+ return (value * INCHSCALE);
+ else
+ return (value * CMSCALE);
+}
+
+/*---------------------------------------------------------------*/
+/* Keep track of columns of output and split lines when too long */
+/*---------------------------------------------------------------*/
+
+void dostcount(FILE *ps, short *count, short addlength)
+{
+ *count += addlength;
+ if (*count > OUTPUTWIDTH) {
+ *count = addlength;
+ fprintf(ps, "\n");
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Write a numerical value as a string to _STR, making a parameter */
+/* substitution if appropriate. */
+/* Return 1 if a parameter substitution was made, 0 if not. */
+/*----------------------------------------------------------------------*/
+
+Boolean varpcheck(FILE *ps, short value, objectptr localdata, int pointno,
+ short *stptr, genericptr thiselem, u_char which)
+{
+ oparamptr ops;
+ eparamptr epp;
+ Boolean done = False;
+
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ if ((epp->pdata.pointno != -1) && (epp->pdata.pointno != pointno)) continue;
+ ops = match_param(localdata, epp->key);
+ if (ops != NULL && (ops->which == which)) {
+ sprintf(_STR, "%s ", epp->key);
+ done = True;
+ break;
+ }
+ }
+
+ if (!done) {
+ if (pointno == -1) return done;
+ sprintf(_STR, "%d ", (int)value);
+ }
+ else if ((epp->pdata.pointno == -1) && (pointno >= 0)) {
+ sprintf(_STR, "%d ", (int)value - ops->parameter.ivalue);
+ }
+
+ dostcount (ps, stptr, strlen(_STR));
+ fputs(_STR, ps);
+ return done;
+}
+
+/*----------------------------------------------------------------------*/
+/* like varpcheck(), but without pointnumber */
+/*----------------------------------------------------------------------*/
+
+void varcheck(FILE *ps, short value, objectptr localdata,
+ short *stptr, genericptr thiselem, u_char which)
+{
+ varpcheck(ps, value, localdata, 0, stptr, thiselem, which);
+}
+
+/*----------------------------------------------------------------------*/
+/* like varcheck(), but for floating-point values */
+/*----------------------------------------------------------------------*/
+
+void varfcheck(FILE *ps, float value, objectptr localdata, short *stptr,
+ genericptr thiselem, u_char which)
+{
+ oparamptr ops;
+ eparamptr epp;
+ Boolean done = False;
+
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(localdata, epp->key);
+ if (ops != NULL && (ops->which == which)) {
+ sprintf(_STR, "%s ", epp->key);
+ done = True;
+ break;
+ }
+ }
+
+ if (!done)
+ sprintf(_STR, "%3.3f ", value);
+
+ dostcount (ps, stptr, strlen(_STR));
+ fputs(_STR, ps);
+}
+
+/*----------------------------------------------------------------------*/
+/* Like varpcheck(), for path types only. */
+/*----------------------------------------------------------------------*/
+
+Boolean varpathcheck(FILE *ps, short value, objectptr localdata, int pointno,
+ short *stptr, genericptr *thiselem, pathptr thispath, u_char which)
+{
+ oparamptr ops;
+ eparamptr epp;
+ Boolean done = False;
+
+ for (epp = thispath->passed; epp != NULL; epp = epp->next) {
+ if ((epp->pdata.pathpt[0] != -1) && (epp->pdata.pathpt[1] != pointno)) continue;
+ if ((epp->pdata.pathpt[0] != -1) && (epp->pdata.pathpt[0] !=
+ (short)(thiselem - thispath->plist))) continue;
+ ops = match_param(localdata, epp->key);
+ if (ops != NULL && (ops->which == which)) {
+ sprintf(_STR, "%s ", epp->key);
+ done = True;
+ break;
+ }
+ }
+
+ if (!done) {
+ if (pointno == -1) return done;
+ sprintf(_STR, "%d ", (int)value);
+ }
+ else if ((epp->pdata.pathpt[0] == -1) && (pointno >= 0)) {
+ sprintf(_STR, "%d ", (int)value - ops->parameter.ivalue);
+ }
+ dostcount (ps, stptr, strlen(_STR));
+ fputs(_STR, ps);
+ return done;
+}
+
+/* Structure used to hold data specific to each load mode. See */
+/* xcircuit.h for the list of load modes (enum loadmodes) */
+
+typedef struct _loaddata {
+ void (*func)(); /* Routine to run to load the file */
+ char *prompt; /* Substring name of action, for prompting */
+ char *filext; /* Default extention of file to load */
+} loaddata;
+
+/*-------------------------------------------------------*/
+/* Load a PostScript or Python (interpreter script) file */
+/*-------------------------------------------------------*/
+
+void getfile(xcWidget button, pointertype mode, caddr_t nulldata)
+{
+ static loaddata loadmodes[LOAD_MODES] = {
+ {normalloadfile, "load", "ps"}, /* mode NORMAL */
+ {importfile, "import", "ps"}, /* mode IMPORT */
+ {loadbackground, "render", "ps"}, /* mode PSBKGROUND */
+#ifdef HAVE_PYTHON
+ {execscript, "execute", "py"},
+#else
+ {execscript, "execute", ""}, /* mode SCRIPT */
+#endif
+ {crashrecover, "recover", "ps"}, /* mode RECOVER */
+#ifdef ASG
+ {importspice, "import", "spice"}, /* mode IMPORTSPICE */
+#endif
+ };
+
+ buttonsave *savebutton = NULL;
+ char *promptstr = NULL;
+ /* char strext[10]; (jdk) */
+ int idx = (int)mode;
+
+ if (is_page(topobject) == -1) {
+ Wprintf("Can only read file into top-level page!");
+ return;
+ }
+ else if (idx >= LOAD_MODES) {
+ Wprintf("Unknown mode passed to routine getfile()\n");
+ return;
+ }
+#ifndef TCL_WRAPPER
+ savebutton = getgeneric(button, getfile, (void *)mode);
+#endif
+ if (idx == RECOVER) {
+ char *cfile = getcrashfilename();
+ promptstr = (char *)malloc(18 + ((cfile == NULL) ? 9 : strlen(cfile)));
+ sprintf(promptstr, "Recover file \'%s\'?", (cfile == NULL) ? "(unknown)" : cfile);
+ popupprompt(button, promptstr, NULL, loadmodes[idx].func, savebutton, NULL);
+ if (cfile) free(cfile);
+ }
+ else {
+ promptstr = (char *)malloc(18 + strlen(loadmodes[idx].prompt));
+ sprintf(promptstr, "Select file to %s:", loadmodes[idx].prompt);
+ popupprompt(button, promptstr, "\0", loadmodes[idx].func,
+ savebutton, loadmodes[idx].filext);
+ }
+ free(promptstr);
+}
+
+/*--------------------------------------------------------------*/
+/* Tilde ('~') expansion in file name. Assumes that filename */
+/* is a static character array of size "nchars". */
+/*--------------------------------------------------------------*/
+
+Boolean xc_tilde_expand(char *filename, int nchars)
+{
+#ifndef _MSC_VER
+ struct passwd *passwd;
+ char *username = NULL, *expanded, *sptr;
+
+ if (*filename == '~') {
+ sptr = filename + 1;
+ if (*sptr == '/' || *sptr == ' ' || *sptr == '\0')
+ username = getenv("HOME");
+ else {
+ for (; *sptr != '/' && *sptr != '\0'; sptr++);
+ if (*sptr == '\0') *(sptr + 1) = '\0';
+ *sptr = '\0';
+
+ passwd = getpwnam(filename + 1);
+ if (passwd != NULL)
+ username = passwd->pw_dir;
+
+ *sptr = '/';
+ }
+ if (username != NULL) {
+ expanded = (char *)malloc(strlen(username) +
+ strlen(filename));
+ strcpy(expanded, username);
+ strcat(expanded, sptr);
+ strncpy(filename, expanded, nchars);
+ free(expanded);
+ }
+ return True;
+ }
+ return False;
+#else
+ return False;
+#endif
+}
+
+/*--------------------------------------------------------------*/
+/* Variable ('$') expansion in file name */
+/*--------------------------------------------------------------*/
+
+Boolean xc_variable_expand(char *filename, int nchars)
+{
+ char *expanded, *sptr, tmpchar, *varpos, *varsub;
+
+ if ((varpos = strchr(filename, '$')) != NULL) {
+ for (sptr = varpos; *sptr != '/' && *sptr != '\0'; sptr++);
+ if (*sptr == '\0') *(sptr + 1) = '\0';
+ tmpchar = *sptr;
+ *sptr = '\0';
+
+#ifdef TCL_WRAPPER
+ /* Interpret as a Tcl variable */
+ varsub = (char *)Tcl_GetVar(xcinterp, varpos + 1, TCL_NAMESPACE_ONLY);
+#else
+ /* Interpret as an environment variable */
+ varsub = (char *)getenv((const char *)(varpos + 1));
+#endif
+
+ if (varsub != NULL) {
+
+ *varpos = '\0';
+ expanded = (char *)malloc(strlen(varsub) + strlen(filename) +
+ strlen(sptr + 1) + 2);
+ strcpy(expanded, filename);
+ strcat(expanded, varsub);
+ *sptr = tmpchar;
+ strcat(expanded, sptr);
+ strncpy(filename, expanded, nchars);
+ free(expanded);
+ }
+ else
+ *sptr = tmpchar;
+ return True;
+ }
+ return False;
+}
+
+/*--------------------------------------------------------------*/
+/* Attempt to find a file and open it. */
+/*--------------------------------------------------------------*/
+
+FILE *fileopen(char *filename, char *suffix, char *name_return, int nchars)
+{
+ FILE *file = NULL;
+ char inname[250], expname[250], *sptr, *cptr, *iptr, *froot;
+ int slen;
+
+ sscanf(filename, "%249s", expname);
+ xc_tilde_expand(expname, 249);
+ while (xc_variable_expand(expname, 249));
+
+ sptr = xobjs.filesearchpath;
+ while (1) {
+ if ((xobjs.filesearchpath == NULL) || (expname[0] == '/')) {
+ strcpy(inname, expname);
+ iptr = inname;
+ }
+ else {
+ strcpy(inname, sptr);
+ cptr = strchr(sptr, ':');
+ slen = (cptr == NULL) ? strlen(sptr) : (int)(cptr - sptr);
+ sptr += (slen + ((cptr == NULL) ? 0 : 1));
+ iptr = inname + slen;
+ if (*(iptr - 1) != '/') strcpy(iptr++, "/");
+ strcpy(iptr, expname);
+ }
+
+ /* Attempt to open the filename with a suffix */
+
+ if ((froot = strrchr(iptr, '/')) == NULL) froot = iptr;
+ if (strrchr(froot, '.') == NULL) {
+ if (suffix) {
+ if (suffix[0] != '.')
+ strncat(inname, ".", 249);
+ strncat(inname, suffix, 249);
+ }
+ file = fopen(inname, "r");
+ }
+
+ /* Attempt to open the filename as given, without a suffix */
+
+ if (file == NULL) {
+ strcpy(iptr, expname);
+ file = fopen(inname, "r");
+ }
+
+ if (file != NULL) break;
+ else if (sptr == NULL) break;
+ else if (*sptr == '\0') break;
+ }
+
+ if (name_return) strncpy(name_return, inname, nchars);
+ return file;
+}
+
+/*---------------------------------------------------------*/
+
+Boolean nextfilename() /* extract next filename from _STR2 into _STR */
+{
+ char *cptr, *slptr;
+
+ sprintf(_STR, "%.149s", _STR2);
+ if ((cptr = strrchr(_STR2, ',')) != NULL) {
+ slptr = strrchr(_STR, '/');
+ if (slptr == NULL || ((slptr - _STR) > (cptr - _STR2))) slptr = _STR - 1;
+ sprintf(slptr + 1, "%s", cptr + 1);
+ *cptr = '\0';
+ return True;
+ }
+ else return False;
+}
+
+/*---------------------------------------------------------*/
+
+void loadfontlib()
+{
+ loadlibrary(FONTLIB);
+}
+
+/*------------------------------------------------------*/
+/* Handle library loading and refresh current page if */
+/* it is a library page that just changed. */
+/*------------------------------------------------------*/
+
+void loadglib(Boolean lflag, short ilib, short tlib)
+{
+ while (nextfilename()) {
+ if (lflag)
+ lflag = False;
+ else
+ ilib = createlibrary(False);
+ loadlibrary(ilib);
+ /* if (ilib == tlib) zoomview(NULL, NULL, NULL); */
+ }
+ if (lflag)
+ lflag = False;
+ else
+ ilib = createlibrary(False);
+ loadlibrary(ilib);
+ /* if (ilib == tlib) zoomview(NULL, NULL, NULL); */
+}
+
+/*------------------------------------------------------*/
+/* Load new library: Create new library page and load */
+/* to it. */
+/*------------------------------------------------------*/
+
+void loadulib()
+{
+ loadglib(False, (short)0, (short)is_library(topobject) + LIBRARY);
+}
+
+/*-----------------------------------------------------------*/
+/* Add to library: If on library page, add to that library. */
+/* Otherwise, create a new library page and load to it. */
+/*-----------------------------------------------------------*/
+
+void loadblib()
+{
+ short ilib, tlib;
+ Boolean lflag = True;
+
+ /* Flag whether current page is a library page or not */
+
+ if ((tlib = is_library(topobject)) < 0) {
+ ilib = LIBRARY;
+ lflag = False;
+ }
+ else
+ ilib = tlib + LIBRARY;
+
+ loadglib(lflag, ilib, tlib + LIBRARY);
+}
+
+/*---------------------------------------------------------*/
+
+void getlib(xcWidget button, caddr_t clientdata, caddr_t nulldata)
+{
+ buttonsave *savebutton;
+#ifndef TCL_WRAPPER
+ savebutton = getgeneric(button, getlib, NULL);
+#endif
+ popupprompt(button, "Enter library to load:", "\0", loadblib, savebutton,
+ "lps");
+}
+
+/*---------------------------------------------------------*/
+
+void getuserlib(xcWidget button, caddr_t clientdata, caddr_t nulldata)
+{
+ buttonsave *savebutton;
+
+#ifndef TCL_WRAPPER
+ savebutton = getgeneric(button, getuserlib, NULL);
+#endif
+ popupprompt(button, "Enter library to load:", "\0", loadulib, savebutton,
+ "lps");
+}
+
+/*------------------------------------------------------*/
+/* Add a new name to the list of aliases for an object */
+/*------------------------------------------------------*/
+
+Boolean addalias(objectptr thisobj, char *newname)
+{
+ aliasptr aref;
+ slistptr sref;
+ /* Boolean retval = False; (jdk) */
+ char *origname = thisobj->name;
+
+ for (aref = aliastop; aref != NULL; aref = aref->next)
+ if (aref->baseobj == thisobj)
+ break;
+
+ /* An equivalence, not an alias */
+ if (!strcmp(origname, newname)) return True;
+
+ if (aref == NULL) { /* entry does not exist; add new baseobj */
+ aref = (aliasptr)malloc(sizeof(alias));
+ aref->baseobj = thisobj;
+ aref->aliases = NULL;
+ aref->next = aliastop;
+ aliastop = aref;
+ }
+
+ for (sref = aref->aliases; sref != NULL; sref = sref->next)
+ if (!strcmp(sref->alias, newname))
+ break;
+
+ if (sref == NULL) { /* needs new entry */
+ sref = (slistptr)malloc(sizeof(stringlist));
+ sref->alias = strdup(newname);
+ sref->next = aref->aliases;
+ aref->aliases = sref;
+ return False;
+ }
+ else return True; /* alias already exists! */
+}
+
+/*------------------------------------------------------*/
+/* Remove all object name aliases */
+/*------------------------------------------------------*/
+
+void cleanupaliases(short mode)
+{
+ aliasptr aref;
+ slistptr sref;
+ objectptr baseobj;
+ char *sptr; /* *basename, (jdk) */
+ int i, j;
+
+ if (aliastop == NULL) return;
+
+ for (aref = aliastop; aref != NULL; aref = aref->next) {
+ baseobj = aref->baseobj;
+ for (sref = aref->aliases; sref != NULL; sref = sref->next)
+ free(sref->alias);
+ }
+
+ for (; (aref = aliastop->next); aliastop = aref)
+ free(aliastop);
+ free(aliastop);
+ aliastop = NULL;
+
+ /* Get rid of propagating underscores in names */
+
+ for (i = 0; i < ((mode == FONTLIB) ? 1 : xobjs.numlibs); i++) {
+ for (j = 0; j < ((mode == FONTLIB) ? xobjs.fontlib.number :
+ xobjs.userlibs[i].number); j++) {
+ baseobj = (mode == FONTLIB) ? *(xobjs.fontlib.library + j) :
+ *(xobjs.userlibs[i].library + j);
+
+ sptr = baseobj->name;
+ while (*sptr == '_') sptr++;
+ /* need memmove to avoid overwriting? */
+ memmove((void *)baseobj->name, (const void *)sptr, strlen(sptr) + 1);
+ checkname(baseobj);
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Open a library file by name and return a pointer to */
+/* the file structure, or NULL if an error occurred. */
+/*------------------------------------------------------*/
+
+FILE *libopen(char *libname, short mode, char *name_return, int nchars)
+{
+ FILE *file = NULL;
+ char inname[150], expname[150], *sptr, *cptr, *iptr;
+ int slen;
+ char *suffix = (mode == FONTENCODING) ? ".xfe" : ".lps";
+
+ sscanf(libname, "%149s", expname);
+ xc_tilde_expand(expname, 149);
+ while(xc_variable_expand(expname, 149));
+
+ sptr = xobjs.libsearchpath;
+ while (1) {
+
+ if ((xobjs.libsearchpath == NULL) || (expname[0] == '/')) {
+ strcpy(inname, expname);
+ iptr = inname;
+ }
+ else {
+ strcpy(inname, sptr);
+ cptr = strchr(sptr, ':');
+ slen = (cptr == NULL) ? strlen(sptr) : (int)(cptr - sptr);
+ sptr += (slen + ((cptr == NULL) ? 0 : 1));
+ iptr = inname + slen;
+ if (*(iptr - 1) != '/') strcpy(iptr++, "/");
+ strcpy(iptr, expname);
+ }
+
+ /* Try to open the filename with a suffix if it doesn't have one */
+
+ if (strrchr(iptr, '.') == NULL) {
+ strncat(inname, suffix, 149);
+ file = fopen(inname, "r");
+ }
+
+ /* Try to open the filename as given, without a suffix */
+
+ if (file == NULL) {
+ strcpy(iptr, expname);
+ file = fopen(inname, "r");
+ }
+
+ if (file != NULL) break;
+ else if (sptr == NULL) break;
+ else if (*sptr == '\0') break;
+ }
+
+ if ((file == NULL) && (xobjs.libsearchpath == NULL)) {
+
+ /* if not found in cwd and there is no library search */
+ /* path, look for environment variable "XCIRCUIT_LIB_DIR" */
+ /* defined (Thanks to Ali Moini, U. Adelaide, S. Australia) */
+
+ char *tmp_s = getenv((const char *)"XCIRCUIT_LIB_DIR");
+
+ if (tmp_s != NULL) {
+ sprintf(inname, "%s/%s", tmp_s, expname);
+ file = fopen(inname, "r");
+ if (file == NULL) {
+ sprintf(inname, "%s/%s%s", tmp_s, expname, suffix);
+ file = fopen(inname, "r");
+ }
+ }
+
+ /* last resort: hard-coded directory BUILTINS_DIR */
+
+ if (file == NULL) {
+ sprintf(inname, "%s/%s", BUILTINS_DIR, expname);
+ file = fopen(inname, "r");
+ if (file == NULL) {
+ sprintf(inname, "%s/%s%s", BUILTINS_DIR, expname, suffix);
+ file = fopen(inname, "r");
+ }
+ }
+ }
+
+ if (name_return) strncpy(name_return, inname, nchars);
+ return file;
+}
+
+/*--------------------------------------------------------------*/
+/* Add a record to the instlist list of the library indexed by */
+/* mode, create a new instance, and add it to the record. */
+/* */
+/* objname is the name of the library object to be instanced, */
+/* and buffer is the line containing the instance parameters */
+/* of the new instance, optionally preceded by scale and */
+/* rotation values. */
+/* */
+/*--------------------------------------------------------------*/
+
+objinstptr new_library_instance(short mode, char *objname, char *buffer,
+ TechPtr defaulttech)
+{
+ char *lineptr;
+ objectptr libobj, localdata;
+ objinstptr newobjinst;
+ int j;
+ char *nsptr, *fullname = objname;
+
+ localdata = xobjs.libtop[mode + LIBRARY]->thisobject;
+
+ /* For (older) libraries that do not use technologies, give the */
+ /* object a technology name in the form <library>::<object> */
+
+ if ((nsptr = strstr(objname, "::")) == NULL) {
+ int deftechlen = (defaulttech == NULL) ? 0 : strlen(defaulttech->technology);
+ fullname = (char *)malloc(deftechlen + strlen(objname) + 3);
+ if (defaulttech == NULL)
+ sprintf(fullname, "::%s", objname);
+ else
+ sprintf(fullname, "%s::%s", defaulttech->technology, objname);
+ }
+
+ for (j = 0; j < xobjs.userlibs[mode].number; j++) {
+ libobj = *(xobjs.userlibs[mode].library + j);
+ if (!strcmp(fullname, libobj->name)) {
+ newobjinst = addtoinstlist(mode, libobj, TRUE);
+
+ lineptr = buffer;
+ while (isspace(*lineptr)) lineptr++;
+ if (*lineptr != '<') {
+ /* May declare instanced scale and rotation first */
+ lineptr = varfscan(localdata, lineptr, &newobjinst->scale,
+ (genericptr)newobjinst, P_SCALE);
+ lineptr = varscan(localdata, lineptr, &newobjinst->rotation,
+ (genericptr)newobjinst, P_ROTATION);
+ }
+ readparams(NULL, newobjinst, libobj, lineptr);
+ if (fullname != objname) free(fullname);
+ return newobjinst;
+ }
+ }
+ if (fullname != objname) free(fullname);
+ return NULL; /* error finding the library object */
+}
+
+/*------------------------------------------------------*/
+/* Import a single object from a library file. "mode" */
+/* is the number of the library into which the object */
+/* will be placed. This function allows new libraries */
+/* to be generated by "cutting and pasting" from */
+/* existing libraries. It also allows better library */
+/* management when the number of objects becomes very */
+/* large, such as when using "diplib" (7400 series */
+/* chips, created from the PCB library). */
+/*------------------------------------------------------*/
+
+void importfromlibrary(short mode, char *libname, char *objname)
+{
+ FILE *ps;
+ char temp[150], keyword[100];
+ char inname[150], *tptr;
+ objectptr *newobject;
+ objlistptr redef;
+ float saveversion;
+ Boolean dependencies = False;
+ TechPtr nsptr = NULL;
+
+ ps = libopen(libname, mode, inname, 149);
+ if (ps == NULL) {
+ Fprintf(stderr, "Cannot open library %s for import.\n", libname);
+ return;
+ }
+
+ version = 2.0; /* Assume version is 2.0 unless found in header */
+
+ for(;;) {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error in library.");
+ goto endload;
+ }
+ else if (temp[0] == '/') {
+ int s = 1;
+ if (temp[1] == '@') s = 2;
+ sscanf(&temp[s], "%s", keyword);
+ if (!strcmp(keyword, objname))
+ break;
+ }
+ else if (*temp == '%') {
+ char *tptr = temp + 1;
+ while (isspace(*tptr)) tptr++;
+ if (!strncmp(tptr, "Version:", 8)) {
+ float tmpv;
+ tptr += 9;
+ if (sscanf(tptr, "%f", &tmpv) > 0) version = tmpv;
+ }
+ else if (!strncmp(tptr, "Library", 7)) {
+ char *techname = strstr(tptr, ":");
+ if (techname != NULL) {
+ techname++; /* skip over colon */
+ while(isspace(*techname)) techname++;
+ ridnewline(techname); /* Remove newline character */
+ if ((tptr = strrchr(techname, '/')) != NULL)
+ techname = tptr + 1;
+ if ((tptr = strrchr(techname, '.')) != NULL)
+ if (!strncmp(tptr, ".lps", 4))
+ *tptr = '\0';
+ nsptr = AddNewTechnology(techname, inname);
+ if (nsptr) {
+ // Set the IMPORTED flag, to help prevent overwriting
+ // the techfile with a truncated version of it, unless
+ // the filename of the techfile has been changed, in
+ // which case the technology should be considered to
+ // stand on its own, and is not considered a partially
+ // complete imported version of the original techfile.
+
+ if (!strcmp(inname, nsptr->filename))
+ nsptr->flags |= TECH_IMPORTED;
+ }
+ }
+ }
+ else if (!strncmp(tptr, "Depend", 6)) {
+ dependencies = TRUE;
+ tptr += 7;
+ sscanf(tptr, "%s", keyword);
+ if (!strcmp(keyword, objname)) {
+ /* Load dependencies */
+ while (1) {
+ tptr += strlen(keyword) + 1;
+ if (sscanf(tptr, "%s", keyword) != 1) break;
+ if (keyword[0] == '\n' || keyword[0] == '\0') break;
+ /* Recursive import */
+ saveversion = version;
+ importfromlibrary(mode, libname, keyword);
+ version = saveversion;
+ }
+ }
+ }
+ }
+ }
+
+ if ((version < 3.2) && (!dependencies)) {
+ Fprintf(stderr, "Library does not have dependency list and cannot "
+ "be trusted.\nLoad and rewrite library to update.\n");
+ goto endload;
+ }
+
+ newobject = new_library_object(mode, keyword, &redef, nsptr);
+
+ load_in_progress = True;
+ if (objectread(ps, *newobject, 0, 0, mode, temp, DEFAULTCOLOR, nsptr) == False) {
+
+ if (library_object_unique(mode, *newobject, redef)) {
+ add_object_to_library(mode, *newobject);
+ cleanupaliases(mode);
+
+ /* pull in any instances of this object that */
+ /* are defined in the library */
+
+ for(;;) {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error in library.");
+ goto endload;
+ }
+ else if (!strncmp(temp, "% EndLib", 8))
+ break;
+ else if (strstr(temp, "libinst") != NULL) {
+ if ((tptr = strstr(temp, objname)) != NULL) {
+ if (*(tptr - 1) == '/') {
+ char *eptr = tptr;
+ while (!isspace(*++eptr));
+ *eptr = '\0';
+ new_library_instance(mode - LIBRARY, tptr, temp, nsptr);
+ }
+ }
+ }
+ }
+
+ if (mode != FONTLIB) {
+ composelib(mode);
+ centerview(xobjs.libtop[mode]);
+ }
+ }
+ }
+
+endload:
+ fclose(ps);
+ version = PROG_VERSION;
+ load_in_progress = False;
+}
+
+/*------------------------------------------------------*/
+/* Copy all technologies' replace flags into temp flag. */
+/* Then clear the replace flags (replace none) */
+/*------------------------------------------------------*/
+
+void TechReplaceSave()
+{
+ TechPtr nsp;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ {
+ if (nsp->flags & TECH_REPLACE)
+ nsp->flags |= TECH_REPLACE_TEMP;
+ else
+ nsp->flags &= ~TECH_REPLACE_TEMP;
+ nsp->flags &= ~TECH_REPLACE;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Restore all technologies' replace flags */
+/*------------------------------------------------------*/
+
+void TechReplaceRestore()
+{
+ TechPtr nsp;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ {
+ if (nsp->flags & TECH_REPLACE_TEMP)
+ nsp->flags |= TECH_REPLACE;
+ else
+ nsp->flags &= ~TECH_REPLACE;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Set all technologies' replace flags (replace all) */
+/*------------------------------------------------------*/
+
+void TechReplaceAll()
+{
+ TechPtr nsp;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ nsp->flags |= TECH_REPLACE;
+}
+
+/*------------------------------------------------------*/
+/* Clear all technologies' replace flags (replace none) */
+/*------------------------------------------------------*/
+
+void TechReplaceNone()
+{
+ TechPtr nsp;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ nsp->flags &= ~TECH_REPLACE;
+}
+
+
+/*------------------------------------------------------*/
+/* Compare an object's name with a specific technology */
+/* */
+/* A missing "::" prefix separator or an empty prefix */
+/* both match a NULL technology or a technology name */
+/* that is an empty string (""). All of these */
+/* conditions indicate the default "user" technology. */
+/*------------------------------------------------------*/
+
+Boolean CompareTechnology(objectptr cobj, char *technology)
+{
+ char *cptr;
+ Boolean result = FALSE;
+
+ if ((cptr = strstr(cobj->name, "::")) != NULL) {
+ if (technology == NULL)
+ result = (cobj->name == cptr) ? TRUE : FALSE;
+ else {
+ *cptr = '\0';
+ if (!strcmp(cobj->name, technology)) result = TRUE;
+ *cptr = ':';
+ }
+ }
+ else if (technology == NULL)
+ result = TRUE;
+
+ return result;
+}
+
+/*------------------------------------------------------*/
+/* Find a technology record */
+/*------------------------------------------------------*/
+
+TechPtr LookupTechnology(char *technology)
+{
+ TechPtr nsp;
+ Boolean usertech = FALSE;
+
+ // A NULL technology is allowed as equivalent to a
+ // technology name of "" (null string)
+
+ if (technology == NULL)
+ usertech = TRUE;
+ else if (*technology == '\0')
+ usertech = TRUE;
+ else if (!strcmp(technology, "(user)"))
+ usertech = TRUE;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next) {
+ if (usertech == TRUE) {
+ if (*nsp->technology == '\0')
+ return nsp;
+ }
+ if ((technology != NULL) && !strcmp(technology, nsp->technology))
+ return nsp;
+ }
+ return NULL;
+}
+
+/*------------------------------------------------------*/
+/* Find a technology according to the filename */
+/*------------------------------------------------------*/
+
+TechPtr GetFilenameTechnology(char *filename)
+{
+ TechPtr nsp;
+
+ if (filename == NULL) return NULL;
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ if (!filecmp(filename, nsp->filename))
+ return nsp;
+
+ return NULL;
+}
+
+/*------------------------------------------------------*/
+/* Find a technology record corresponding to the */
+/* indicated object's technology. */
+/*------------------------------------------------------*/
+
+TechPtr GetObjectTechnology(objectptr thisobj)
+{
+ TechPtr nsp;
+ char *cptr;
+ /* int nlen; (jdk) */
+
+ cptr = strstr(thisobj->name, "::");
+ if (cptr == NULL) return NULL;
+ else *cptr = '\0';
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next)
+ if (!strcmp(thisobj->name, nsp->technology))
+ break;
+
+ *cptr = ':';
+ return nsp;
+}
+
+/*------------------------------------------------------*/
+/* Add a new technology name to the list */
+/*------------------------------------------------------*/
+
+TechPtr AddNewTechnology(char *technology, char *filename)
+{
+ TechPtr nsp;
+ char usertech[] = "";
+ char *localtech = technology;
+
+ // In the case where somebody has saved the contents of the user
+ // technology to a file, create a technology->filename mapping
+ // using a null string ("") for the technology name. If we are
+ // only checking if a technology name exists (filename is NULL),
+ // then ignore an reference to the user technology.
+
+ if (technology == NULL) {
+ if (filename == NULL) return NULL;
+ else localtech = usertech;
+ }
+
+ for (nsp = xobjs.technologies; nsp != NULL; nsp = nsp->next) {
+ if (!strcmp(localtech, nsp->technology)) {
+
+ /* A namespace may be created for an object that is a dependency */
+ /* in a different technology. If so, it will have a NULL */
+ /* filename, and the filename should be replaced if we ever load */
+ /* the file that properly defines the technology. */
+
+ if ((nsp->filename == NULL) && (filename != NULL))
+ nsp->filename = strdup(filename);
+
+ return nsp; /* Namespace already exists */
+ }
+ }
+
+ nsp = (TechPtr)malloc(sizeof(Technology));
+ nsp->next = xobjs.technologies;
+ if (filename == NULL)
+ nsp->filename = NULL;
+ else
+ nsp->filename = strdup(filename);
+ nsp->technology = strdup(localtech);
+ nsp->flags = (u_char)0;
+ xobjs.technologies = nsp;
+
+ return nsp;
+}
+
+/*------------------------------------------------------*/
+/* Check an object's name for a technology, and add it */
+/* to the list of technologies if it has one. */
+/*------------------------------------------------------*/
+
+void AddObjectTechnology(objectptr thisobj)
+{
+ char *cptr;
+
+ cptr = strstr(thisobj->name, "::");
+ if (cptr != NULL) {
+ *cptr = '\0';
+ AddNewTechnology(thisobj->name, NULL);
+ *cptr = ':';
+ }
+}
+
+/*------------------------------------------------------*/
+/* Load a library page (given in parameter "mode") and */
+/* rename the library page to match the library name as */
+/* found in the file header. */
+/*------------------------------------------------------*/
+
+Boolean loadlibrary(short mode)
+{
+ FILE *ps;
+ objinstptr saveinst;
+ char temp[150], keyword[30], percentc, inname[150];
+ TechPtr nsptr = NULL;
+
+ ps = libopen(_STR, mode, inname, 149);
+
+ if ((ps == NULL) && (mode == FONTLIB)) {
+ /* We automatically try looking in all the usual places plus a */
+ /* subdirectory named "fonts". */
+
+ sprintf(temp, "fonts/%s", _STR);
+ ps = libopen(temp, mode, inname, 149);
+ }
+ if (ps == NULL) {
+ Wprintf("Library not found.");
+ return False;
+ }
+
+ /* current version is PROG_VERSION; however, all libraries newer than */
+ /* version 2.0 require "Version" in the header. So unnumbered */
+ /* libraries may be assumed to be version 1.9 or earlier. */
+
+ version = 1.9;
+ for(;;) {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error in library.");
+ fclose(ps);
+ return False;
+ }
+ sscanf(temp, "%c %29s", &percentc, keyword);
+
+ /* Commands in header are PostScript comments (%) */
+ if (percentc == '%') {
+
+ /* The library name in the header corresponds to the object */
+ /* technology defined by the library. This no longer has */
+ /* anything to do with the name of the library page where we */
+ /* are loading this file. */
+
+ /* Save the technology, filename, and flags in the technology list. */
+
+ if ((mode != FONTLIB) && !strcmp(keyword, "Library")) {
+ char *cptr, *nptr;
+ cptr = strchr(temp, ':');
+ if (cptr != NULL) {
+ cptr += 2;
+
+ /* Don't write terminating newline to the object's name string */
+ ridnewline(cptr);
+
+ /* The default user technology is written to the output */
+ /* as "(user)". If this is found, replace it with a */
+ /* null string. */
+ if (!strcmp(cptr, "(user)")) cptr += 6;
+
+ /* Removing any leading pathname from the library name */
+ if ((nptr = strrchr(cptr, '/')) != NULL) cptr = nptr + 1;
+
+ /* Remove any ".lps" extension from the library name */
+
+ nptr = strrchr(cptr, '.');
+ if ((nptr != NULL) && !strcmp(nptr, ".lps")) *nptr = '\0';
+
+ nsptr = AddNewTechnology(cptr, inname);
+
+ if (nsptr) {
+ // If anything was previously imported from this file
+ // using importfromlibrary(), then the IMPORTED flag
+ // will be set and needs to be cleared.
+ nsptr->flags &= ~TECH_IMPORTED;
+ }
+ }
+ }
+
+ /* This comment gives the Xcircuit version number */
+ else if (!strcmp(keyword, "Version:")) {
+ float tmpv;
+ if (sscanf(temp, "%*c %*s %f", &tmpv) > 0) version = tmpv;
+ }
+
+ /* This PostScript comment marks the end of the file header */
+ else if (!strcmp(keyword, "XCircuitLib")) break;
+ }
+ }
+
+ /* Set the current top object to the library page so that any */
+ /* expression parameters are computed with respect to the library, */
+ /* not a page. Revert back to the page after loading the library. */
+
+ saveinst = areawin->topinstance;
+ areawin->topinstance = xobjs.libtop[mode];
+
+ load_in_progress = True;
+ objectread(ps, topobject, 0, 0, mode, temp, DEFAULTCOLOR, nsptr);
+ load_in_progress = False;
+ cleanupaliases(mode);
+
+ areawin->topinstance = saveinst;
+
+ if (mode != FONTLIB) {
+ composelib(mode);
+ centerview(xobjs.libtop[mode]);
+ if (nsptr == NULL) nsptr = GetFilenameTechnology(inname);
+ if (nsptr != NULL)
+ Wprintf("Loaded library file %s", inname);
+ else
+ Wprintf("Loaded library file %s (technology %s)", inname,
+ nsptr->technology);
+ }
+ else
+ Wprintf("Loaded font file %s", inname);
+
+ version = PROG_VERSION;
+ fclose(ps);
+
+ /* Check if the library is read-only by opening for append */
+
+ if ((mode != FONTLIB) && (nsptr != NULL)) {
+ ps = fopen(inname, "a");
+ if (ps == NULL)
+ nsptr->flags |= TECH_READONLY;
+ else
+ fclose(ps);
+ }
+
+ return True;
+}
+
+/*---------------------------------------------------------*/
+
+void startloadfile(int libnum)
+{
+ int savemode;
+ short firstpage = areawin->page;
+
+ while (nextfilename()) {
+ loadfile(0, libnum);
+
+ /* find next undefined page */
+
+ while(areawin->page < xobjs.pages &&
+ xobjs.pagelist[areawin->page]->pageinst != NULL) areawin->page++;
+ changepage(areawin->page);
+ }
+ loadfile(0, libnum);
+
+
+ /* Prevent page change from being registered as an undoable action */
+ savemode = eventmode;
+ eventmode = UNDO_MODE;
+
+ /* Display the first page loaded */
+ newpage(firstpage);
+ eventmode = savemode;
+
+ setsymschem();
+}
+
+/*------------------------------------------------------*/
+/* normalloadfile() is a call to startloadfile(-1) */
+/* meaning load symbols to the User Library */
+/*------------------------------------------------------*/
+
+void normalloadfile()
+{
+ startloadfile(-1);
+}
+
+/*------------------------------------------------------*/
+/* Import an xcircuit file onto the current page */
+/*------------------------------------------------------*/
+
+void importfile()
+{
+ while (nextfilename()) loadfile(1, -1);
+ loadfile(1, -1);
+}
+
+/*--------------------------------------------------------------*/
+/* Skip forward in the input file to the next comment line */
+/*--------------------------------------------------------------*/
+
+void skiptocomment(char *temp, int length, FILE *ps)
+{
+ int pch;
+
+ do {
+ pch = getc(ps);
+ } while (pch == '\n');
+
+ ungetc(pch, ps);
+ if (pch == '%') fgets(temp, length, ps);
+}
+
+/*--------------------------------------------------------------*/
+/* ASG file import functions: */
+/* This function loads a SPICE deck (hspice format) */
+/*--------------------------------------------------------------*/
+
+#ifdef ASG
+
+void importspice()
+{
+ char inname[250];
+ FILE *spcfile;
+
+ if (eventmode == CATALOG_MODE) {
+ Wprintf("Cannot import a netlist while in the library window.");
+ return;
+ }
+
+ if (!nextfilename()) {
+ xc_tilde_expand(_STR, 149);
+ sscanf(_STR, "%149s", inname);
+ spcfile = fopen(inname, "r");
+ if (spcfile != NULL) {
+ ReadSpice(spcfile);
+ Route(areawin, False);
+ fclose(spcfile);
+ }
+ else {
+ Wprintf("Error: Spice file not found.");
+ return;
+ }
+ }
+ else {
+ Wprintf("Error: No spice file to read.");
+ return;
+ }
+}
+
+#endif
+
+/*--------------------------------------------------------------*/
+/* Load an xcircuit file into xcircuit */
+/* */
+/* mode = 0 is a "load" function. Behavior: load on */
+/* current page if empty. Otherwise, load on first empty */
+/* page found. If no empty pages exist, create a new page */
+/* and load there. */
+/* mode = 1 is an "import" function. Behavior: add */
+/* contents of file to the current page. */
+/* mode = 2 is a "library load" function. Behavior: add */
+/* objects in file to the user library but ignore the */
+/* page contents. */
+/* */
+/* Return value: True if file was successfully loaded, False */
+/* if not. */
+/*--------------------------------------------------------------*/
+
+typedef struct _connects *connectptr;
+
+typedef struct _connects {
+ short page;
+ char *master;
+ connectptr next;
+} connects;
+
+Boolean loadfile(short mode, int libnum)
+{
+ FILE *ps;
+ char inname[150], temp[150], keyword[30], percentc, *pdchar;
+ char teststr[50], teststr2[20], pagestr[100];
+ short offx, offy, multipage, page, temppmode = 0;
+ float tmpfl;
+ XPoint pagesize;
+ connects *connlist = NULL;
+ struct stat statbuf;
+ int loclibnum = (libnum == -1) ? USERLIB : libnum;
+
+ /* First, if we're in catalog mode, return with error */
+
+ if (eventmode == CATALOG_MODE) {
+ Wprintf("Cannot load file from library window");
+ return False;
+ }
+
+ /* Do tilde/variable expansions on filename and open */
+ ps = fileopen(_STR, "ps", inname, 149);
+
+ /* Could possibly be a library file? */
+ /* (Note---loadfile() has no problems loading libraries */
+ /* except for setting technology names and setting the */
+ /* library page view at the end. The loadlibrary() routine */
+ /* should probably be merged into this one.) */
+
+ if (ps == NULL) {
+ ps = fileopen(_STR, "lps", NULL, 0);
+ if (ps != NULL) {
+ fclose(ps);
+ loadlibrary(loclibnum);
+ return True;
+ }
+ }
+ else if (!strcmp(inname + strlen(inname) - 4, ".lps")) {
+ fclose(ps);
+ loadlibrary(loclibnum);
+ return True;
+ }
+
+
+#ifdef LGF
+ /* Could possibly be an LGF file? */
+ if (ps == NULL) {
+ ps = fileopen(_STR, "lgf", NULL, 0);
+ if (ps != NULL) {
+ fclose(ps);
+ loadlgf(mode);
+ return True;
+ }
+ }
+
+ /* Could possibly be an LGF backup (.lfo) file? */
+ if (ps == NULL) {
+ ps = fileopen(_STR, "lfo", NULL, 0);
+ if (ps != NULL) {
+ fclose(ps);
+ loadlgf(mode);
+ return True;
+ }
+ }
+#endif /* LGF */
+
+ /* Check for empty file---don't attempt to read empty files */
+ if (ps != NULL) {
+ if (fstat(fileno(ps), &statbuf) == 0 && (statbuf.st_size == (off_t)0)) {
+ fclose(ps);
+ ps = NULL;
+ }
+ }
+
+ /* What to do if no file was found. . . */
+
+ if (ps == NULL) {
+ if (topobject->parts == 0 && (mode == 0)) {
+
+ /* Check for file extension, and remove if "ps". */
+
+ if ((pdchar = strchr(_STR, '.')) != NULL)
+ if (!strcmp(pdchar + 1, "ps")) *pdchar = '\0';
+
+ free(xobjs.pagelist[areawin->page]->filename);
+ xobjs.pagelist[areawin->page]->filename = strdup(_STR);
+
+ /* If the name has a path component, use only the root */
+ /* for the object name, but the full path for the filename. */
+
+ if ((pdchar = strrchr(_STR, '/')) != NULL)
+ sprintf(topobject->name, "%s", pdchar + 1);
+ else
+ sprintf(topobject->name, "%s", _STR);
+
+ renamepage(areawin->page);
+ printname(topobject);
+ Wprintf("Starting new drawing");
+ }
+ else {
+ Wprintf("Can't find file %s, won't overwrite current page", _STR);
+ }
+ return False;
+ }
+
+ version = 1.0;
+ multipage = 1;
+ pagesize.x = 612;
+ pagesize.y = 792;
+
+ for(;;) {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: EOF in or before prolog.");
+ return False;
+ }
+ sscanf(temp, "%c%29s", &percentc, keyword);
+ for (pdchar = keyword; isspace(*pdchar); pdchar++);
+ if (percentc == '%') {
+ if (!strcmp(pdchar, "XCircuit")) break;
+ if (!strcmp(pdchar, "XCircuitLib")) {
+ /* version control in libraries is post version 1.9 */
+ if (version == 1.0) version = 1.9;
+ break;
+ }
+ if (!strcmp(pdchar, "%Page:")) break;
+ if (strstr(pdchar, "PS-Adobe") != NULL)
+ temppmode = (strstr(temp, "EPSF") != NULL) ? 0 : 1;
+ else if (!strcmp(pdchar, "Version:"))
+ sscanf(temp, "%*c%*s %f", &version);
+ else if (!strcmp(pdchar, "%Pages:")) {
+ pdchar = advancetoken(temp);
+ multipage = atoi(pdchar);
+ }
+ /* Crash files get renamed back to their original filename */
+ else if (!strcmp(pdchar, "%Title:")) {
+ if (xobjs.tempfile != NULL)
+ if (!strcmp(inname, xobjs.tempfile))
+ sscanf(temp, "%*c%*s %s", inname);
+ }
+ else if ((temppmode == 1) && !strcmp(pdchar, "%BoundingBox:")) {
+ short botx, boty;
+ sscanf(temp, "%*s %hd %hd %hd %hd", &botx, &boty,
+ &(pagesize.x), &(pagesize.y));
+ pagesize.x += botx;
+ pagesize.y += boty;
+ }
+
+ }
+#ifdef LGF
+ else if (percentc == '-' && !strcmp(keyword, "5")) {
+ fclose(ps);
+ loadlgf(mode);
+ return True;
+ }
+#endif
+ }
+
+ /* Look for old-style files (no %%Page; maximum one page in file) */
+
+ if (!strcmp(pdchar, "XCircuit"))
+ skiptocomment(temp, 149, ps);
+
+ for (page = 0; page < multipage; page++) {
+ sprintf(pagestr, "%d", page + 1);
+
+ /* read out-of-page library definitions */
+
+ if (strstr(temp, "%%Page:") == NULL && strstr(temp, "offsets") == NULL) {
+ load_in_progress = True;
+ objectread(ps, topobject, 0, 0, loclibnum, temp, DEFAULTCOLOR, NULL);
+ load_in_progress = False;
+ }
+
+ if (strstr(temp, "%%Page:") != NULL) {
+ sscanf(temp + 8, "%99s", pagestr);
+
+ /* Read the next line so any keywords in the Page name don't */
+ /* confuse the parser. */
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: bad page header.");
+ return False;
+ }
+
+ /* Library load mode: Ignore all pages, just load objects */
+ if (mode == 2) {
+ while (strstr(temp, "showpage") == NULL) {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: bad page definition.");
+ return False;
+ }
+ }
+ skiptocomment(temp, 149, ps);
+ continue;
+ }
+ }
+
+ /* go to new page if necessary */
+
+ if (page > 0) {
+
+ /* find next undefined page */
+
+ while(areawin->page < xobjs.pages &&
+ xobjs.pagelist[areawin->page]->pageinst != NULL) areawin->page++;
+ changepage(areawin->page);
+ }
+
+ /* If this file was a library file then there is no page to load */
+
+ if (strstr(temp, "EndLib") != NULL) {
+ composelib(loclibnum);
+ centerview(xobjs.libtop[mode]);
+ Wprintf("Loaded library.");
+ return True;
+ }
+
+ /* good so far; let's clear out the old data structure */
+
+ if (mode == 0) {
+ reset(topobject, NORMAL);
+ pagereset(areawin->page);
+ xobjs.pagelist[areawin->page]->pmode = temppmode;
+ if (temppmode == 1) {
+ xobjs.pagelist[areawin->page]->pagesize.x = pagesize.x;
+ xobjs.pagelist[areawin->page]->pagesize.y = pagesize.y;
+ }
+ }
+ else {
+ invalidate_netlist(topobject);
+ /* ensure that the netlist for topobject is destroyed */
+ freenetlist(topobject);
+ }
+
+ /* clear the undo record */
+ flush_undo_stack();
+
+ /* read to the "scale" line, picking up inch/cm type, drawing */
+ /* scale, and grid/snapspace along the way */
+
+ offx = offy = 0;
+ for(;;) {
+ if (strstr(temp, "offsets") != NULL) {
+ /* Prior to version 3.1.28 only. . . */
+ sscanf(temp, "%c %hd %hd %*s", &percentc, &offx, &offy);
+ if(percentc != '%') {
+ Wprintf("Something wrong in offsets line.");
+ offx = offy = 0;
+ }
+ }
+
+ if ((temppmode == 1) && strstr(temp, "%%PageBoundingBox:") != NULL) {
+ /* Recast the individual page size if specified per page */
+ sscanf(temp, "%*s %*d %*d %hd %hd",
+ &xobjs.pagelist[areawin->page]->pagesize.x,
+ &xobjs.pagelist[areawin->page]->pagesize.y);
+ }
+ else if (strstr(temp, "drawingscale") != NULL)
+ sscanf(temp, "%*c %hd:%hd %*s",
+ &xobjs.pagelist[areawin->page]->drawingscale.x,
+ &xobjs.pagelist[areawin->page]->drawingscale.y);
+
+ else if (strstr(temp, "hidden") != NULL)
+ topobject->hidden = True;
+
+ else if (strstr(temp, "is_symbol") != NULL) {
+ sscanf(temp, "%*c %49s", teststr);
+ checkschem(topobject, teststr);
+ }
+ else if (strstr(temp, "is_primary") != NULL) {
+ /* objectptr master; (jdk) */
+ connects *newconn;
+
+ /* Save information about master schematic and link at end of load */
+ sscanf(temp, "%*c %49s", teststr);
+ newconn = (connects *)malloc(sizeof(connects));
+ newconn->next = connlist;
+ connlist = newconn;
+ newconn->page = areawin->page;
+ newconn->master = strdup(teststr);
+ }
+
+ else if (strstr(temp, "gridspace"))
+ sscanf(temp, "%*c %f %f %*s", &xobjs.pagelist[areawin->page]->gridspace,
+ &xobjs.pagelist[areawin->page]->snapspace);
+ else if (strstr(temp, "scale") != NULL || strstr(temp, "rotate") != NULL) {
+ /* rotation (landscape mode) is optional; parse accordingly */
+
+ sscanf(temp, "%f %49s", &tmpfl, teststr);
+ if (strstr(teststr, "scale") != NULL) {
+#ifndef TCL_WRAPPER
+ setgridtype(teststr);
+#else
+ if (strstr(teststr, "inch"))
+ Tcl_Eval(xcinterp, "xcircuit::coordstyle inches");
+ else
+ Tcl_Eval(xcinterp, "xcircuit::coordstyle centimeters");
+#endif
+ xobjs.pagelist[areawin->page]->outscale = tmpfl;
+ }
+ else if (!strcmp(teststr, "rotate")) {
+ xobjs.pagelist[areawin->page]->orient = (short)tmpfl;
+ fgets(temp, 149, ps);
+ sscanf(temp, "%f %19s", &tmpfl, teststr2);
+ if (strstr(teststr2, "scale") != NULL) {
+#ifndef TCL_WRAPPER
+ setgridtype(teststr2);
+#else
+ if (strstr(teststr2, "inch"))
+ Tcl_Eval(xcinterp, "xcircuit::coordstyle inches");
+ else
+ Tcl_Eval(xcinterp, "xcircuit::coordstyle centimeters");
+#endif
+ xobjs.pagelist[areawin->page]->outscale = tmpfl;
+ }
+ else {
+ sscanf(temp, "%*f %*f %19s", teststr2);
+ if (!strcmp(teststr2, "scale"))
+ xobjs.pagelist[areawin->page]->outscale = tmpfl /
+ getpsscale(1.0, areawin->page);
+ else {
+ Wprintf("Error in scale/rotate constructs.");
+ return False;
+ }
+ }
+ }
+ else { /* old style scale? */
+ sscanf(temp, "%*f %*s %19s", teststr2);
+ if ((teststr2 != NULL) && (!strcmp(teststr2, "scale")))
+ xobjs.pagelist[areawin->page]->outscale = tmpfl /
+ getpsscale(1.0, areawin->page);
+ else {
+ Wprintf("Error in scale/rotate constructs.");
+ return False;
+ }
+ }
+ }
+ else if (strstr(temp, "setlinewidth") != NULL) {
+ sscanf(temp, "%f %*s", &xobjs.pagelist[areawin->page]->wirewidth);
+ xobjs.pagelist[areawin->page]->wirewidth /= 1.3;
+ break;
+ }
+ else if (strstr(temp, "insertion") != NULL) {
+ /* read in an included background image */
+ readbackground(ps);
+ }
+ else if (strstr(temp, "<<") != NULL) {
+ char *buffer = temp, *endptr;
+ /* Make sure we have the whole dictionary before calling */
+ while (strstr(buffer, ">>") == NULL) {
+ if (buffer == temp) {
+ buffer = (char *)malloc(strlen(buffer) + 150);
+ strcpy(buffer, temp);
+ }
+ else
+ buffer = (char *)realloc(buffer, strlen(buffer) + 150);
+ endptr = ridnewline(buffer);
+ *endptr++ = ' ';
+ fgets(endptr, 149, ps);
+ }
+ /* read top-level parameter dictionary */
+ readparams(NULL, NULL, topobject, buffer);
+ if (buffer != temp) free(buffer);
+ }
+
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: Problems encountered in page header.");
+ return False;
+ }
+ }
+
+ load_in_progress = True;
+ objectread(ps, topobject, offx, offy, LIBRARY, temp, DEFAULTCOLOR, NULL);
+ load_in_progress = False;
+
+ /* skip to next page boundary or file trailer */
+
+ if (strstr(temp, "showpage") != NULL && multipage != 1) {
+ char *fstop;
+
+ skiptocomment(temp, 149, ps);
+
+ /* check for new filename if this is a crash recovery file */
+ if ((fstop = strstr(temp, "is_filename")) != NULL) {
+ strncpy(inname, temp + 2, (int)(fstop - temp - 3));
+ *(inname + (int)(fstop - temp) - 3) = '\0';
+ fgets(temp, 149, ps);
+ skiptocomment(temp, 149, ps);
+ }
+ }
+
+ /* Finally: set the filename and pagename for this page */
+
+ if (mode == 0) {
+ char tpstr[6], *rootptr;
+
+ /* Set filename and page title. */
+
+ if (xobjs.pagelist[areawin->page]->filename != NULL)
+ free(xobjs.pagelist[areawin->page]->filename);
+ xobjs.pagelist[areawin->page]->filename = strdup(inname);
+
+ /* Get the root name (after all path components) */
+
+ rootptr = strrchr(xobjs.pagelist[areawin->page]->filename, '/');
+ if (rootptr == NULL) rootptr = xobjs.pagelist[areawin->page]->filename;
+ else rootptr++;
+
+ /* If we didn't read in a page name from the %%Page: header line, then */
+ /* set the page name to the root name of the file. */
+
+ sprintf(tpstr, "%d", page + 1);
+ if (!strcmp(pagestr, tpstr)) {
+ if (rootptr == NULL)
+ sprintf(topobject->name, "Page %d", page + 1);
+ else
+ sprintf(topobject->name, "%.79s", rootptr);
+
+ /* Delete filename extensions ".ps" or ".eps" from the page name */
+ if ((pdchar = strrchr(topobject->name, '.')) != NULL) {
+ if (!strcmp(pdchar + 1, "ps") || !strcmp(pdchar + 1, "eps"))
+ *pdchar = '\0';
+ }
+ }
+ else
+ sprintf(topobject->name, "%.79s", pagestr);
+
+ renamepage(areawin->page);
+ }
+
+ /* set object position to fit to window separately for each page */
+ calcbbox(areawin->topinstance);
+ centerview(areawin->topinstance);
+ }
+
+ /* Crash file recovery: read any out-of-page library definitions tacked */
+ /* onto the end of the file into the user library. */
+ if (strncmp(temp, "%%Trailer", 9)) {
+ load_in_progress = True;
+ objectread(ps, topobject, 0, 0, USERLIB, temp, DEFAULTCOLOR, NULL);
+ load_in_progress = False;
+ }
+
+ cleanupaliases(USERLIB);
+
+ /* Connect master->slave schematics */
+ while (connlist != NULL) {
+ connects *thisconn = connlist;
+ objectptr master = NameToPageObject(thisconn->master, NULL, NULL);
+ if (master) {
+ xobjs.pagelist[thisconn->page]->pageinst->thisobject->symschem = master;
+ xobjs.pagelist[thisconn->page]->pageinst->thisobject->schemtype = SECONDARY;
+ }
+ else {
+ Fprintf(stderr, "Error: Cannot find primary schematic for %s\n",
+ xobjs.pagelist[thisconn->page]->pageinst->thisobject->name);
+ }
+ connlist = thisconn->next;
+ free(thisconn->master);
+ free(thisconn);
+ }
+
+ Wprintf("Loaded file: %s (%d page%s)", inname, multipage,
+ (multipage > 1 ? "s" : ""));
+
+ composelib(loclibnum);
+ centerview(xobjs.libtop[loclibnum]);
+ composelib(PAGELIB);
+
+ if (version > PROG_VERSION + VEPS) {
+ Wprintf("WARNING: file %s is version %2.1f vs. executable version %2.1f",
+ inname, version, PROG_VERSION);
+ }
+
+ version = PROG_VERSION;
+ fclose(ps);
+ return True;
+}
+
+/*------------------------------------------------------*/
+/* Object name comparison: True if names are equal, */
+/* not counting leading underscores. */
+/*------------------------------------------------------*/
+
+int objnamecmp(char *name1, char *name2)
+{
+ char *n1ptr = name1;
+ char *n2ptr = name2;
+
+ while (*n1ptr == '_') n1ptr++;
+ while (*n2ptr == '_') n2ptr++;
+
+ return (strcmp(n1ptr, n2ptr));
+}
+
+/*------------------------------------------------------*/
+/* Standard delimiter matching character. */
+/*------------------------------------------------------*/
+
+char standard_delimiter_end(char source)
+{
+ char target;
+ switch(source) {
+ case '(': target = ')'; break;
+ case '[': target = ']'; break;
+ case '{': target = '}'; break;
+ case '<': target = '>'; break;
+ default: target = source;
+ }
+ return target;
+}
+
+/*------------------------------------------------------*/
+/* Find matching parenthesis, bracket, brace, or tag */
+/* Don't count when backslash character '\' is in front */
+/*------------------------------------------------------*/
+
+u_char *find_delimiter(u_char *fstring)
+{
+ int count = 1;
+
+ u_char *search = fstring;
+ u_char source = *fstring;
+ u_char target;
+
+ target = (u_char)standard_delimiter_end((char)source);
+ while (*++search != '\0') {
+ if (*search == source && *(search - 1) != '\\') count++;
+ else if (*search == target && *(search - 1) != '\\') count--;
+ if (count == 0) break;
+ }
+ return search;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove unnecessary font change information from a label */
+/*----------------------------------------------------------------------*/
+
+void cleanuplabel(stringpart **strhead)
+{
+ stringpart *curpart = *strhead;
+ int oldfont, curfont;
+ Boolean fline = False;
+
+ oldfont = curfont = -1;
+
+ while (curpart != NULL) {
+ switch (curpart->type) {
+ case FONT_NAME:
+ if (curfont == curpart->data.font) {
+ /* Font change is redundant: remove it */
+ /* Careful! font changes remove overline/underline; if */
+ /* either one is in effect, replace it with "noline" */
+ if (fline)
+ curpart->type = NOLINE;
+ else
+ curpart = deletestring(curpart, strhead, NULL);
+ }
+ else {
+ curfont = curpart->data.font;
+ }
+ break;
+
+ case FONT_SCALE:
+ /* Old style font scale is always written absolute, not relative. */
+ /* Changes in scale were not allowed, so just get rid of them. */
+ if (version < 2.25)
+ curpart = deletestring(curpart, strhead, areawin->topinstance);
+ break;
+
+ /* A font change may occur inside a parameter, so any font */
+ /* declaration after a parameter must be considered to be */
+ /* intentional. */
+
+ case PARAM_END:
+ curfont = oldfont = -1;
+ break;
+
+ case OVERLINE: case UNDERLINE:
+ fline = True;
+ break;
+
+ case NOLINE:
+ fline = False;
+ break;
+
+ case NORMALSCRIPT: case RETURN:
+ if (oldfont != -1) {
+ curfont = oldfont;
+ oldfont = -1;
+ }
+ break;
+
+ case SUBSCRIPT: case SUPERSCRIPT:
+ if (oldfont == -1)
+ oldfont = curfont;
+ break;
+ }
+ if (curpart != NULL)
+ curpart = curpart->nextpart;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Read label segments */
+/*----------------------------------------------------------------------*/
+
+void readlabel(objectptr localdata, char *lineptr, stringpart **strhead)
+{
+ Boolean fline = False;
+ /* char *sptr; (jdk) */
+ short j;
+ char *endptr, *segptr = lineptr;
+ char key[100];
+ stringpart *newpart;
+ oparamptr ops;
+
+ while (*segptr != '\0') { /* Look through all segments */
+
+ while (isspace(*segptr) && (*segptr != '\0')) segptr++;
+
+ if (*segptr == '(' || *segptr == '{') {
+ endptr = find_delimiter(segptr);
+ *endptr++ = '\0';
+ /* null string (e.g., null parameter substitution) */
+ if ((*segptr == '(') && (*(segptr + 1) == '\0')) {
+ segptr = endptr;
+ continue;
+ }
+ }
+ else if (*segptr == '\0' || *segptr == '}') break;
+
+ makesegment(strhead, *strhead);
+ newpart = *strhead;
+
+ /* Embedded command is in braces: {} */
+
+ if (*segptr == '{') {
+
+ /* Find the command for this PostScript procedure */
+ char *cmdptr = endptr - 2;
+ while (isspace(*cmdptr)) cmdptr--;
+ while (!isspace(*cmdptr) && (cmdptr > segptr)) cmdptr--;
+ cmdptr++;
+ segptr++;
+
+ if (!strncmp(cmdptr, "Ss", 2))
+ newpart->type = SUPERSCRIPT;
+ else if (!strncmp(cmdptr, "ss", 2))
+ newpart->type = SUBSCRIPT;
+ else if (!strncmp(cmdptr, "ns", 2))
+ newpart->type = NORMALSCRIPT;
+ else if (!strncmp(cmdptr, "hS", 2))
+ newpart->type = HALFSPACE;
+ else if (!strncmp(cmdptr, "qS", 2))
+ newpart->type = QTRSPACE;
+ else if (!strncmp(cmdptr, "CR", 2)) {
+ newpart->type = RETURN;
+ newpart->data.flags = 0;
+ }
+ else if (!strcmp(cmdptr, "Ts")) /* "Tab set" command */
+ newpart->type = TABSTOP;
+ else if (!strcmp(cmdptr, "Tf")) /* "Tab forward" command */
+ newpart->type = TABFORWARD;
+ else if (!strcmp(cmdptr, "Tb")) /* "Tab backward" command */
+ newpart->type = TABBACKWARD;
+ else if (!strncmp(cmdptr, "ol", 2)) {
+ newpart->type = OVERLINE;
+ fline = True;
+ }
+ else if (!strncmp(cmdptr, "ul", 2)) {
+ newpart->type = UNDERLINE;
+ fline = True;
+ }
+ else if (!strncmp(cmdptr, "sce", 3)) { /* revert to default color */
+ newpart->type = FONT_COLOR;
+ newpart->data.color = DEFAULTCOLOR;
+ }
+ else if (cmdptr == segptr) { /* cancel over- or underline */
+ newpart->type = NOLINE;
+ fline = False;
+ }
+ /* To-do: replace old-style backspace with tab stop */
+ else if (!strcmp(cmdptr, "bs")) {
+ Wprintf("Warning: Obsolete backspace command ommitted in text");
+ }
+ else if (!strcmp(cmdptr, "Kn")) { /* "Kern" command */
+ int kx, ky;
+ sscanf(segptr, "%d %d", &kx, &ky);
+ newpart->type = KERN;
+ newpart->data.kern[0] = kx;
+ newpart->data.kern[1] = ky;
+ }
+ else if (!strcmp(cmdptr, "MR")) { /* "Margin stop" command */
+ int width;
+ sscanf(segptr, "%d", &width);
+ newpart->type = MARGINSTOP;
+ newpart->data.width = width;
+ }
+ else if (!strcmp(cmdptr, "scb")) { /* change color command */
+ float cr, cg, cb;
+ int cval, cindex;
+ sscanf(segptr, "%f %f %f", &cr, &cg, &cb);
+ newpart->type = FONT_COLOR;
+ cval = rgb_alloccolor((int)(cr * 65535), (int)(cg * 65535),
+ (int)(cb * 65535));
+ for (cindex = 0; cindex < number_colors; cindex++)
+ if (colorlist[cindex].color.pixel == cval)
+ break;
+ if (cindex == number_colors) {
+ Wprintf("Error: Cannot allocate another color");
+ cindex = DEFAULTCOLOR;
+ }
+ newpart->data.color = cindex;
+ }
+ else if (!strcmp(cmdptr, "cf")) { /* change font or scale command */
+ char *nextptr, *newptr = segptr;
+
+ /* Set newptr to the fontname and nextptr to the next token. */
+ while (*newptr != '/' && *newptr != '\0') newptr++;
+ if (*newptr++ == '\0') {
+ Wprintf("Error: Bad change-font command");
+ newpart->type = NOLINE; /* placeholder */
+ }
+ for (nextptr = newptr; !isspace(*nextptr); nextptr++);
+ *(nextptr++) = '\0';
+ while (isspace(*nextptr)) nextptr++;
+
+ for (j = 0; j < fontcount; j++)
+ if (!strcmp(newptr, fonts[j].psname))
+ break;
+
+ if (j == fontcount) /* this is a non-loaded font */
+ if (loadfontfile(newptr) < 0) {
+ if (fontcount > 0) {
+ Wprintf("Error: Font \"%s\" not found---using default.", newptr);
+ j = 0;
+ }
+ else {
+ Wprintf("Error: No fonts!");
+ newpart->type = NOLINE; /* placeholder */
+ }
+ }
+
+ if (isdigit(*nextptr)) { /* second form of "cf" command---includes scale */
+ float locscale;
+ sscanf(nextptr, "%f", &locscale);
+ newpart->type = FONT_SCALE;
+ newpart->data.scale = locscale;
+ makesegment(strhead, *strhead);
+ newpart = *strhead;
+ }
+ newpart->type = FONT_NAME;
+ newpart->data.font = j;
+ }
+ else { /* This exec isn't a known label function */
+ Wprintf("Error: unknown substring function");
+ newpart->type = NOLINE; /* placeholder */
+ }
+ }
+
+ /* Text substring is in parentheses: () */
+
+ else if (*segptr == '(') {
+ if (fline == True) {
+ newpart->type = NOLINE;
+ makesegment(strhead, *strhead);
+ newpart = *strhead;
+ fline = False;
+ }
+ newpart->type = TEXT_STRING;
+ newpart->data.string = (u_char *)malloc(1 + strlen(++segptr));
+
+ /* Copy string, translating octal codes into 8-bit characters */
+ parse_ps_string(segptr, newpart->data.string, strlen(segptr), TRUE, TRUE);
+ }
+
+ /* Parameterized substrings are denoted by parameter key. */
+ /* The parameter (default and/or substitution value) is */
+ /* assumed to exist. */
+
+ else {
+
+ parse_ps_string(segptr, key, 99, FALSE, TRUE);
+ if (strlen(key) > 0) {
+ newpart->type = PARAM_START;
+ newpart->data.string = (char *)malloc(1 + strlen(key));
+ strcpy(newpart->data.string, key);
+
+ /* check for compatibility between the parameter value and */
+ /* the number of parameters and parameter type. */
+
+ ops = match_param(localdata, key);
+ if (ops == NULL) {
+ Fprintf(stderr, "readlabel() error: No such parameter %s!\n", key);
+ deletestring(newpart, strhead, areawin->topinstance);
+ }
+
+ /* Fprintf(stdout, "Parameter %s called from object %s\n", */
+ /* key, localdata->name); */
+ }
+ endptr = segptr + 1;
+ while (!isspace(*endptr) && (*endptr != '\0')) endptr++;
+ }
+ segptr = endptr;
+ }
+}
+
+/*--------------------------------------*/
+/* skip over whitespace in string input */
+/*--------------------------------------*/
+
+char *skipwhitespace(char *lineptr)
+{
+ char *locptr = lineptr;
+
+ while (isspace(*locptr) && (*locptr != '\n') && (*locptr != '\0')) locptr++;
+ return locptr;
+}
+
+/*-------------------------------------------*/
+/* advance to the next token in string input */
+/*-------------------------------------------*/
+
+char *advancetoken(char *lineptr)
+{
+ char *locptr = lineptr;
+
+ while (!isspace(*locptr) && (*locptr != '\n') && (*locptr != '\0')) locptr++;
+ while (isspace(*locptr) && (*locptr != '\n') && (*locptr != '\0')) locptr++;
+ return locptr;
+}
+
+/*------------------------------------------------------*/
+/* Read a parameter list for an object instance call. */
+/* This uses the key-value dictionary method but also */
+/* allows the "old style" in which each parameter */
+/* was automatically assigned the key v1, v2, etc. */
+/*------------------------------------------------------*/
+
+void readparams(objectptr localdata, objinstptr newinst, objectptr libobj,
+ char *buffer)
+{
+ oparamptr newops, objops, fops;
+ char *arrayptr, *endptr, *arraynext;
+ int paramno = 0;
+ char paramkey[100];
+
+ if ((arrayptr = strstr(buffer, "<<")) == NULL)
+ if ((arrayptr = strchr(buffer, '[')) == NULL)
+ return;
+
+ endptr = find_delimiter(arrayptr);
+ if (*arrayptr == '<') {
+ arrayptr++; /* move to second '<' in "<<" */
+ endptr--; /* back up to first '>' in ">>" */
+ }
+
+ /* move to next non-space token after opening bracket */
+ arrayptr++;
+ while (isspace(*arrayptr) && *arrayptr != '\0') arrayptr++;
+
+ while ((*arrayptr != '\0') && (arrayptr < endptr)) {
+
+ newops = (oparamptr)malloc(sizeof(oparam));
+
+ /* Arrays contain values only. Dictionaries contain key:value pairs */
+ if (*endptr == '>') { /* dictionary type */
+ if (*arrayptr != '/') {
+ Fprintf(stdout, "Error: Dictionary key is a literal, not a name\n");
+ }
+ else arrayptr++; /* Skip PostScript name delimiter */
+ parse_ps_string(arrayptr, paramkey, 99, FALSE, TRUE);
+ newops->key = (char *)malloc(1 + strlen(paramkey));
+ strcpy(newops->key, paramkey);
+ arrayptr = advancetoken(arrayptr);
+ }
+ else { /* array type; keys are "v1", "v2", etc. */
+ paramno++;
+ newops->key = (char *)malloc(6);
+ sprintf(newops->key, "v%d", paramno);
+ }
+
+ /* Find matching parameter in object definition */
+ if (newinst) {
+ objops = match_param(libobj, newops->key);
+ if (objops == NULL) {
+ Fprintf(stdout, "Error: parameter %s does not exist in object %s!\n",
+ newops->key, libobj->name);
+ free(newops->key);
+ free(newops);
+ return;
+ }
+ }
+
+ /* Add to instance's parameter list */
+ /* If newinst is null, then the parameters are added to libobj */
+ newops->next = NULL;
+ if (newinst) {
+
+ /* Delete any parameters with duplicate names. This */
+ /* This may indicate an expression parameter that was */
+ /* precomputed while determining the bounding box. */
+
+ for (fops = newinst->params; fops != NULL; fops = fops->next)
+ if (!strcmp(fops->key, newops->key))
+ if ((fops = free_instance_param(newinst, fops)) == NULL)
+ break;
+
+ if (newinst->params == NULL)
+ newinst->params = newops;
+ else {
+ for (fops = newinst->params; fops->next != NULL; fops = fops->next);
+ fops->next = newops;
+ }
+ }
+ else {
+ if (libobj->params == NULL)
+ libobj->params = newops;
+ else {
+ for (fops = libobj->params; fops->next != NULL; fops = fops->next);
+ fops->next = newops;
+ }
+ }
+
+ /* Fill in "which" entry from the object default */
+ newops->which = (newinst) ? objops->which : 0;
+
+ /* Check next token. If not either end-of-dictionary or */
+ /* the next parameter key, then value is an expression. */
+ /* Expressions are written as two strings, the first the */
+ /* result of evaluting the expression, and the second the */
+ /* expression itself, followed by "pop" to prevent the */
+ /* PostScript interpreter from trying to evaluate the */
+ /* expression (which is not in PostScript). */
+
+ if (*arrayptr == '(' || *arrayptr == '{')
+ arraynext = find_delimiter(arrayptr);
+ else
+ arraynext = arrayptr;
+ arraynext = advancetoken(arraynext);
+
+ if ((*endptr == '>') && (arraynext < endptr) && (*arraynext != '/')) {
+ char *substrend, *arraysave;
+
+ if (*arraynext == '(' || *arraynext == '{') {
+
+ substrend = find_delimiter(arraynext);
+ arraysave = arraynext + 1;
+ arraynext = advancetoken(substrend);
+
+ newops->type = (u_char)XC_EXPR;
+ newops->which = P_EXPRESSION; /* placeholder */
+ }
+
+ if (strncmp(arraynext, "pop ", 4)) {
+ Wprintf("Error: bad expression parameter!\n");
+#ifdef TCL_WRAPPER
+ newops->parameter.expr = strdup("expr 0");
+#else
+ newops->parameter.expr = strdup("0");
+#endif
+ arrayptr = advancetoken(arrayptr);
+ } else {
+ *substrend = '\0';
+ newops->parameter.expr = strdup(arraysave);
+ arrayptr = advancetoken(arraynext);
+ }
+ }
+
+ else if (*arrayptr == '(' || *arrayptr == '{') {
+ float r, g, b;
+ char *substrend, csave;
+ stringpart *endpart;
+
+ /* type XC_STRING */
+
+ substrend = find_delimiter(arrayptr);
+ csave = *(++substrend);
+ *substrend = '\0';
+ if (*arrayptr == '{') arrayptr++;
+
+ /* A numerical value immediately following the opening */
+ /* brace indicates a color parameter. */
+ if (sscanf(arrayptr, "%f %f %f", &r, &g, &b) == 3) {
+ newops->type = (u_char)XC_INT;
+ newops->which = P_COLOR;
+ newops->parameter.ivalue = rgb_alloccolor((int)(r * 65535),
+ (int)(g * 65535), (int)(b * 65535));
+ addnewcolorentry(newops->parameter.ivalue);
+ *substrend = csave;
+ }
+ else {
+ char *arraytmp = arrayptr;
+ char linkdefault[5] = "(%n)";
+
+ newops->type = (u_char)XC_STRING;
+ newops->which = P_SUBSTRING;
+ newops->parameter.string = NULL;
+
+ /* Quick check for "link" parameter: make object name into "%n" */
+ if (!strcmp(newops->key, "link"))
+ if (!strncmp(arrayptr + 1, libobj->name, strlen(libobj->name)) &&
+ !strcmp(arrayptr + strlen(libobj->name) + 1, ")"))
+ arraytmp = linkdefault;
+
+ readlabel(libobj, arraytmp, &(newops->parameter.string));
+ *substrend = csave;
+
+ /* Append a PARAM_END to the parameter string */
+
+ endpart = makesegment(&(newops->parameter.string), NULL);
+ endpart->type = PARAM_END;
+ endpart->data.string = (u_char *)NULL;
+ }
+ arrayptr = substrend;
+ while (isspace(*arrayptr) && *arrayptr != '\0')
+ arrayptr++;
+ }
+ else {
+ /* char *token; (jdk) */
+ int scanned = 0;
+
+ /* type XC_FLOAT or XC_INT, or an indirect reference */
+
+ newops->type = (newinst) ? objops->type : (u_char)XC_FLOAT;
+
+ if (newops->type == XC_FLOAT) {
+ scanned = sscanf(arrayptr, "%f", &(newops->parameter.fvalue));
+ /* Fprintf(stdout, "Object %s called with parameter "
+ "%s value %g\n", libobj->name,
+ newops->key, newops->parameter.fvalue); */
+ }
+ else if (newops->type == XC_INT) {
+ scanned = sscanf(arrayptr, "%d", &(newops->parameter.ivalue));
+ /* Fprintf(stdout, "Object %s called with parameter "
+ "%s value %d\n", libobj->name,
+ newops->key, newops->parameter.ivalue); */
+ }
+ else if (newops->type == XC_EXPR) {
+ /* Instance values of parameters hold the last evaluated */
+ /* result and will be regenerated, so we can ignore them */
+ /* here. By ignoring it, we don't have to deal with issues */
+ /* like type promotion. */
+ free_instance_param(newinst, newops);
+ scanned = 1; /* avoid treating as an indirect ref */
+ }
+ else if (newops->type == XC_STRING) {
+ /* Fill string record, so we have a valid record. This will */
+ /* be blown away and replaced by opsubstitute(), but it must */
+ /* have an initial valid entry. */
+ stringpart *tmpptr;
+ newops->parameter.string = NULL;
+ tmpptr = makesegment(&newops->parameter.string, NULL);
+ tmpptr->type = TEXT_STRING;
+ tmpptr = makesegment(&newops->parameter.string, NULL);
+ tmpptr->type = PARAM_END;
+ }
+ else {
+ Fprintf(stderr, "Error: unknown parameter type!\n");
+ }
+
+ if (scanned == 0) {
+ /* Indirect reference --- create an eparam in the instance */
+ parse_ps_string(arrayptr, paramkey, 99, FALSE, TRUE);
+
+ if (!newinst || !localdata) {
+ /* Only object instances can use indirect references */
+ Fprintf(stderr, "Error: parameter default %s cannot "
+ "be parsed!\n", paramkey);
+ }
+ else if (match_param(localdata, paramkey) == NULL) {
+ /* Reference key must exist in the calling object */
+ Fprintf(stderr, "Error: parameter value %s cannot be parsed!\n",
+ paramkey);
+ }
+ else {
+ /* Create an eparam record in the instance */
+ eparamptr newepp = make_new_eparam(paramkey);
+ newepp->flags |= P_INDIRECT;
+ newepp->pdata.refkey = strdup(newops->key);
+ newepp->next = newinst->passed;
+ newinst->passed = newepp;
+ }
+
+ }
+ arrayptr = advancetoken(arrayptr);
+ }
+ }
+
+ /* Calculate the unique bounding box for the instance */
+
+ if (newinst && (newinst->params != NULL)) {
+ opsubstitute(libobj, newinst);
+ calcbboxinst(newinst);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Read a value which might be a short integer or a parameter. */
+/* If the value is a parameter, check the parameter list to see */
+/* if it needs to be re-typecast. Return the position to the */
+/* next token in "lineptr". */
+/*--------------------------------------------------------------*/
+
+char *varpscan(objectptr localdata, char *lineptr, short *hvalue,
+ genericptr thiselem, int pointno, int offset, u_char which)
+{
+ oparamptr ops = NULL;
+ char key[100];
+ /* char *nexttok; (jdk) */
+ eparamptr newepp;
+
+ if (sscanf(lineptr, "%hd", hvalue) != 1) {
+ parse_ps_string(lineptr, key, 99, FALSE, TRUE);
+
+ /* This bit of a hack takes care of scale-variant */
+ /* linewidth specifiers for object instances. */
+
+ if (!strncmp(key, "/sv", 3)) {
+ ((objinstptr)thiselem)->style &= ~LINE_INVARIANT;
+ return varpscan(localdata, advancetoken(skipwhitespace(lineptr)),
+ hvalue, thiselem, pointno, offset, which);
+ }
+
+ ops = match_param(localdata, key);
+ newepp = make_new_eparam(key);
+
+ /* Add parameter to the linked list */
+ newepp->next = thiselem->passed;
+ thiselem->passed = newepp;
+ newepp->pdata.pointno = pointno;
+
+ if (ops != NULL) {
+
+ /* It cannot be known whether a parameter value is a float or int */
+ /* until we see how the parameter is used. So we always read the */
+ /* parameter default as a float, and re-typecast it if necessary. */
+
+ if (ops->type == XC_FLOAT) {
+ ops->type = XC_INT;
+ /* (add 0.1 to avoid roundoff error in conversion to integer) */
+ ops->parameter.ivalue = (int)(ops->parameter.fvalue +
+ ((ops->parameter.fvalue < 0) ? -0.1 : 0.1));
+ }
+ ops->which = which;
+ *hvalue = (short)ops->parameter.ivalue;
+ }
+ else {
+ *hvalue = 0; /* okay; will get filled in later */
+ Fprintf(stderr, "Error: parameter %s was used but not defined!\n", key);
+ }
+ }
+
+ *hvalue -= (short)offset;
+
+ return advancetoken(skipwhitespace(lineptr));
+}
+
+/*--------------------------------------------------------------*/
+/* Read a value which might be a short integer or a parameter, */
+/* but which is not a point in a pointlist. */
+/*--------------------------------------------------------------*/
+
+char *varscan(objectptr localdata, char *lineptr, short *hvalue,
+ genericptr thiselem, u_char which)
+{
+ return varpscan(localdata, lineptr, hvalue, thiselem, 0, 0, which);
+}
+
+/*--------------------------------------------------------------*/
+/* Read a value which might be a float or a parameter. */
+/* Return the position to the next token in "lineptr". */
+/*--------------------------------------------------------------*/
+
+char *varfscan(objectptr localdata, char *lineptr, float *fvalue,
+ genericptr thiselem, u_char which)
+{
+ oparamptr ops = NULL;
+ eparamptr newepp;
+ char key[100];
+
+ if (sscanf(lineptr, "%f", fvalue) != 1) {
+ parse_ps_string(lineptr, key, 99, FALSE, TRUE);
+ ops = match_param(localdata, key);
+ newepp = make_new_eparam(key);
+
+ /* Add parameter to the linked list */
+ newepp->next = thiselem->passed;
+ thiselem->passed = newepp;
+
+ if (ops != NULL) {
+ ops->which = which;
+ *fvalue = ops->parameter.fvalue;
+ }
+ else
+ Fprintf(stderr, "Error: no parameter defined!\n");
+ }
+
+ /* advance to next token */
+ return advancetoken(skipwhitespace(lineptr));
+}
+
+/*--------------------------------------------------------------*/
+/* Same as varpscan(), but for path types only. */
+/*--------------------------------------------------------------*/
+
+char *varpathscan(objectptr localdata, char *lineptr, short *hvalue,
+ genericptr *thiselem, pathptr thispath, int pointno, int offset,
+ u_char which, eparamptr *nepptr)
+{
+ oparamptr ops = NULL;
+ char key[100];
+ eparamptr newepp;
+
+ if (nepptr != NULL) *nepptr = NULL;
+
+ if (sscanf(lineptr, "%hd", hvalue) != 1) {
+ parse_ps_string(lineptr, key, 99, FALSE, TRUE);
+ ops = match_param(localdata, key);
+ newepp = make_new_eparam(key);
+ newepp->pdata.pathpt[1] = pointno;
+
+ if (thiselem == NULL)
+ newepp->pdata.pathpt[0] = (short)0;
+ else {
+ short elemidx = (short)(thiselem - thispath->plist);
+ if (elemidx >= 0 && elemidx < thispath->parts)
+ newepp->pdata.pathpt[0] = (short)(thiselem - thispath->plist);
+ else {
+ Fprintf(stderr, "Error: Bad parameterized path point!\n");
+ free(newepp);
+ goto pathdone;
+ }
+ }
+ if (nepptr != NULL) *nepptr = newepp;
+
+ /* Add parameter to the linked list. */
+
+ newepp->next = thispath->passed;
+ thispath->passed = newepp;
+
+ if (ops != NULL) {
+
+ /* It cannot be known whether a parameter value is a float or int */
+ /* until we see how the parameter is used. So we always read the */
+ /* parameter default as a float, and re-typecast it if necessary. */
+
+ if (ops->type == XC_FLOAT) {
+ ops->type = XC_INT;
+ /* (add 0.1 to avoid roundoff error in conversion to integer) */
+ ops->parameter.ivalue = (int)(ops->parameter.fvalue +
+ ((ops->parameter.fvalue < 0) ? -0.1 : 0.1));
+ }
+ ops->which = which;
+ *hvalue = (short)ops->parameter.ivalue;
+ }
+ else {
+ *hvalue = 0; /* okay; will get filled in later */
+ Fprintf(stderr, "Error: parameter %s was used but not defined!\n", key);
+ }
+ }
+
+pathdone:
+ *hvalue -= (short)offset;
+ return advancetoken(skipwhitespace(lineptr));
+}
+
+/*--------------------------------------------------------------*/
+/* Create a new instance of an object in the library's list of */
+/* instances. This instance will be used on the library page */
+/* when doing "composelib()". */
+/*--------------------------------------------------------------*/
+
+objinstptr addtoinstlist(int libnum, objectptr libobj, Boolean virtual)
+{
+ objinstptr newinst = (objinstptr) malloc(sizeof(objinst));
+ liblistptr spec = (liblistptr) malloc(sizeof(liblist));
+ liblistptr srch;
+
+ newinst->type = OBJINST;
+ instancedefaults(newinst, libobj, 0, 0);
+
+ spec->virtual = (u_char)virtual;
+ spec->thisinst = newinst;
+ spec->next = NULL;
+
+ /* Add to end, so that duplicate, parameterized instances */
+ /* always come after the original instance with the default */
+ /* parameters. */
+
+ if ((srch = xobjs.userlibs[libnum].instlist) == NULL)
+ xobjs.userlibs[libnum].instlist = spec;
+ else {
+ while (srch->next != NULL) srch = srch->next;
+ srch->next = spec;
+ }
+
+ /* Calculate the instance-specific bounding box */
+ calcbboxinst(newinst);
+
+ return newinst;
+}
+
+/*--------------------------------------------------------------*/
+/* Deal with object reads: Create a new object and prepare for */
+/* reading. The library number is passed as "mode". */
+/*--------------------------------------------------------------*/
+
+objectptr *new_library_object(short mode, char *name, objlistptr *retlist,
+ TechPtr defaulttech)
+{
+ objlistptr newdef, redef = NULL;
+ objectptr *newobject, *libobj;
+ objectptr *curlib = (mode == FONTLIB) ?
+ xobjs.fontlib.library : xobjs.userlibs[mode - LIBRARY].library;
+ short *libobjects = (mode == FONTLIB) ?
+ &xobjs.fontlib.number : &xobjs.userlibs[mode - LIBRARY].number;
+ int i, j;
+ char *nsptr, *fullname = name;
+
+ curlib = (objectptr *) realloc(curlib, (*libobjects + 1)
+ * sizeof(objectptr));
+ if (mode == FONTLIB) xobjs.fontlib.library = curlib;
+ else xobjs.userlibs[mode - LIBRARY].library = curlib;
+
+ /* For (older) libraries that do not use technologies, give the */
+ /* object a technology name in the form <library>::<object> */
+
+ if ((nsptr = strstr(name, "::")) == NULL) {
+ int deftechlen = (defaulttech == NULL) ? 0 : strlen(defaulttech->technology);
+ fullname = (char *)malloc(deftechlen + strlen(name) + 3);
+ if (defaulttech == NULL)
+ sprintf(fullname, "::%s", name);
+ else
+ sprintf(fullname, "%s::%s", defaulttech->technology, name);
+ }
+
+ /* initial 1-pointer allocations */
+
+ newobject = curlib + (*libobjects);
+ *newobject = (objectptr) malloc(sizeof(object));
+ initmem(*newobject);
+
+ /* check that this object is not already in list of objects */
+
+ if (mode == FONTLIB) {
+ for (libobj = xobjs.fontlib.library; libobj != xobjs.fontlib.library +
+ xobjs.fontlib.number; libobj++) {
+ /* This font character may be a redefinition of another */
+ if (!objnamecmp(fullname, (*libobj)->name)) {
+ newdef = (objlistptr) malloc(sizeof(objlist));
+ newdef->libno = FONTLIB;
+ newdef->thisobject = *libobj;
+ newdef->next = redef;
+ redef = newdef;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ libobj = xobjs.userlibs[i].library + j;
+ /* This object may be a redefinition of another object */
+ if (!objnamecmp(fullname, (*libobj)->name)) {
+ newdef = (objlistptr) malloc(sizeof(objlist));
+ newdef->libno = i + LIBRARY;
+ newdef->thisobject = *libobj;
+ newdef->next = redef;
+ redef = newdef;
+ }
+ }
+ }
+ }
+
+ (*libobjects)++;
+ sprintf((*newobject)->name, "%s", fullname);
+ if (fullname != name) free(fullname);
+
+ /* initmem() initialized schemtype to PRIMARY; change it. */
+ (*newobject)->schemtype = (mode == FONTLIB) ? GLYPH : SYMBOL;
+
+ /* If the object declares a technology name that is different from the */
+ /* default, then add the technology name to the list of technologies, */
+ /* with a NULL filename. */
+
+ if (mode != FONTLIB) AddObjectTechnology(*newobject);
+
+ *retlist = redef;
+ return newobject;
+}
+
+/*--------------------------------------------------------------*/
+/* do an exhaustive comparison between a new object and any */
+/* object having the same name. If they are the same, destroy */
+/* the duplicate. If different, rename the original one. */
+/*--------------------------------------------------------------*/
+
+Boolean library_object_unique(short mode, objectptr newobject, objlistptr redef)
+{
+ Boolean is_unique = True;
+ objlistptr newdef;
+ short *libobjects = (mode == FONTLIB) ?
+ &xobjs.fontlib.number : &xobjs.userlibs[mode - LIBRARY].number;
+
+ if (redef == NULL)
+ return is_unique; /* No name conflicts; object is okay as-is */
+
+ for (newdef = redef; newdef != NULL; newdef = newdef->next) {
+
+ /* Must make sure that default parameter values are */
+ /* plugged into both objects! */
+ opsubstitute(newdef->thisobject, NULL);
+ opsubstitute(newobject, NULL);
+
+ if (objcompare(newobject, newdef->thisobject) == True) {
+ addalias(newdef->thisobject, newobject->name);
+
+ /* If the new object has declared an association to a */
+ /* schematic, transfer it to the original, and make */
+ /* sure that the page points to the object which will */
+ /* be left, not the one which will be destroyed. */
+
+ if (newobject->symschem != NULL) {
+ newdef->thisobject->symschem = newobject->symschem;
+ newdef->thisobject->symschem->symschem = newdef->thisobject;
+ }
+
+ reset(newobject, DESTROY);
+ (*libobjects)--;
+ is_unique = False;
+ break;
+ }
+
+ /* Not the same object, but has the same name. This can't */
+ /* happen within the same input file, so the name of the */
+ /* original object can safely be altered. */
+
+ else if (!strcmp(newobject->name, newdef->thisobject->name)) {
+
+ /* Replacement---for project management, allow the technology */
+ /* master version to take precedence over a local version. */
+
+ TechPtr nsptr = GetObjectTechnology(newobject);
+
+ if (nsptr && (nsptr->flags & TECH_REPLACE)) {
+ reset(newobject, DESTROY);
+ (*libobjects)--;
+ is_unique = False;
+ }
+ else
+ checkname(newdef->thisobject);
+ break;
+ }
+ }
+ for (; (newdef = redef->next); redef = newdef)
+ free(redef);
+ free(redef);
+
+ return is_unique;
+}
+
+/*--------------------------------------------------------------*/
+/* Add an instance of the object to the library's instance list */
+/*--------------------------------------------------------------*/
+
+void add_object_to_library(short mode, objectptr newobject)
+{
+ objinstptr libinst;
+
+ if (mode == FONTLIB) return;
+
+ libinst = addtoinstlist(mode - LIBRARY, newobject, False);
+ calcbboxvalues(libinst, (genericptr *)NULL);
+
+ /* Center the view of the object in its instance */
+ centerview(libinst);
+}
+
+/*--------------------------------------------------------------*/
+/* Continuation Line --- add memory to "buffer" as necessary. */
+/* Add a space character to the current text in "buffer" and */
+/* return a pointer to the new end-of-text. */
+/*--------------------------------------------------------------*/
+
+char *continueline(char **buffer)
+{
+ char *lineptr;
+ int bufsize;
+
+ for (lineptr = *buffer; (*lineptr != '\n') && (*lineptr != '\0'); lineptr++);
+ /* Repair Windoze-mangled files */
+ if ((lineptr > *buffer) && (*lineptr == '\n') && (*(lineptr - 1) == '\r'))
+ *(lineptr - 1) = ' ';
+ if (*lineptr == '\n') *lineptr++ = ' ';
+
+ bufsize = (int)(lineptr - (*buffer)) + 256;
+ *buffer = (char *)realloc((*buffer), bufsize * sizeof(char));
+
+ return ((*buffer) + (bufsize - 256));
+}
+
+/*--------------------------------------------------------------*/
+/* Read image data out of the Setup block of the input */
+/* We assume that width and height have been parsed from the */
+/* "imagedata" line and the file pointer is at the next line. */
+/*--------------------------------------------------------------*/
+
+void readimagedata(FILE *ps, int width, int height)
+{
+ char temp[150], ascbuf[6];
+ int x, y, p, q, r, g, b, ilen;
+ char *pptr;
+ Imagedata *iptr;
+ Boolean do_flate = False, do_ascii = False;
+ u_char *filtbuf, *flatebuf;
+ union {
+ u_char b[4];
+ u_long i;
+ } pixel;
+
+ iptr = addnewimage(NULL, width, height);
+
+ /* Read the image data */
+
+ fgets(temp, 149, ps);
+ if (strstr(temp, "ASCII85Decode") != NULL) do_ascii = TRUE;
+#ifdef HAVE_LIBZ
+ if (strstr(temp, "FlateDecode") != NULL) do_flate = TRUE;
+#else
+ if (strstr(temp, "FlateDecode") != NULL)
+ Fprintf(stderr, "Error: Don't know how to Flate decode!"
+ " Get zlib and recompile xcircuit!\n");
+#endif
+ while (strstr(temp, "ReusableStreamDecode") == NULL)
+ fgets(temp, 149, ps); /* Additional piped filter lines */
+
+ fgets(temp, 149, ps); /* Initial data line */
+ q = 0;
+ pptr = temp;
+ ilen = 3 * width * height;
+ filtbuf = (u_char *)malloc(ilen + 4);
+
+ if (!do_ascii) { /* ASCIIHexDecode algorithm */
+ q = 0;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ sscanf(pptr, "%02x%02x%02x", &r, &g, &b);
+ filtbuf[q++] = (u_char)r;
+ filtbuf[q++] = (u_char)g;
+ filtbuf[q++] = (u_char)b;
+ pptr += 6;
+ if (*pptr == '\n') {
+ fgets(temp, 149, ps);
+ pptr = temp;
+ }
+ }
+ }
+ }
+ else { /* ASCII85Decode algorithm */
+ p = 0;
+ while (1) {
+ ascbuf[0] = *pptr;
+ pptr++;
+ if (ascbuf[0] == '~')
+ break;
+ else if (ascbuf[0] == 'z') {
+ for (y = 0; y < 5; y++) ascbuf[y] = '\0';
+ }
+ else {
+ for (y = 1; y < 5; y++) {
+ if (*pptr == '\n') {
+ fgets(temp, 149, ps);
+ pptr = temp;
+ }
+ ascbuf[y] = *pptr;
+ if (ascbuf[y] == '~') {
+ for (; y < 5; y++) {
+ ascbuf[y] = '!';
+ p++;
+ }
+ break;
+ }
+ else pptr++;
+ }
+ for (y = 0; y < 5; y++) ascbuf[y] -= '!';
+ }
+
+ if (*pptr == '\n') {
+ fgets(temp, 149, ps);
+ pptr = temp;
+ }
+
+ /* Decode from ASCII85 to binary */
+
+ pixel.i = ascbuf[4] + ascbuf[3] * 85 + ascbuf[2] * 7225 +
+ ascbuf[1] * 614125 + ascbuf[0] * 52200625;
+
+ /* Add in roundoff for final bytes */
+ if (p > 0) {
+ switch (p) {
+ case 3:
+ pixel.i += 0xff0000;
+ case 2:
+ pixel.i += 0xff00;
+ case 1:
+ pixel.i += 0xff;
+ }
+ }
+
+ for (y = 0; y < (4 - p); y++) {
+ filtbuf[q + y] = pixel.b[3 - y];
+ }
+ q += (4 - p);
+ if (q >= ilen) break;
+ }
+ }
+
+ /* Extra decoding goes here */
+
+#ifdef HAVE_LIBZ
+ if (do_flate) {
+ flatebuf = (char *)malloc(ilen);
+ large_inflate(filtbuf, q, &flatebuf, ilen);
+ free(filtbuf);
+ }
+ else
+#endif
+
+ flatebuf = filtbuf;
+
+ pixel.b[3] = 0;
+ q = 0;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ pixel.b[2] = flatebuf[q++];
+ pixel.b[1] = flatebuf[q++];
+ pixel.b[0] = flatebuf[q++];
+ XPutPixel(iptr->image, x, y, pixel.i);
+ }
+ }
+
+ free(flatebuf);
+
+ fgets(temp, 149, ps); /* definition line */
+ fgets(temp, 149, ps); /* pick up name of image from here */
+ for (pptr = temp; !isspace(*pptr); pptr++);
+ *pptr = '\0';
+ iptr->filename = strdup(temp + 1);
+ for (x = 0; x < 5; x++) fgets(temp, 149, ps); /* skip image dictionary */
+}
+
+/*--------------------------------------------------------------*/
+/* Read an object (page) from a file into xcircuit */
+/*--------------------------------------------------------------*/
+
+Boolean objectread(FILE *ps, objectptr localdata, short offx, short offy,
+ short mode, char *retstr, int ccolor, TechPtr defaulttech)
+{
+ char *temp, *buffer, keyword[80];
+ short tmpfont = -1;
+ float tmpscale = 0.0;
+ objectptr *libobj;
+ int curcolor = ccolor;
+ char *colorkey = NULL;
+ char *widthkey = NULL;
+ int i, j, k;
+ short px, py;
+ objinstptr *newinst;
+ eparamptr epptrx, epptry; /* used for paths only */
+
+ /* path-handling variables */
+ pathptr *newpath;
+ XPoint startpoint;
+
+ keyword[0] = '\0';
+
+ buffer = (char *)malloc(256 * sizeof(char));
+ temp = buffer;
+
+ for(;;) {
+ char *lineptr, *keyptr, *saveptr;
+
+ if (fgets(temp, 255, ps) == NULL) {
+ if (strcmp(keyword, "restore")) {
+ Wprintf("Error: end of file.");
+ *retstr = '\0';
+ }
+ break;
+ }
+ temp = buffer;
+
+ /* because PostScript is a stack language, we will scan from the end */
+ for (lineptr = buffer; (*lineptr != '\n') && (*lineptr != '\0'); lineptr++);
+ /* Avoid CR-LF at EOL added by stupid Windoze programs */
+ if ((lineptr > buffer) && *(lineptr - 1) == '\r') lineptr--;
+ if (lineptr != buffer) { /* ignore any blank lines */
+ for (keyptr = lineptr - 1; isspace(*keyptr) && keyptr != buffer; keyptr--);
+ for (; !isspace(*keyptr) && keyptr != buffer; keyptr--);
+ sscanf(keyptr, "%79s", keyword);
+
+ if (!strcmp(keyword, "showpage")) {
+ strncpy(retstr, buffer, 150);
+ retstr[149] = '\0';
+ free(buffer);
+
+ /* If we have just read a schematic that is attached */
+ /* to a symbol, check all of the pin labels in the symbol */
+ /* to see if they correspond to pin names in the schematic. */
+ /* The other way around (pin in schematic with no */
+ /* corresponding name in the symbol) is not an error. */
+
+ if (localdata->symschem != NULL) {
+ genericptr *pgen, *lgen;
+ labelptr plab, lcmp;
+ for (pgen = localdata->symschem->plist; pgen < localdata->
+ symschem->plist + localdata->symschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plab = TOLABEL(pgen);
+ if (plab->pin == LOCAL) {
+ for (lgen = localdata->plist; lgen < localdata->plist +
+ localdata->parts; lgen++) {
+ if (IS_LABEL(*lgen)) {
+ lcmp = TOLABEL(lgen);
+ if (lcmp->pin == LOCAL)
+ if (!stringcomprelaxed(lcmp->string, plab->string,
+ areawin->topinstance))
+ break;
+ }
+ }
+ if (lgen == localdata->plist + localdata->parts) {
+ char *pch = textprint(plab->string, areawin->topinstance);
+ Fprintf(stderr, "Warning: Unattached pin \"%s\" in "
+ "symbol %s\n", pch,
+ localdata->symschem->name);
+ free(pch);
+ }
+ }
+ }
+ }
+ }
+ return False; /* end of page */
+ }
+
+ /* make a color change, adding the color if necessary */
+
+ else if (!strcmp(keyword, "scb")) {
+ float red, green, blue;
+ if (sscanf(buffer, "%f %f %f", &red, &green, &blue) == 3) {
+ curcolor = rgb_alloccolor((int)(red * 65535), (int)(green * 65535),
+ (int)(blue * 65535));
+ addnewcolorentry(curcolor);
+ colorkey = NULL;
+ }
+ else {
+ char tmpkey[30];
+ oparamptr ops;
+
+ parse_ps_string(buffer, tmpkey, 29, FALSE, TRUE);
+ ops = match_param(localdata, tmpkey);
+ if (ops != NULL) {
+ /* Recast expression parameter, if necessary */
+ if (ops->which == P_EXPRESSION) ops->which = P_COLOR;
+ if (ops->which == P_COLOR) {
+ colorkey = ops->key;
+ switch (ops->type) {
+ case XC_INT:
+ curcolor = ops->parameter.ivalue;
+ break;
+ default:
+ curcolor = DEFAULTCOLOR; /* placeholder */
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* end the color change, returning to default */
+
+ else if (!strcmp(keyword, "sce")) {
+ curcolor = ccolor;
+ colorkey = NULL;
+ }
+
+ /* begin a path constructor */
+
+ else if (!strcmp(keyword, "beginpath")) {
+ px = py = 0;
+
+ NEW_PATH(newpath, localdata);
+ (*newpath)->plist = (genericptr *)malloc(sizeof(genericptr));
+ (*newpath)->parts = 0;
+ (*newpath)->color = curcolor;
+ (*newpath)->passed = NULL;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* check for "addtox" and "addtoy" parameter specification */
+ while (!strncmp(keyptr + 1, "addto", 5)) {
+ saveptr = keyptr + 1;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* Get parameter and its value */
+ if (*(saveptr + 5) == 'x')
+ varpscan(localdata, keyptr + 1, &px, (genericptr)*newpath,
+ -1, offx, P_POSITION_X);
+ else
+ varpscan(localdata, keyptr + 1, &py, (genericptr)*newpath,
+ -1, offy, P_POSITION_Y);
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ }
+
+ lineptr = varpathscan(localdata, buffer, &startpoint.x,
+ (genericptr *)NULL, *newpath, 0, offx + px, P_POSITION_X,
+ &epptrx);
+ lineptr = varpathscan(localdata, lineptr, &startpoint.y,
+ (genericptr *)NULL, *newpath, 0, offy + py, P_POSITION_Y,
+ &epptry);
+
+ std_eparam((genericptr)(*newpath), colorkey);
+ }
+
+ /* end the path constructor */
+
+ else if (!strcmp(keyword, "endpath")) {
+
+ lineptr = varscan(localdata, buffer, &(*newpath)->style,
+ (genericptr)*newpath, P_STYLE);
+ lineptr = varfscan(localdata, lineptr, &(*newpath)->width,
+ (genericptr)*newpath, P_LINEWIDTH);
+
+ if ((*newpath)->parts <= 0) { /* in case of an empty path */
+ free((*newpath)->plist);
+ free(*newpath);
+ localdata->parts--;
+ }
+ newpath = NULL;
+ }
+
+ /* read path parts */
+
+ else if (!strcmp(keyword, "polyc")) {
+ polyptr *newpoly;
+ pointlist newpoints;
+ short tmpnum;
+
+ px = py = 0;
+
+ NEW_POLY(newpoly, (*newpath));
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* check for "addtox" and "addtoy" parameter specification */
+ while (!strncmp(keyptr + 1, "addto", 5)) {
+ saveptr = keyptr + 1;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* Get parameter and its value */
+ if (*(saveptr + 5) == 'x')
+ varpscan(localdata, keyptr + 1, &px, (genericptr)*newpoly,
+ -1, offx, P_POSITION_X);
+ else
+ varpscan(localdata, keyptr + 1, &py, (genericptr)*newpoly,
+ -1, offy, P_POSITION_Y);
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ }
+
+ sscanf(keyptr, "%hd", &tmpnum);
+ (*newpoly)->number = tmpnum + 1;
+ (*newpoly)->width = 1.0;
+ (*newpoly)->style = UNCLOSED;
+ (*newpoly)->color = curcolor;
+ (*newpoly)->passed = NULL;
+ (*newpoly)->cycle = NULL;
+
+ (*newpoly)->points = (pointlist) malloc((*newpoly)->number *
+ sizeof(XPoint));
+
+ /* If the last point on the last path part was parameterized, then */
+ /* the first point of the spline must be, too. */
+
+ if (epptrx != NULL) {
+ eparamptr newepp = copyeparam(epptrx, (genericptr)(*newpath));
+ newepp->next = (*newpath)->passed;
+ (*newpath)->passed = newepp;
+ newepp->pdata.pathpt[1] = 0;
+ newepp->pdata.pathpt[0] = (*newpath)->parts - 1;
+ }
+ if (epptry != NULL) {
+ eparamptr newepp = copyeparam(epptry, (genericptr)(*newpath));
+ newepp->next = (*newpath)->passed;
+ (*newpath)->passed = newepp;
+ newepp->pdata.pathpt[1] = 0;
+ newepp->pdata.pathpt[0] = (*newpath)->parts - 1;
+ }
+
+ lineptr = buffer;
+
+ newpoints = (*newpoly)->points + (*newpoly)->number - 1;
+ lineptr = varpathscan(localdata, lineptr, &newpoints->x,
+ (genericptr *)newpoly, *newpath, newpoints - (*newpoly)->points,
+ offx + px, P_POSITION_X, &epptrx);
+ lineptr = varpathscan(localdata, lineptr, &newpoints->y,
+ (genericptr *)newpoly, *newpath, newpoints - (*newpoly)->points,
+ offy + py, P_POSITION_Y, &epptry);
+
+ for (--newpoints; newpoints > (*newpoly)->points; newpoints--) {
+
+ lineptr = varpathscan(localdata, lineptr, &newpoints->x,
+ (genericptr *)newpoly, *newpath, newpoints - (*newpoly)->points,
+ offx + px, P_POSITION_X, NULL);
+ lineptr = varpathscan(localdata, lineptr, &newpoints->y,
+ (genericptr *)newpoly, *newpath, newpoints - (*newpoly)->points,
+ offy + py, P_POSITION_Y, NULL);
+ }
+ newpoints->x = startpoint.x;
+ newpoints->y = startpoint.y;
+ startpoint.x = (newpoints + (*newpoly)->number - 1)->x;
+ startpoint.y = (newpoints + (*newpoly)->number - 1)->y;
+ }
+
+ else if (!strcmp(keyword, "arc") || !strcmp(keyword, "arcn")) {
+ arcptr *newarc;
+ NEW_ARC(newarc, (*newpath));
+ (*newarc)->width = 1.0;
+ (*newarc)->style = UNCLOSED;
+ (*newarc)->color = curcolor;
+ (*newarc)->passed = NULL;
+ (*newarc)->cycle = NULL;
+
+ lineptr = varpscan(localdata, buffer, &(*newarc)->position.x,
+ (genericptr)*newarc, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.y,
+ (genericptr)*newarc, 0, offy, P_POSITION_Y);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->radius,
+ (genericptr)*newarc, P_RADIUS);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle1,
+ (genericptr)*newarc, P_ANGLE1);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle2,
+ (genericptr)*newarc, P_ANGLE2);
+
+ (*newarc)->yaxis = (*newarc)->radius;
+ if (!strcmp(keyword, "arcn")) {
+ float tmpang = (*newarc)->angle1;
+ (*newarc)->radius = -((*newarc)->radius);
+ (*newarc)->angle1 = (*newarc)->angle2;
+ (*newarc)->angle2 = tmpang;
+ }
+
+ calcarc(*newarc);
+ startpoint.x = (short)(*newarc)->points[(*newarc)->number - 1].x;
+ startpoint.y = (short)(*newarc)->points[(*newarc)->number - 1].y;
+ decomposearc(*newpath);
+ }
+
+ else if (!strcmp(keyword, "pellip") || !strcmp(keyword, "nellip")) {
+ arcptr *newarc;
+ NEW_ARC(newarc, (*newpath));
+ (*newarc)->width = 1.0;
+ (*newarc)->style = UNCLOSED;
+ (*newarc)->color = curcolor;
+ (*newarc)->passed = NULL;
+ (*newarc)->cycle = NULL;
+
+ lineptr = varpscan(localdata, buffer, &(*newarc)->position.x,
+ (genericptr)*newarc, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.y,
+ (genericptr)*newarc, 0, offy, P_POSITION_Y);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->radius,
+ (genericptr)*newarc, P_RADIUS);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->yaxis,
+ (genericptr)*newarc, P_MINOR_AXIS);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle1,
+ (genericptr)*newarc, P_ANGLE1);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle2,
+ (genericptr)*newarc, P_ANGLE2);
+
+ if (!strcmp(keyword, "nellip")) {
+ float tmpang = (*newarc)->angle1;
+ (*newarc)->radius = -((*newarc)->radius);
+ (*newarc)->angle1 = (*newarc)->angle2;
+ (*newarc)->angle2 = tmpang;
+
+ }
+ calcarc(*newarc);
+ startpoint.x = (short)(*newarc)->points[(*newarc)->number - 1].x;
+ startpoint.y = (short)(*newarc)->points[(*newarc)->number - 1].y;
+ decomposearc(*newpath);
+ }
+
+ else if (!strcmp(keyword, "curveto")) {
+ splineptr *newspline;
+ px = py = 0;
+
+ NEW_SPLINE(newspline, (*newpath));
+ (*newspline)->passed = NULL;
+ (*newspline)->cycle = NULL;
+ (*newspline)->width = 1.0;
+ (*newspline)->style = UNCLOSED;
+ (*newspline)->color = curcolor;
+
+ /* If the last point on the last path part was parameterized, then */
+ /* the first point of the spline must be, too. */
+
+ if (epptrx != NULL) {
+ eparamptr newepp = copyeparam(epptrx, (genericptr)(*newpath));
+ newepp->next = (*newpath)->passed;
+ (*newpath)->passed = newepp;
+ newepp->pdata.pathpt[1] = 0;
+ newepp->pdata.pathpt[0] = (*newpath)->parts - 1;
+ }
+ if (epptry != NULL) {
+ eparamptr newepp = copyeparam(epptry, (genericptr)(*newpath));
+ newepp->next = (*newpath)->passed;
+ (*newpath)->passed = newepp;
+ newepp->pdata.pathpt[1] = 0;
+ newepp->pdata.pathpt[0] = (*newpath)->parts - 1;
+ }
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* check for "addtox" and "addtoy" parameter specification */
+ while (!strncmp(keyptr + 1, "addto", 5)) {
+ saveptr = keyptr + 1;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* Get parameter and its value */
+ if (*(saveptr + 5) == 'x')
+ varpscan(localdata, keyptr + 1, &px, (genericptr)*newspline,
+ -1, offx, P_POSITION_X);
+ else
+ varpscan(localdata, keyptr + 1, &py, (genericptr)*newspline,
+ -1, offy, P_POSITION_Y);
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ }
+
+
+ lineptr = varpathscan(localdata, buffer, &(*newspline)->ctrl[1].x,
+ (genericptr *)newspline, *newpath, 1, offx + px, P_POSITION_X,
+ NULL);
+ lineptr = varpathscan(localdata, lineptr, &(*newspline)->ctrl[1].y,
+ (genericptr *)newspline, *newpath, 1, offy + py, P_POSITION_Y,
+ NULL);
+ lineptr = varpathscan(localdata, lineptr, &(*newspline)->ctrl[2].x,
+ (genericptr *)newspline, *newpath, 2, offx + px, P_POSITION_X,
+ NULL);
+ lineptr = varpathscan(localdata, lineptr, &(*newspline)->ctrl[2].y,
+ (genericptr *)newspline, *newpath, 2, offy + py, P_POSITION_Y,
+ NULL);
+ lineptr = varpathscan(localdata, lineptr, &(*newspline)->ctrl[3].x,
+ (genericptr *)newspline, *newpath, 3, offx + px, P_POSITION_X,
+ &epptrx);
+ lineptr = varpathscan(localdata, lineptr, &(*newspline)->ctrl[3].y,
+ (genericptr *)newspline, *newpath, 3, offy + py, P_POSITION_Y,
+ &epptry);
+
+ (*newspline)->ctrl[0].x = startpoint.x;
+ (*newspline)->ctrl[0].y = startpoint.y;
+
+ calcspline(*newspline);
+ startpoint.x = (*newspline)->ctrl[3].x;
+ startpoint.y = (*newspline)->ctrl[3].y;
+ }
+
+ /* read arcs */
+
+ else if (!strcmp(keyword, "xcarc")) {
+ arcptr *newarc;
+
+ NEW_ARC(newarc, localdata);
+ (*newarc)->color = curcolor;
+ (*newarc)->passed = NULL;
+ (*newarc)->cycle = NULL;
+
+ /* backward compatibility */
+ if (version < 1.5) {
+ sscanf(buffer, "%hd %hd %hd %f %f %f %hd", &(*newarc)->position.x,
+ &(*newarc)->position.y, &(*newarc)->radius, &(*newarc)->angle1,
+ &(*newarc)->angle2, &(*newarc)->width, &(*newarc)->style);
+ (*newarc)->position.x -= offx;
+ (*newarc)->position.y -= offy;
+ }
+ else {
+ lineptr = varscan(localdata, buffer, &(*newarc)->style,
+ (genericptr)*newarc, P_STYLE);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->width,
+ (genericptr)*newarc, P_LINEWIDTH);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.x,
+ (genericptr)*newarc, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.y,
+ (genericptr)*newarc, 0, offy, P_POSITION_Y);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->radius,
+ (genericptr)*newarc, P_RADIUS);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle1,
+ (genericptr)*newarc, P_ANGLE1);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle2,
+ (genericptr)*newarc, P_ANGLE2);
+ }
+
+ (*newarc)->yaxis = (*newarc)->radius;
+ calcarc(*newarc);
+ std_eparam((genericptr)(*newarc), colorkey);
+ }
+
+ /* read ellipses */
+
+ else if (!strcmp(keyword, "ellipse")) {
+ arcptr *newarc;
+
+ NEW_ARC(newarc, localdata);
+
+ (*newarc)->color = curcolor;
+ (*newarc)->passed = NULL;
+ (*newarc)->cycle = NULL;
+
+ lineptr = varscan(localdata, buffer, &(*newarc)->style,
+ (genericptr)*newarc, P_STYLE);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->width,
+ (genericptr)*newarc, P_LINEWIDTH);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.x,
+ (genericptr)*newarc, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newarc)->position.y,
+ (genericptr)*newarc, 0, offy, P_POSITION_Y);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->radius,
+ (genericptr)*newarc, P_RADIUS);
+ lineptr = varscan(localdata, lineptr, &(*newarc)->yaxis,
+ (genericptr)*newarc, P_MINOR_AXIS);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle1,
+ (genericptr)*newarc, P_ANGLE1);
+ lineptr = varfscan(localdata, lineptr, &(*newarc)->angle2,
+ (genericptr)*newarc, P_ANGLE2);
+
+ calcarc(*newarc);
+ std_eparam((genericptr)(*newarc), colorkey);
+ }
+
+ /* read polygons */
+ /* (and wires---backward compatibility for v1.5 and earlier) */
+
+ else if (!strcmp(keyword, "polygon") || !strcmp(keyword, "wire")) {
+ polyptr *newpoly;
+ pointlist newpoints;
+ px = py = 0;
+
+ NEW_POLY(newpoly, localdata);
+ lineptr = buffer;
+
+ (*newpoly)->passed = NULL;
+ (*newpoly)->cycle = NULL;
+
+ if (!strcmp(keyword, "wire")) {
+ (*newpoly)->number = 2;
+ (*newpoly)->width = 1.0;
+ (*newpoly)->style = UNCLOSED;
+ }
+ else {
+ /* backward compatibility */
+ if (version < 1.5) {
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ sscanf(keyptr, "%hd", &(*newpoly)->style);
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ sscanf(keyptr, "%f", &(*newpoly)->width);
+ }
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ /* check for "addtox" and "addtoy" parameter specification */
+ while (!strncmp(keyptr + 1, "addto", 5)) {
+ saveptr = keyptr + 1;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* Get parameter and its value */
+ if (*(saveptr + 5) == 'x')
+ varpscan(localdata, keyptr + 1, &px, (genericptr)*newpoly,
+ -1, offx, P_POSITION_X);
+ else
+ varpscan(localdata, keyptr + 1, &py, (genericptr)*newpoly,
+ -1, offy, P_POSITION_Y);
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ }
+ sscanf(keyptr, "%hd", &(*newpoly)->number);
+
+ if (version >= 1.5) {
+ lineptr = varscan(localdata, lineptr, &(*newpoly)->style,
+ (genericptr)*newpoly, P_STYLE);
+ lineptr = varfscan(localdata, lineptr, &(*newpoly)->width,
+ (genericptr)*newpoly, P_LINEWIDTH);
+ }
+ }
+
+ if ((*newpoly)->style & BBOX)
+ (*newpoly)->color = BBOXCOLOR;
+ else
+ (*newpoly)->color = curcolor;
+ (*newpoly)->points = (pointlist) malloc((*newpoly)->number *
+ sizeof(XPoint));
+
+ for (newpoints = (*newpoly)->points; newpoints < (*newpoly)->points
+ + (*newpoly)->number; newpoints++) {
+ lineptr = varpscan(localdata, lineptr, &newpoints->x,
+ (genericptr)*newpoly, newpoints - (*newpoly)->points,
+ offx + px, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &newpoints->y,
+ (genericptr)*newpoly, newpoints - (*newpoly)->points,
+ offy + py, P_POSITION_Y);
+ }
+ std_eparam((genericptr)(*newpoly), colorkey);
+ }
+
+ /* read spline curves */
+
+ else if (!strcmp(keyword, "spline")) {
+ splineptr *newspline;
+ px = py = 0;
+
+ NEW_SPLINE(newspline, localdata);
+ (*newspline)->color = curcolor;
+ (*newspline)->passed = NULL;
+ (*newspline)->cycle = NULL;
+
+ /* backward compatibility */
+ if (version < 1.5) {
+ sscanf(buffer, "%f %hd %hd %hd %hd %hd %hd %hd %hd %hd",
+ &(*newspline)->width, &(*newspline)->ctrl[1].x,
+ &(*newspline)->ctrl[1].y, &(*newspline)->ctrl[2].x,
+ &(*newspline)->ctrl[2].y, &(*newspline)->ctrl[3].x,
+ &(*newspline)->ctrl[3].y, &(*newspline)->ctrl[0].x,
+ &(*newspline)->ctrl[0].y, &(*newspline)->style);
+ (*newspline)->ctrl[1].x -= offx; (*newspline)->ctrl[2].x -= offx;
+ (*newspline)->ctrl[0].x -= offx;
+ (*newspline)->ctrl[3].x -= offx;
+ (*newspline)->ctrl[1].y -= offy; (*newspline)->ctrl[2].y -= offy;
+ (*newspline)->ctrl[3].y -= offy;
+ (*newspline)->ctrl[0].y -= offy;
+ }
+ else {
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ /* check for "addtox" and "addtoy" parameter specification */
+ while (!strncmp(keyptr + 1, "addto", 5)) {
+ saveptr = keyptr + 1;
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+
+ /* Get parameter and its value */
+ if (*(saveptr + 5) == 'x')
+ varpscan(localdata, keyptr + 1, &px, (genericptr)*newspline,
+ -1, offx, P_POSITION_X);
+ else
+ varpscan(localdata, keyptr + 1, &py, (genericptr)*newspline,
+ -1, offy, P_POSITION_Y);
+
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; *keyptr != ' '; keyptr--);
+ }
+
+ lineptr = varscan(localdata, buffer, &(*newspline)->style,
+ (genericptr)*newspline, P_STYLE);
+ lineptr = varfscan(localdata, lineptr, &(*newspline)->width,
+ (genericptr)*newspline, P_LINEWIDTH);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[1].x,
+ (genericptr)*newspline, 1, offx + px, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[1].y,
+ (genericptr)*newspline, 1, offy + py, P_POSITION_Y);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[2].x,
+ (genericptr)*newspline, 2, offx + px, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[2].y,
+ (genericptr)*newspline, 2, offy + py, P_POSITION_Y);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[3].x,
+ (genericptr)*newspline, 3, offx + px, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[3].y,
+ (genericptr)*newspline, 3, offy + py, P_POSITION_Y);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[0].x,
+ (genericptr)*newspline, 0, offx + px, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newspline)->ctrl[0].y,
+ (genericptr)*newspline, 0, offy + py, P_POSITION_Y);
+
+ /* check for "addtox" and "addtoy" parameter specification */
+ }
+
+ calcspline(*newspline);
+ std_eparam((genericptr)(*newspline), colorkey);
+ }
+
+ /* read graphics image instances */
+
+ else if (!strcmp(keyword, "graphic")) {
+ graphicptr *newgp;
+ Imagedata *img;
+
+ lineptr = buffer + 1;
+ for (i = 0; i < xobjs.images; i++) {
+ img = xobjs.imagelist + i;
+ if (!strncmp(img->filename, lineptr, strlen(img->filename))) {
+ NEW_GRAPHIC(newgp, localdata);
+ (*newgp)->color = curcolor;
+ (*newgp)->passed = NULL;
+ (*newgp)->clipmask = (Pixmap)NULL;
+ (*newgp)->target = NULL;
+ (*newgp)->valid = False;
+ (*newgp)->source = img->image;
+ img->refcount++;
+ lineptr += strlen(img->filename) + 1;
+ break;
+ }
+ }
+ if (i == xobjs.images) {
+ /* Error: Line points to a non-existant image (no data) */
+ /* See if we can load the image name as a filename, and */
+ /* if that fails, then we must throw an error and ignore */
+ /* the image element. */
+
+ graphicptr locgp;
+ char *sptr = strchr(lineptr, ' ');
+
+ if (sptr != NULL)
+ *sptr = '\0';
+ else
+ sptr = lineptr;
+ locgp = new_graphic(NULL, lineptr, 0, 0);
+
+ if (locgp == NULL) {
+ Fprintf(stderr, "Error: No graphic data for \"%s\".\n",
+ lineptr);
+ newgp = NULL;
+ }
+ else {
+ lineptr = sptr;
+ newgp = &locgp;
+ }
+ }
+
+ if ((newgp != NULL) && (*newgp != NULL)) {
+ lineptr = varfscan(localdata, lineptr, &(*newgp)->scale,
+ (genericptr)*newgp, P_SCALE);
+ lineptr = varscan(localdata, lineptr, &(*newgp)->rotation,
+ (genericptr)*newgp, P_ROTATION);
+ lineptr = varpscan(localdata, lineptr, &(*newgp)->position.x,
+ (genericptr)*newgp, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newgp)->position.y,
+ (genericptr)*newgp, 0, offy, P_POSITION_Y);
+ std_eparam((genericptr)(*newgp), colorkey);
+ }
+ }
+
+ /* read labels */
+
+ else if (!strcmp(keyword, "fontset")) { /* old style */
+ char tmpstring[100];
+ int i;
+ sscanf(buffer, "%f %*c%99s", &tmpscale, tmpstring);
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(tmpstring, fonts[i].psname)) {
+ tmpfont = i;
+ break;
+ }
+ if (i == fontcount) i = 0; /* Why bother with anything fancy? */
+ }
+
+ else if (!strcmp(keyword, "label") || !strcmp(keyword, "pinlabel")
+ || !strcmp(keyword, "pinglobal") || !strcmp(keyword, "infolabel")) {
+
+ labelptr *newlabel;
+ stringpart *firstscale, *firstfont;
+
+ NEW_LABEL(newlabel, localdata);
+ (*newlabel)->color = curcolor;
+ (*newlabel)->string = NULL;
+ (*newlabel)->passed = NULL;
+ (*newlabel)->cycle = NULL;
+
+ /* scan backwards to get the number of substrings */
+ lineptr = keyptr - 1;
+ for (i = 0; i < ((version < 2.25) ? 5 : 6); i++) {
+ for (; *lineptr == ' '; lineptr--);
+ for (; *lineptr != ' '; lineptr--);
+ }
+ if ((strchr(lineptr, '.') != NULL) && (version < 2.25)) {
+ Fprintf(stderr, "Error: File version claims to be %2.1f,"
+ " but has version %2.1f labels\n", version, PROG_VERSION);
+ Fprintf(stderr, "Attempting to resolve problem by updating version.\n");
+ version = PROG_VERSION;
+ for (; *lineptr == ' '; lineptr--);
+ for (; *lineptr != ' '; lineptr--);
+ }
+ /* no. segments is ignored---may be a derived quantity, anyway */
+ if (version < 2.25) {
+ sscanf(lineptr, "%*s %hd %hd %hd %hd", &(*newlabel)->justify,
+ &(*newlabel)->rotation, &(*newlabel)->position.x,
+ &(*newlabel)->position.y);
+ (*newlabel)->position.x -= offx; (*newlabel)->position.y -= offy;
+ *lineptr = '\0';
+ }
+ else {
+ *lineptr++ = '\0';
+ lineptr = advancetoken(lineptr); /* skip string token */
+ lineptr = varscan(localdata, lineptr, &(*newlabel)->justify,
+ (genericptr)*newlabel, P_JUSTIFY);
+ lineptr = varscan(localdata, lineptr, &(*newlabel)->rotation,
+ (genericptr)*newlabel, P_ROTATION);
+ lineptr = varfscan(localdata, lineptr, &(*newlabel)->scale,
+ (genericptr)*newlabel, P_SCALE);
+ lineptr = varpscan(localdata, lineptr, &(*newlabel)->position.x,
+ (genericptr)*newlabel, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newlabel)->position.y,
+ (genericptr)*newlabel, 0, offy, P_POSITION_Y);
+ }
+ if (version < 2.4)
+ (*newlabel)->rotation = -(*newlabel)->rotation;
+ while ((*newlabel)->rotation < 0) (*newlabel)->rotation += 360;
+
+ (*newlabel)->pin = False;
+ if (strcmp(keyword, "label")) { /* all the schematic types */
+ /* enable schematic capture if it is not already on. */
+ if (!strcmp(keyword, "pinlabel"))
+ (*newlabel)->pin = LOCAL;
+ else if (!strcmp(keyword, "pinglobal"))
+ (*newlabel)->pin = GLOBAL;
+ else if (!strcmp(keyword, "infolabel")) {
+ /* Do not turn top-level pages into symbols! */
+ /* Info labels on schematics are treated differently. */
+ if (localdata != topobject)
+ localdata->schemtype = FUNDAMENTAL;
+ (*newlabel)->pin = INFO;
+ if (curcolor == DEFAULTCOLOR)
+ (*newlabel)->color = INFOLABELCOLOR;
+ }
+ }
+
+ lineptr = buffer; /* back to beginning of string */
+ if (!strncmp(lineptr, "mark", 4)) lineptr += 4;
+
+ readlabel(localdata, lineptr, &(*newlabel)->string);
+ CheckMarginStop(*newlabel, areawin->topinstance, FALSE);
+
+ if (version < 2.25) {
+ /* Switch 1st scale designator to overall font scale */
+
+ firstscale = (*newlabel)->string->nextpart;
+ if (firstscale->type != FONT_SCALE) {
+ if (tmpscale != 0.0)
+ (*newlabel)->scale = 0.0;
+ else
+ (*newlabel)->scale = 1.0;
+ }
+ else {
+ (*newlabel)->scale = firstscale->data.scale;
+ deletestring(firstscale, &((*newlabel)->string),
+ areawin->topinstance);
+ }
+ }
+
+ firstfont = (*newlabel)->string;
+ if ((firstfont == NULL) || (firstfont->type != FONT_NAME)) {
+ if (tmpfont == -1) {
+ Fprintf(stderr, "Error: Label with no font designator?\n");
+ tmpfont = 0;
+ }
+ firstfont = makesegment(&((*newlabel)->string), (*newlabel)->string);
+ firstfont->type = FONT_NAME;
+ firstfont->data.font = tmpfont;
+ }
+ cleanuplabel(&(*newlabel)->string);
+
+ std_eparam((genericptr)(*newlabel), colorkey);
+ }
+
+ /* read symbol-to-schematic connection */
+
+ else if (!strcmp(keyword, "is_schematic")) {
+ char tempstr[50];
+ for (lineptr = buffer; *lineptr == ' '; lineptr++);
+ parse_ps_string(++lineptr, tempstr, 49, FALSE, FALSE);
+ checksym(localdata, tempstr);
+ }
+
+ /* read bounding box (font files only) */
+
+ else if (!strcmp(keyword, "bbox")) {
+ for (lineptr = buffer; *lineptr == ' '; lineptr++);
+ if (*lineptr != '%') {
+ Wprintf("Illegal bbox.");
+ free(buffer);
+ *retstr = '\0';
+ return True;
+ }
+ sscanf(++lineptr, "%hd %hd %hd %hd",
+ &localdata->bbox.lowerleft.x, &localdata->bbox.lowerleft.y,
+ &localdata->bbox.width, &localdata->bbox.height);
+ }
+
+ /* read "hidden" attribute */
+
+ else if (!strcmp(keyword, "hidden")) {
+ localdata->hidden = True;
+ }
+
+ /* read "libinst" special instance of a library part */
+
+ else if (!strcmp(keyword, "libinst")) {
+
+ /* Read backwards from keyword to find name of object instanced. */
+ for (lineptr = keyptr; *lineptr != '/' && lineptr > buffer;
+ lineptr--);
+ parse_ps_string(++lineptr, keyword, 79, FALSE, FALSE);
+ new_library_instance(mode - LIBRARY, keyword, buffer, defaulttech);
+ }
+
+ /* read objects */
+
+ else if (!strcmp(keyword, "{")) { /* This is an object definition */
+ objlistptr redef;
+ objectptr *newobject;
+
+ for (lineptr = buffer; *lineptr == ' '; lineptr++);
+ if (*lineptr++ != '/') {
+ /* This may be part of a label. . . treat as a continuation line */
+ temp = continueline(&buffer);
+ continue;
+ }
+ parse_ps_string(lineptr, keyword, 79, FALSE, FALSE);
+
+ newobject = new_library_object(mode, keyword, &redef, defaulttech);
+
+ if (objectread(ps, *newobject, 0, 0, mode, retstr, curcolor,
+ defaulttech) == True) {
+ strncpy(retstr, buffer, 150);
+ retstr[149] = '\0';
+ free(buffer);
+ return True;
+ }
+ else {
+ if (library_object_unique(mode, *newobject, redef))
+ add_object_to_library(mode, *newobject);
+ }
+ }
+ else if (!strcmp(keyword, "def")) {
+ strncpy(retstr, buffer, 150);
+ retstr[149] = '\0';
+ free (buffer);
+ return False; /* end of object def or end of object library */
+ }
+
+ else if (!strcmp(keyword, "loadfontencoding")) {
+ /* Deprecated, but retained for backward compatibility. */
+ /* Load from script, .xcircuitrc, or command line instead. */
+ for (lineptr = buffer; *lineptr != '%'; lineptr++);
+ sscanf (lineptr + 1, "%149s", _STR);
+ if (*(lineptr + 1) != '%') loadfontfile(_STR);
+ }
+ else if (!strcmp(keyword, "loadlibrary")) {
+ /* Deprecated, but retained for backward compatibility */
+ /* Load from script, .xcircuitrc, or command line instead. */
+ int ilib, tlib;
+
+ for (lineptr = buffer; *lineptr != '%'; lineptr++);
+ sscanf (++lineptr, "%149s", _STR);
+ while (isspace(*lineptr)) lineptr++;
+ while (!isspace(*++lineptr));
+ while (isspace(*++lineptr));
+ if (sscanf (lineptr, "%d", &ilib) > 0) {
+ while ((ilib - 2 + LIBRARY) > xobjs.numlibs) {
+ tlib = createlibrary(False);
+ if (tlib != xobjs.numlibs - 2 + LIBRARY) {
+ ilib = tlib;
+ break;
+ }
+ }
+ mode = ilib - 1 + LIBRARY;
+ }
+ loadlibrary(mode);
+ }
+ else if (!strcmp(keyword, "beginparm")) { /* parameterized object */
+ short tmpnum, i;
+ for (--keyptr; *keyptr == ' '; keyptr--);
+ for (; isdigit(*keyptr) && (keyptr >= buffer); keyptr--);
+ sscanf(keyptr, "%hd", &tmpnum);
+ lineptr = buffer;
+ while (isspace(*lineptr)) lineptr++;
+
+ if (tmpnum < 256) { /* read parameter defaults in order */
+ stringpart *newpart;
+ /* oparamptr newops; (jdk) */
+
+ for (i = 0; i < tmpnum; i++) {
+ oparamptr newops;
+
+ newops = (oparamptr)malloc(sizeof(oparam));
+ newops->next = localdata->params;
+ localdata->params = newops;
+ newops->key = (char *)malloc(6);
+ sprintf(newops->key, "v%d", i + 1);
+
+ if (*lineptr == '(' || *lineptr == '{') { /* type is XC_STRING */
+ char *linetmp, csave;
+
+ newops->parameter.string = NULL;
+
+ /* get simple substring or set of substrings and commands */
+ linetmp = find_delimiter(lineptr);
+ csave = *(++linetmp);
+ *linetmp = '\0';
+ if (*lineptr == '{') lineptr++;
+ readlabel(localdata, lineptr, &(newops->parameter.string));
+
+ /* Add the ending part to the parameter string */
+ newpart = makesegment(&(newops->parameter.string), NULL);
+ newpart->type = PARAM_END;
+ newpart->data.string = (u_char *)NULL;
+
+ newops->type = (u_char)XC_STRING;
+ newops->which = P_SUBSTRING;
+ /* Fprintf(stdout, "Parameter %d to object %s defaults "
+ "to string \"%s\"\n", i + 1, localdata->name,
+ ops->parameter.string); */
+ *linetmp = csave;
+ lineptr = linetmp;
+ while (isspace(*lineptr)) lineptr++;
+ }
+ else { /* type is assumed to be XC_FLOAT */
+ newops->type = (u_char)XC_FLOAT;
+ sscanf(lineptr, "%g", &newops->parameter.fvalue);
+ /* Fprintf(stdout, "Parameter %s to object %s defaults to "
+ "value %g\n", newops->key, localdata->name,
+ newops->parameter.fvalue); */
+ lineptr = advancetoken(lineptr);
+ }
+ }
+ }
+ }
+ else if (!strcmp(keyword, "nonetwork")) {
+ localdata->valid = True;
+ localdata->schemtype = NONETWORK;
+ }
+ else if (!strcmp(keyword, "trivial")) {
+ localdata->schemtype = TRIVIAL;
+ }
+ else if (!strcmp(keyword, "begingate")) {
+ localdata->params = NULL;
+ /* read dictionary of parameter key:value pairs */
+ readparams(NULL, NULL, localdata, buffer);
+ }
+
+ else if (!strcmp(keyword, "%%Trailer")) break;
+ else if (!strcmp(keyword, "EndLib")) break;
+ else if (!strcmp(keyword, "restore")); /* handled at top */
+ else if (!strcmp(keyword, "grestore")); /* ignore */
+ else if (!strcmp(keyword, "endgate")); /* also ignore */
+ else if (!strcmp(keyword, "xyarray")); /* ignore for now */
+ else {
+ char *tmpptr, *libobjname, *objnamestart;
+ Boolean matchtech, found = False;
+
+ /* First, make sure this is not a general comment line */
+ /* Return if we have a page boundary */
+ /* Read an image if this is an imagedata line. */
+
+ for (tmpptr = buffer; isspace(*tmpptr); tmpptr++);
+ if (*tmpptr == '%') {
+ if (strstr(buffer, "%%Page:") == tmpptr) {
+ strncpy(retstr, buffer, 150);
+ retstr[149] = '\0';
+ free (buffer);
+ return True;
+ }
+ else if (strstr(buffer, "%imagedata") == tmpptr) {
+ int width, height;
+ sscanf(buffer, "%*s %d %d", &width, &height);
+ readimagedata(ps, width, height);
+ }
+ continue;
+ }
+
+ parse_ps_string(keyword, keyword, 79, FALSE, FALSE);
+ matchtech = (strstr(keyword, "::") == NULL) ? FALSE : TRUE;
+
+ /* If the file contains a reference to a bare-word device */
+ /* without a technology prefix, then it is probably an */
+ /* older-version file. If this is the case, then the file */
+ /* should define an unprefixed object, which will be given */
+ /* a null prefix (just "::" by itself). Look for that */
+ /* match. */
+
+ /* (Assume that this line calls an object instance) */
+ /* Double loop through user libraries */
+
+ for (k = 0; k < ((mode == FONTLIB) ? 1 : xobjs.numlibs); k++) {
+ for (j = 0; j < ((mode == FONTLIB) ? xobjs.fontlib.number :
+ xobjs.userlibs[k].number); j++) {
+
+ libobj = (mode == FONTLIB) ? xobjs.fontlib.library + j :
+ xobjs.userlibs[k].library + j;
+
+ /* Objects which have a technology ("<lib>::<obj>") */
+ /* must compare exactly. Objects which don't can */
+ /* only match an object of the same name with a null */
+ /* technology prefix. */
+
+ libobjname = (*libobj)->name;
+ if (!matchtech) {
+ objnamestart = strstr(libobjname, "::");
+ if (objnamestart != NULL) libobjname = objnamestart + 2;
+ }
+ if (!objnamecmp(keyword, libobjname)) {
+
+ /* If the name is not exactly the same (appended underscores) */
+ /* check if the name is on the list of aliases. */
+
+ if (strcmp(keyword, libobjname)) {
+ Boolean is_alias = False;
+ aliasptr ckalias = aliastop;
+ slistptr sref;
+
+ for (; ckalias != NULL; ckalias = ckalias->next) {
+ if (ckalias->baseobj == (*libobj)) {
+ sref = ckalias->aliases;
+ for (; sref != NULL; sref = sref->next) {
+ if (!strcmp(keyword, sref->alias)) {
+ is_alias = True;
+ break;
+ }
+ }
+ if (is_alias) break;
+ }
+ }
+ if (!is_alias) continue;
+ }
+
+ if (!matchtech && ((*libobj)->name != objnamestart))
+ if (version > 3.7)
+ continue; // no prefix in file must match
+ // null prefix in library object.
+
+ found = True;
+ NEW_OBJINST(newinst, localdata);
+ (*newinst)->thisobject = *libobj;
+ (*newinst)->color = curcolor;
+ (*newinst)->params = NULL;
+ (*newinst)->passed = NULL;
+ (*newinst)->bbox.lowerleft.x = (*libobj)->bbox.lowerleft.x;
+ (*newinst)->bbox.lowerleft.y = (*libobj)->bbox.lowerleft.y;
+ (*newinst)->bbox.width = (*libobj)->bbox.width;
+ (*newinst)->bbox.height = (*libobj)->bbox.height;
+ (*newinst)->schembbox = NULL;
+
+ lineptr = varfscan(localdata, buffer, &(*newinst)->scale,
+ (genericptr)*newinst, P_SCALE);
+
+ /* Format prior to xcircuit 3.7 did not have scale- */
+ /* invariant linewidth. If scale is 1, though, keep it */
+ /* invariant so as not to overuse the scale-variance */
+ /* flag in the output file. */
+
+ if ((version < 3.7) && ((*newinst)->scale != 1.0))
+ (*newinst)->style = NORMAL;
+ else
+ (*newinst)->style = LINE_INVARIANT;
+
+ lineptr = varscan(localdata, lineptr, &(*newinst)->rotation,
+ (genericptr)*newinst, P_ROTATION);
+ lineptr = varpscan(localdata, lineptr, &(*newinst)->position.x,
+ (genericptr)*newinst, 0, offx, P_POSITION_X);
+ lineptr = varpscan(localdata, lineptr, &(*newinst)->position.y,
+ (genericptr)*newinst, 0, offy, P_POSITION_Y);
+
+ /* Negative rotations = flip in x in version 2.3.6 and */
+ /* earlier. Later versions don't allow negative rotation */
+
+ if (version < 2.4) {
+ if ((*newinst)->rotation < 0) {
+ (*newinst)->scale = -((*newinst)->scale);
+ (*newinst)->rotation++;
+ }
+ (*newinst)->rotation = -(*newinst)->rotation;
+ }
+
+ while ((*newinst)->rotation > 360) (*newinst)->rotation -= 360;
+ while ((*newinst)->rotation < 0) (*newinst)->rotation += 360;
+
+ std_eparam((genericptr)(*newinst), colorkey);
+
+ /* Does this instance contain parameters? */
+ readparams(localdata, *newinst, *libobj, buffer);
+
+ calcbboxinst(*newinst);
+
+ break;
+
+ } /* if !strcmp */
+ } /* for j loop */
+ if (found) break;
+ } /* for k loop */
+ if (!found) /* will assume that we have a continuation line */
+ temp = continueline(&buffer);
+ }
+ }
+ }
+ strncpy(retstr, buffer, 150);
+ retstr[149] = '\0';
+ free(buffer);
+ return True;
+}
+
+/*------------------------*/
+/* Save a PostScript file */
+/*------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void setfile(char *filename, int mode)
+{
+ if ((filename == NULL) || (xobjs.pagelist[areawin->page]->filename == NULL)) {
+ Wprintf("Error: No filename for schematic.");
+ if (beeper) XBell(dpy, 100);
+ return;
+ }
+
+ /* see if name has been changed in the buffer */
+
+ if (strcmp(xobjs.pagelist[areawin->page]->filename, filename)) {
+ Wprintf("Changing name of edit file.");
+ free(xobjs.pagelist[areawin->page]->filename);
+ xobjs.pagelist[areawin->page]->filename = strdup(filename);
+ }
+
+ if (strstr(xobjs.pagelist[areawin->page]->filename, "Page ") != NULL) {
+ Wprintf("Warning: Enter a new name.");
+ if (beeper) XBell(dpy, 100);
+ }
+ else {
+ savefile(mode);
+ if (beeper) XBell(dpy, 100);
+ }
+}
+
+#else /* !TCL_WRAPPER */
+
+void setfile(xcWidget button, xcWidget fnamewidget, caddr_t clientdata)
+{
+ /* see if name has been changed in the buffer */
+
+ sprintf(_STR2, "%.249s", (char *)XwTextCopyBuffer(fnamewidget));
+ if (xobjs.pagelist[areawin->page]->filename == NULL) {
+ xobjs.pagelist[areawin->page]->filename = strdup(_STR2);
+ }
+ else if (strcmp(xobjs.pagelist[areawin->page]->filename, _STR2)) {
+ Wprintf("Changing name of edit file.");
+ free(xobjs.pagelist[areawin->page]->filename);
+ xobjs.pagelist[areawin->page]->filename = strdup(_STR2);
+ }
+ if (strstr(xobjs.pagelist[areawin->page]->filename, "Page ") != NULL) {
+ Wprintf("Warning: Enter a new name.");
+ if (beeper) XBell(dpy, 100);
+ }
+ else {
+
+ Arg wargs[1];
+ xcWidget db, di;
+
+ savefile(CURRENT_PAGE);
+
+ /* Change "close" button to read "done" */
+
+ di = xcParent(button);
+ db = XtNameToWidget(di, "Close");
+ XtSetArg(wargs[0], XtNlabel, " Done ");
+ XtSetValues(db, wargs, 1);
+ if (beeper) XBell(dpy, 100);
+ }
+}
+
+#endif /* TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Update number of changes for an object and initiate a temp */
+/* file save if total number of unsaved changes exceeds 20. */
+/*--------------------------------------------------------------*/
+
+void incr_changes(objectptr thisobj)
+{
+ /* It is assumed that empty pages are meant to be that way */
+ /* and are not to be saved, so changes are marked as zero. */
+
+ if (thisobj->parts == 0) {
+ thisobj->changes = 0;
+ return;
+ }
+
+ /* Remove any pending timeout */
+
+ if (xobjs.timeout_id != (xcIntervalId)NULL) {
+ xcRemoveTimeOut(xobjs.timeout_id);
+ xobjs.timeout_id = (xcIntervalId)NULL;
+ }
+
+ thisobj->changes++;
+
+ /* When in "suspend" mode, we assume that we are reading commands from
+ * a script, and therefore we should not continuously increment changes
+ * and keep saving the backup file.
+ */
+
+ if (xobjs.suspend < 0)
+ xobjs.new_changes++;
+
+ if (xobjs.new_changes > MAXCHANGES) {
+#ifdef TCL_WRAPPER
+ savetemp(NULL);
+#else
+ savetemp(NULL, NULL);
+#endif
+ }
+
+ /* Generate a new timeout */
+
+ xobjs.timeout_id = xcAddTimeOut(app, 60000 * xobjs.save_interval,
+ savetemp, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* tempfile save */
+/*--------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void savetemp(ClientData clientdata)
+{
+
+#else
+
+void savetemp(XtPointer clientdata, xcIntervalId *id)
+{
+
+#endif
+
+ /* Remove the timeout ID. If this routine is called from */
+ /* incr_changes() instead of from the timeout interrupt */
+ /* service routine, then this value will already be NULL. */
+
+ xobjs.timeout_id = (xcIntervalId)NULL;
+
+ /* First see if there are any unsaved changes in the file. */
+ /* If not, then just reset the counter and continue. */
+
+ if (xobjs.new_changes > 0) {
+ if (xobjs.tempfile == NULL)
+ {
+ int fd;
+ char *template = (char *)malloc(20 + strlen(xobjs.tempdir));
+ int pid = (int)getpid();
+
+ sprintf(template, "%s/XC%d.XXXXXX", xobjs.tempdir, pid);
+
+#ifdef _MSC_VER
+ fd = mktemp(template);
+#else
+ fd = mkstemp(template);
+#endif
+ if (fd == -1) {
+ Fprintf(stderr, "Error generating file for savetemp\n");
+ free(template);
+ }
+ close(fd);
+ xobjs.tempfile = strdup(template);
+ free(template);
+ }
+ /* Show the "wristwatch" cursor, as graphic data may cause this */
+ /* step to be inordinately long. */
+
+ XDefineCursor(dpy, areawin->window, WAITFOR);
+ savefile(ALL_PAGES);
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+ xobjs.new_changes = 0; /* reset the count */
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Set all objects in the list "wroteobjs" as having no unsaved changes */
+/*----------------------------------------------------------------------*/
+
+void setassaved(objectptr *wroteobjs, short written)
+{
+ int i;
+
+ for (i = 0; i < written; i++)
+ (*(wroteobjs + i))->changes = 0;
+}
+
+/*---------------------------------------------------------------*/
+/* Save indicated library. If libno is 0, save current page if */
+/* the current page is a library. If not, save the user library */
+/*---------------------------------------------------------------*/
+
+void savelibpopup(xcWidget button, char *technology, caddr_t nulldata)
+{
+ TechPtr nsptr;
+
+#ifndef TCL_WRAPPER
+ buttonsave *savebutton;
+#endif
+
+ nsptr = LookupTechnology(technology);
+
+ if (nsptr != NULL) {
+ if ((nsptr->flags & TECH_READONLY) != 0) {
+ Wprintf("Library technology \"%s\" is read-only.", technology);
+ return;
+ }
+ }
+
+#ifndef TCL_WRAPPER
+ savebutton = getgeneric(button, savelibpopup, technology);
+ popupprompt(button, "Enter technology:", "\0", savelibrary,
+ savebutton, NULL);
+#endif
+}
+
+/*---------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+void savelibrary(xcWidget w, char *technology)
+{
+ char outname[250];
+ sscanf(_STR2, "%249s", outname);
+ savetechnology(technology, outname);
+}
+
+#endif
+
+/*---------------------------------------------------------*/
+
+void savetechnology(char *technology, char *outname)
+{
+ FILE *ps;
+ char *outptr, *validname, outfile[150];
+ objectptr *wroteobjs, libobjptr, *optr, depobj;
+ genericptr *gptr;
+ liblistptr spec;
+ short written;
+ short *glist;
+ char *uname = NULL;
+ char *hostname = NULL;
+ struct passwd *mypwentry = NULL;
+ int i, j, ilib;
+ TechPtr nsptr;
+ char *loctechnology;
+
+ // Don't use the string "(user)" as a technology name; this is just
+ // a GUI placeholder for a null string (""). This shouldn't happen,
+ // though, as technology should be NULL if the user technology is
+ // selected.
+
+ if (technology && (!strcmp(technology, "(user)")))
+ nsptr = LookupTechnology(NULL);
+ else
+ nsptr = LookupTechnology(technology);
+
+ if ((outptr = strrchr(outname, '/')) == NULL)
+ outptr = outname;
+ else
+ outptr++;
+ strcpy(outfile, outname);
+ if (strchr(outptr, '.') == NULL) strcat(outfile, ".lps");
+
+ xc_tilde_expand(outfile, 149);
+ while(xc_variable_expand(outfile, 149));
+
+ if (nsptr != NULL && nsptr->filename != NULL) {
+ // To be pedantic, we should probably check that the inodes of the
+ // files are different, to be sure we are avoiding an unintentional
+ // over-write.
+
+ if (!strcmp(outfile, nsptr->filename)) {
+
+ if ((nsptr->flags & TECH_READONLY) != 0) {
+ Wprintf("Technology file \"%s\" is read-only.", technology);
+ return;
+ }
+
+ if ((nsptr->flags & TECH_IMPORTED) != 0) {
+ Wprintf("Attempt to write a truncated technology file!");
+ return;
+ }
+ }
+ }
+
+ ps = fopen(outfile, "wb");
+ if (ps == NULL) {
+ Wprintf("Can't open PS file.");
+ if (nsptr && nsptr->filename && (!strcmp(nsptr->filename, outfile))) {
+ Wprintf("Marking technology \"%s\" as read-only.", technology);
+ nsptr->flags |= TECH_READONLY;
+ }
+ return;
+ }
+
+ /* Did the technology name change? If so, register the new name. */
+ /* Clear any "IMPORTED" or "READONLY" flags. */
+
+ if (nsptr && nsptr->filename && strcmp(outfile, nsptr->filename)) {
+ Wprintf("Technology filename changed from \"%s\" to \"%s\".",
+ nsptr->filename, outfile);
+ free(nsptr->filename);
+ nsptr->filename = strdup(outfile);
+ nsptr->flags &= ~(TECH_READONLY | TECH_IMPORTED);
+ }
+ else if (nsptr && !nsptr->filename) {
+ nsptr->filename = strdup(outfile);
+ nsptr->flags &= ~(TECH_READONLY | TECH_IMPORTED);
+ }
+
+ fprintf(ps, "%%! PostScript set of library objects for XCircuit\n");
+ fprintf(ps, "%% Version: %2.1f\n", version);
+ fprintf(ps, "%% Library name is: %s\n",
+ (technology == NULL) ? "(user)" : technology);
+#ifdef _MSC_VER
+ uname = getenv((const char *)"USERNAME");
+#else
+ uname = getenv((const char *)"USER");
+ if (uname != NULL) mypwentry = getpwnam(uname);
+#endif
+
+ /* Check for both $HOST and $HOSTNAME environment variables. Thanks */
+ /* to frankie liu <frankliu@Stanford.EDU> for this fix. */
+
+ if ((hostname = getenv((const char *)"HOSTNAME")) == NULL)
+ if ((hostname = getenv((const char *)"HOST")) == NULL) {
+ if (gethostname(_STR, 149) != 0)
+ hostname = uname;
+ else
+ hostname = _STR;
+ }
+
+#ifndef _MSC_VER
+ if (mypwentry != NULL)
+ fprintf(ps, "%% Author: %s <%s@%s>\n", mypwentry->pw_gecos, uname,
+ hostname);
+#endif
+
+ fprintf(ps, "%%\n\n");
+
+ /* Print lists of object dependencies, where they exist. */
+ /* Note that objects can depend on objects in other technologies; */
+ /* this is allowed. */
+
+ wroteobjs = (objectptr *) malloc(sizeof(objectptr));
+ for (ilib = 0; ilib < xobjs.numlibs; ilib++) {
+ for (j = 0; j < xobjs.userlibs[ilib].number; j++) {
+
+ libobjptr = *(xobjs.userlibs[ilib].library + j);
+ if (CompareTechnology(libobjptr, technology)) {
+ written = 0;
+
+ /* Search for all object definitions instantiated in this object, */
+ /* and add them to the dependency list (non-recursive). */
+
+ for (gptr = libobjptr->plist; gptr < libobjptr->plist
+ + libobjptr->parts; gptr++) {
+ if (IS_OBJINST(*gptr)) {
+ depobj = TOOBJINST(gptr)->thisobject;
+
+ /* Search among the list of objects already collected. */
+ /* If this object has been previously, then ignore it. */
+ /* Otherwise, update the list of object dependencies */
+
+ for (optr = wroteobjs; optr < wroteobjs + written; optr++)
+ if (*optr == depobj)
+ break;
+
+ if (optr == wroteobjs + written) {
+ wroteobjs = (objectptr *)realloc(wroteobjs, (written + 1) *
+ sizeof(objectptr));
+ *(wroteobjs + written) = depobj;
+ written++;
+ }
+ }
+ }
+ if (written > 0) {
+ fprintf(ps, "%% Depend %s", libobjptr->name);
+ for (i = 0; i < written; i++) {
+ depobj = *(wroteobjs + i);
+ fprintf(ps, " %s", depobj->name);
+ }
+ fprintf(ps, "\n");
+ }
+ }
+ }
+ }
+
+ fprintf(ps, "\n%% XCircuitLib library objects\n");
+
+ /* Start by looking for any graphic images in the library objects */
+ /* and saving the graphic image data at the top of the file. */
+
+ glist = (short *)malloc(xobjs.images * sizeof(short));
+ for (i = 0; i < xobjs.images; i++) glist[i] = 0;
+
+ for (ilib = 0; ilib < xobjs.numlibs; ilib++) {
+ for (spec = xobjs.userlibs[ilib].instlist; spec != NULL; spec = spec->next) {
+ libobjptr = spec->thisinst->thisobject;
+ if (CompareTechnology(libobjptr, technology))
+ count_graphics(spec->thisinst->thisobject, glist);
+ }
+ }
+ output_graphic_data(ps, glist);
+ free(glist);
+
+ /* list of library objects already written */
+
+ wroteobjs = (objectptr *)realloc(wroteobjs, sizeof(objectptr));
+ written = 0;
+
+ /* write all of the object definitions used, bottom up, with virtual */
+ /* instances in the correct placement. The need to find virtual */
+ /* instances is why we do a look through the library pages and not */
+ /* the libraries themselves when looking for objects matching the */
+ /* given technology. */
+
+ for (ilib = 0; ilib < xobjs.numlibs; ilib++) {
+ for (spec = xobjs.userlibs[ilib].instlist; spec != NULL; spec = spec->next) {
+ libobjptr = spec->thisinst->thisobject;
+ if (CompareTechnology(libobjptr, technology)) {
+ if (!spec->virtual) {
+ printobjects(ps, spec->thisinst->thisobject, &wroteobjs,
+ &written, DEFAULTCOLOR);
+ }
+ else {
+ if ((spec->thisinst->scale != 1.0) || (spec->thisinst->rotation != 0)) {
+ fprintf(ps, "%3.3f %d ", spec->thisinst->scale,
+ spec->thisinst->rotation);
+ }
+ printparams(ps, spec->thisinst, 0);
+ validname = create_valid_psname(spec->thisinst->thisobject->name, FALSE);
+ /* Names without technologies get '::' string (blank technology) */
+ if (technology == NULL)
+ fprintf(ps, "/::%s libinst\n", validname);
+ else
+ fprintf(ps, "/%s libinst\n", validname);
+ if ((spec->next != NULL) && (!(spec->next->virtual)))
+ fprintf(ps, "\n");
+ }
+ }
+ }
+ }
+
+ setassaved(wroteobjs, written);
+ if (nsptr) nsptr->flags &= (~TECH_CHANGED);
+ xobjs.new_changes = countchanges(NULL);
+
+ /* and the postlog */
+
+ fprintf(ps, "\n%% EndLib\n");
+ fclose(ps);
+ if (technology != NULL)
+ Wprintf("Library technology \"%s\" saved as file %s.",technology, outname);
+ else
+ Wprintf("Library technology saved as file %s.", outname);
+
+ free(wroteobjs);
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive routine to search the object hierarchy for fonts used */
+/*----------------------------------------------------------------------*/
+
+void findfonts(objectptr writepage, short *fontsused) {
+ genericptr *dfp;
+ stringpart *chp;
+ int findex;
+
+ for (dfp = writepage->plist; dfp < writepage->plist + writepage->parts; dfp++) {
+ if (IS_LABEL(*dfp)) {
+ for (chp = TOLABEL(dfp)->string; chp != NULL; chp = chp->nextpart) {
+ if (chp->type == FONT_NAME) {
+ findex = chp->data.font;
+ if (fontsused[findex] == 0) {
+ fontsused[findex] = 0x8000 | fonts[findex].flags;
+ }
+ }
+ }
+ }
+ else if (IS_OBJINST(*dfp)) {
+ findfonts(TOOBJINST(dfp)->thisobject, fontsused);
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Write graphics image data to file "ps". "glist" is */
+/* a pointer to a vector of short integers, each one */
+/* being an index into xobjs.images for an image that */
+/* is to be output. */
+/*------------------------------------------------------*/
+
+void output_graphic_data(FILE *ps, short *glist)
+{
+ char *fptr, ascbuf[6];
+ int i, j;
+ for (i = 0; i < xobjs.images; i++) {
+ Imagedata *img = xobjs.imagelist + i;
+ int ilen, flen, k, m = 0, n, q = 0;
+ u_char *filtbuf, *flatebuf;
+ Boolean lastpix = False;
+ union {
+ u_long i;
+ u_char b[4];
+ } pixel;
+
+ if (glist[i] == 0) continue;
+
+ fprintf(ps, "%%imagedata %d %d\n", img->image->width, img->image->height);
+ fprintf(ps, "currentfile /ASCII85Decode filter ");
+
+#ifdef HAVE_LIBZ
+ fprintf(ps, "/FlateDecode filter\n");
+#endif
+
+ fprintf(ps, "/ReusableStreamDecode filter\n");
+
+ /* creating a stream buffer is wasteful if we're just using ASCII85 */
+ /* decoding but is a must for compression filters. */
+
+ ilen = 3 * img->image->width * img->image->height;
+ filtbuf = (u_char *)malloc(ilen + 4);
+ q = 0;
+ for (j = 0; j < img->image->height; j++) {
+ for (k = 0; k < img->image->width; k++) {
+ pixel.i = XGetPixel(img->image, k, j);
+ filtbuf[q++] = (u_char)pixel.b[2];
+ filtbuf[q++] = (u_char)pixel.b[1];
+ filtbuf[q++] = (u_char)pixel.b[0];
+ }
+ }
+ for (j = 0; j < 4; j++)
+ filtbuf[q++] = 0;
+
+ /* Extra encoding goes here */
+#ifdef HAVE_LIBZ
+ flen = ilen * 2;
+ flatebuf = (char *)malloc(flen);
+ ilen = large_deflate(flatebuf, flen, filtbuf, ilen);
+ free(filtbuf);
+#else
+ flatebuf = filtbuf;
+#endif
+
+ ascbuf[5] = '\0';
+ for (j = 0; j < ilen; j += 4) {
+ if ((j + 4) > ilen) lastpix = TRUE;
+ if (!lastpix && (flatebuf[j] + flatebuf[j + 1] + flatebuf[j + 2]
+ + flatebuf[j + 3] == 0)) {
+ fprintf(ps, "z");
+ m++;
+ }
+ else {
+ for (n = 0; n < 4; n++)
+ pixel.b[3 - n] = flatebuf[j + n];
+
+ ascbuf[0] = '!' + (pixel.i / 52200625);
+ pixel.i %= 52200625;
+ ascbuf[1] = '!' + (pixel.i / 614125);
+ pixel.i %= 614125;
+ ascbuf[2] = '!' + (pixel.i / 7225);
+ pixel.i %= 7225;
+ ascbuf[3] = '!' + (pixel.i / 85);
+ pixel.i %= 85;
+ ascbuf[4] = '!' + pixel.i;
+ if (lastpix)
+ for (n = 0; n < ilen + 1 - j; n++)
+ fprintf(ps, "%c", ascbuf[n]);
+ else
+ fprintf(ps, "%5s", ascbuf);
+ m += 5;
+ }
+ if (m > 75) {
+ fprintf(ps, "\n");
+ m = 0;
+ }
+ }
+ fprintf(ps, "~>\n");
+ free(flatebuf);
+
+ /* Remove any filesystem path information from the image name. */
+ /* Otherwise, the slashes will cause PostScript to err. */
+
+ fptr = strrchr(img->filename, '/');
+ if (fptr == NULL)
+ fptr = img->filename;
+ else
+ fptr++;
+ fprintf(ps, "/%sdata exch def\n", fptr);
+ fprintf(ps, "/%s <<\n", fptr);
+ fprintf(ps, " /ImageType 1 /Width %d /Height %d /BitsPerComponent 8\n",
+ img->image->width, img->image->height);
+ fprintf(ps, " /MultipleDataSources false\n");
+ fprintf(ps, " /Decode [0 1 0 1 0 1]\n");
+ fprintf(ps, " /ImageMatrix [1 0 0 -1 %d %d]\n",
+ (img->image->width >> 1), (img->image->height >> 1));
+ fprintf(ps, " /DataSource %sdata >> def\n\n", fptr);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Main file saving routine */
+/*----------------------------------------------------------------------*/
+/* mode description */
+/*----------------------------------------------------------------------*/
+/* ALL_PAGES saves a crash recovery backup file */
+/* CURRENT_PAGE saves all pages associated with the same */
+/* filename as the current page, and all */
+/* dependent schematics (which have their */
+/* filenames changed to match). */
+/* NO_SUBCIRCUITS saves all pages associated with the same */
+/* filename as the current page, only. */
+/*----------------------------------------------------------------------*/
+
+void savefile(short mode)
+{
+ FILE *ps, *pro;
+ char outname[150], temp[150], prologue[150], *fname, *fptr, ascbuf[6];
+ /* u_char decodebuf[6]; (jdk */
+ short written, fontsused[256], i, page, curpage, multipage;
+ short savepage, stcount, *pagelist, *glist;
+ objectptr *wroteobjs;
+ objinstptr writepage;
+ int findex, j;
+ time_t tdate;
+ char *tmp_s;
+
+ if (mode != ALL_PAGES) {
+ /* doubly-protected file write: protect against errors during file write */
+ fname = xobjs.pagelist[areawin->page]->filename;
+ sprintf(outname, "%s~", fname);
+ rename(fname, outname);
+ }
+ else {
+ /* doubly-protected backup: protect against errors during file write */
+ sprintf(outname, "%sB", xobjs.tempfile);
+ rename(xobjs.tempfile, outname);
+ fname = xobjs.tempfile;
+ }
+
+ if ((fptr = strrchr(fname, '/')) != NULL)
+ fptr++;
+ else
+ fptr = fname;
+
+ if ((mode != ALL_PAGES) && (strchr(fptr, '.') == NULL))
+ sprintf(outname, "%s.ps", fname);
+ else sprintf(outname, "%s", fname);
+
+ xc_tilde_expand(outname, 149);
+ while(xc_variable_expand(outname, 149));
+
+ ps = fopen(outname, "wb");
+ if (ps == NULL) {
+ Wprintf("Can't open file %s for writing.", outname);
+ return;
+ }
+
+ if ((mode != NO_SUBCIRCUITS) && (mode != ALL_PAGES))
+ collectsubschems(areawin->page);
+
+ /* Check for multiple-page output: get the number of pages; */
+ /* ignore empty pages. */
+
+ multipage = 0;
+
+ if (mode == NO_SUBCIRCUITS)
+ pagelist = pagetotals(areawin->page, INDEPENDENT);
+ else if (mode == ALL_PAGES)
+ pagelist = pagetotals(areawin->page, ALL_PAGES);
+ else
+ pagelist = pagetotals(areawin->page, TOTAL_PAGES);
+
+ for (page = 0; page < xobjs.pages; page++)
+ if (pagelist[page] > 0)
+ multipage++;
+
+ if (multipage == 0) {
+ Wprintf("Panic: could not find this page in page list!");
+ free (pagelist);
+ fclose(ps);
+ return;
+ }
+
+ /* Print the PostScript DSC Document Header */
+
+ fprintf(ps, "%%!PS-Adobe-3.0");
+ if (multipage == 1 && !(xobjs.pagelist[areawin->page]->pmode & 1))
+ fprintf(ps, " EPSF-3.0\n");
+ else
+ fprintf(ps, "\n");
+ fprintf(ps, "%%%%Title: %s\n", fptr);
+ fprintf(ps, "%%%%Creator: XCircuit v%2.1f rev%d\n", PROG_VERSION, PROG_REVISION);
+ tdate = time(NULL);
+ fprintf(ps, "%%%%CreationDate: %s", asctime(localtime(&tdate)));
+ fprintf(ps, "%%%%Pages: %d\n", multipage);
+
+ /* This is just a default value; each bounding box is declared per */
+ /* page by the DSC "PageBoundingBox" keyword. */
+ /* However, encapsulated files adjust the bounding box to center on */
+ /* the object, instead of centering the object on the page. */
+
+ if (multipage == 1 && !(xobjs.pagelist[areawin->page]->pmode & 1)) {
+ objectptr thisobj = xobjs.pagelist[areawin->page]->pageinst->thisobject;
+ float psscale = getpsscale(xobjs.pagelist[areawin->page]->outscale,
+ areawin->page);
+
+ /* The top-level bounding box determines the size of an encapsulated */
+ /* drawing, regardless of the PageBoundingBox numbers. Therefore, */
+ /* we size this to bound just the picture by closing up the 1" (72 */
+ /* PostScript units) margins, except for a tiny sliver of a margin */
+ /* (4 PostScript units) which covers a bit of sloppiness in the font */
+ /* measurements. */
+
+ fprintf(ps, "%%%%BoundingBox: 68 68 %d %d\n",
+ (int)((float)thisobj->bbox.width * psscale)
+ + xobjs.pagelist[areawin->page]->margins.x + 4,
+ (int)((float)thisobj->bbox.height * psscale)
+ + xobjs.pagelist[areawin->page]->margins.y + 4);
+ }
+ else if (xobjs.pagelist[0]->coordstyle == CM)
+ fprintf(ps, "%%%%BoundingBox: 0 0 595 842\n"); /* A4 default (fixed by jdk) */
+ else
+ fprintf(ps, "%%%%BoundingBox: 0 0 612 792\n"); /* letter default */
+
+ for (i = 0; i < fontcount; i++) fontsused[i] = 0;
+ fprintf(ps, "%%%%DocumentNeededResources: font ");
+ stcount = 32;
+
+ /* find all of the fonts used in this document */
+ /* log all fonts which are native PostScript */
+
+ for (curpage = 0; curpage < xobjs.pages; curpage++)
+ if (pagelist[curpage] > 0) {
+ writepage = xobjs.pagelist[curpage]->pageinst;
+ findfonts(writepage->thisobject, fontsused);
+ }
+
+ for (i = 0; i < fontcount; i++) {
+ if (fontsused[i] & 0x8000)
+ if ((fonts[i].flags & 0x8018) == 0x0) {
+ stcount += strlen(fonts[i].psname) + 1;
+ if (stcount > OUTPUTWIDTH) {
+ stcount = strlen(fonts[i].psname) + 11;
+ fprintf(ps, "\n%%%%+ font ");
+ }
+ fprintf(ps, "%s ", fonts[i].psname);
+ }
+ }
+
+ fprintf(ps, "\n%%%%EndComments\n");
+
+ tmp_s = getenv((const char *)"XCIRCUIT_LIB_DIR");
+ if (tmp_s != NULL) {
+ sprintf(prologue, "%s/%s", tmp_s, PROLOGUE_FILE);
+ pro = fopen(prologue, "r");
+ }
+ else
+ pro = NULL;
+
+ if (pro == NULL) {
+ sprintf(prologue, "%s/%s", PROLOGUE_DIR, PROLOGUE_FILE);
+ pro = fopen(prologue, "r");
+ if (pro == NULL) {
+ sprintf(prologue, "%s", PROLOGUE_FILE);
+ pro = fopen(prologue, "r");
+ if (pro == NULL) {
+ Wprintf("Can't open prolog.");
+ free(pagelist);
+ fclose(ps);
+ return;
+ }
+ }
+ }
+
+ /* write the prolog to the output */
+
+ for(;;) {
+ if (fgets(temp, 149, pro) == NULL) break;
+ fputs(temp, ps);
+ }
+ fclose(pro);
+
+ /* Special font handling */
+
+ for (findex = 0; findex < fontcount; findex++) {
+
+ /* Derived font slant */
+
+ if ((fontsused[findex] & 0x032) == 0x032)
+ fprintf(ps, "/%s /%s .167 fontslant\n\n",
+ fonts[findex].psname, fonts[findex].family);
+
+ /* Derived ISO-Latin1 encoding */
+
+ if ((fontsused[findex] & 0xf80) == 0x100) {
+ char *fontorig = NULL;
+ short i;
+ /* find the original standard-encoded font (can be itself) */
+ for (i = 0; i < fontcount; i++) {
+ if (i == findex) continue;
+ if (!strcmp(fonts[i].family, fonts[findex].family) &&
+ ((fonts[i].flags & 0x03) == (fonts[findex].flags & 0x03)))
+ fontorig = fonts[i].psname;
+ if (fontorig == NULL) fontorig = fonts[findex].psname;
+ }
+ fprintf(ps, "/%s findfont dup length dict begin\n", fontorig);
+ fprintf(ps, "{1 index /FID ne {def} {pop pop} ifelse} forall\n");
+ fprintf(ps, "/Encoding ISOLatin1Encoding def currentdict end\n");
+ fprintf(ps, "/%s exch definefont pop\n\n", fonts[findex].psname);
+ }
+
+ /* To do: ISO-Latin2 encoding */
+
+ if ((fontsused[findex] & 0xf80) == 0x180) {
+ }
+
+ /* To do: Special encoding */
+
+ if ((fontsused[findex] & 0xf80) == 0x80) {
+ }
+
+ /* To do: Vectored (drawn) font */
+
+ if (fontsused[findex] & 0x8) {
+ }
+ }
+
+ /* List of objects already written */
+ wroteobjs = (objectptr *) malloc (sizeof(objectptr));
+ written = 0;
+
+ fprintf(ps, "%% XCircuit output starts here.\n\n");
+ fprintf(ps, "%%%%BeginSetup\n\n");
+
+ /* Write out all of the images used */
+
+ glist = collect_graphics(pagelist);
+ output_graphic_data(ps, glist);
+ free(glist);
+
+ for (curpage = 0; curpage < xobjs.pages; curpage++) {
+ if (pagelist[curpage] == 0) continue;
+
+ /* Write all of the object definitions used, bottom up */
+ printrefobjects(ps, xobjs.pagelist[curpage]->pageinst->thisobject,
+ &wroteobjs, &written);
+ }
+
+ fprintf(ps, "\n%%%%EndSetup\n\n");
+
+ page = 0;
+ for (curpage = 0; curpage < xobjs.pages; curpage++) {
+ if (pagelist[curpage] == 0) continue;
+
+ /* Print the page header, all elements in the page, and page trailer */
+ savepage = areawin->page;
+ /* Set the current page for the duration of printing so that any */
+ /* page parameters will be printed correctly. */
+ areawin->page = curpage;
+ printpageobject(ps, xobjs.pagelist[curpage]->pageinst->thisobject,
+ ++page, curpage);
+ areawin->page = savepage;
+
+ /* For crash recovery, log the filename for each page */
+ if (mode == ALL_PAGES) {
+ fprintf(ps, "%% %s is_filename\n",
+ (xobjs.pagelist[curpage]->filename == NULL) ?
+ xobjs.pagelist[curpage]->pageinst->thisobject->name :
+ xobjs.pagelist[curpage]->filename);
+ }
+
+ fprintf(ps, "\n");
+ fflush(ps);
+ }
+
+ /* For crash recovery, save all objects that have been edited but are */
+ /* not in the list of objects already saved. */
+
+ if (mode == ALL_PAGES)
+ {
+ int i, j, k;
+ objectptr thisobj;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ thisobj = *(xobjs.userlibs[i].library + j);
+ if (thisobj->changes > 0 ) {
+ for (k = 0; k < written; k++)
+ if (thisobj == *(wroteobjs + k)) break;
+ if (k == written)
+ printobjects(ps, thisobj, &wroteobjs, &written, DEFAULTCOLOR);
+ }
+ }
+ }
+ }
+ else { /* No unsaved changes in these objects */
+ setassaved(wroteobjs, written);
+ for (i = 0; i < xobjs.pages; i++)
+ if (pagelist[i] > 0)
+ xobjs.pagelist[i]->pageinst->thisobject->changes = 0;
+ xobjs.new_changes = countchanges(NULL);
+ }
+
+ /* Free allocated memory */
+ free((char *)pagelist);
+ free((char *)wroteobjs);
+
+ /* Done! */
+
+ fprintf(ps, "%%%%Trailer\n");
+ fprintf(ps, "XCIRCsave restore\n");
+ fprintf(ps, "%%%%EOF\n");
+ fclose(ps);
+
+ Wprintf("File %s saved (%d page%s).", fname, multipage,
+ (multipage > 1 ? "s" : ""));
+
+ if (mode == ALL_PAGES) {
+ /* Remove the temporary redundant backup */
+ sprintf(outname, "%sB", xobjs.tempfile);
+ unlink(outname);
+ }
+ else if (!xobjs.retain_backup) {
+ /* Remove the backup file */
+ sprintf(outname, "%s~", fname);
+ unlink(outname);
+ }
+
+ /* Write LATEX strings, if any are present */
+ TopDoLatex();
+}
+
+/*----------------------------------------------------------------------*/
+/* Given a color index, print the R, G, B values */
+/*----------------------------------------------------------------------*/
+
+int printRGBvalues(char *tstr, int index, const char *postfix)
+{
+ int i;
+ for (i = 0; i < number_colors; i++) {
+ if (colorlist[i].color.pixel == index) {
+ sprintf(tstr, "%4.3f %4.3f %4.3f %s",
+ (float)colorlist[i].color.red / 65535,
+ (float)colorlist[i].color.green / 65535,
+ (float)colorlist[i].color.blue / 65535,
+ postfix);
+ return 0;
+ }
+ }
+
+ /* The program can reach this point for any color which is */
+ /* not listed in the table. This can happen when parameters */
+ /* printed from printobjectparams object contain the string */
+ /* "@p_color". Therefore print the default top-level */
+ /* default color, which is black. */
+
+ /* If the index is *not* DEFAULTCOLOR (-1), return an error */
+ /* code. */
+
+ sprintf(tstr, "0 0 0 %s", postfix);
+ return (index == DEFAULTCOLOR) ? 0 : -1;
+}
+
+/*----------------------------------------------------*/
+/* Write string to PostScript string, ignoring NO_OPs */
+/*----------------------------------------------------*/
+
+char *nosprint(char *baseptr, int *margin, int *extsegs)
+{
+ int qtmp, slen = 100;
+ char *sptr, *lptr = NULL, lsave, *sptr2;
+ u_char *pptr, *qptr, *bptr;
+
+ bptr = (u_char *)malloc(slen); /* initial length 100 */
+ qptr = bptr;
+
+ while(1) { /* loop for breaking up margin-limited text into words */
+
+ if (*margin > 0) {
+ sptr = strrchr(baseptr, ' ');
+ if (sptr == NULL)
+ sptr = baseptr;
+ else {
+ if (*(sptr + 1) == '\0') {
+ while (*sptr == ' ') sptr--;
+ *(sptr + 1) = '\0';
+ sptr2 = strrchr(baseptr, ' ');
+ *(sptr + 1) = ' ';
+ if (sptr2 == NULL)
+ sptr = baseptr;
+ else
+ sptr = sptr2 + 1;
+ }
+ else
+ sptr++;
+ }
+ }
+ else
+ sptr = baseptr;
+
+ *qptr++ = '(';
+
+ /* Includes extended character set (non-ASCII) */
+
+ for (pptr = sptr; pptr && *pptr != '\0'; pptr++) {
+ /* Ensure enough space for the string, including everything */
+ /* following the "for" loop */
+ qtmp = qptr - bptr;
+ if (qtmp + 7 >= slen) {
+ slen += 7;
+ bptr = (char *)realloc(bptr, slen);
+ qptr = bptr + qtmp;
+ }
+
+ /* Deal with non-printable characters and parentheses */
+ if (*pptr > (char)126) {
+ sprintf(qptr, "\\%3o", (int)(*pptr));
+ qptr += 4;
+ }
+ else {
+ if ((*pptr == '(') || (*pptr == ')') || (*pptr == '\\'))
+ *qptr++ = '\\';
+ *qptr++ = *pptr;
+ }
+ }
+ if (qptr == bptr + 1) { /* Empty string gets a NULL result, not "()" */
+ qptr--;
+ }
+ else {
+ *qptr++ = ')';
+ *qptr++ = ' ';
+ }
+
+ if (lptr != NULL)
+ *lptr = lsave;
+
+ if (sptr == baseptr)
+ break;
+ else {
+ lptr = sptr;
+ lsave = *lptr;
+ *lptr = '\0';
+ (*extsegs)++;
+ }
+ }
+
+ *qptr++ = '\0';
+ return (char *)bptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Write label segments to the output (in reverse order) */
+/*--------------------------------------------------------------*/
+
+short writelabel(FILE *ps, stringpart *chrtop, short *stcount)
+{
+ short i, segs = 0;
+ stringpart *chrptr;
+ char **ostr = (char **)malloc(sizeof(char *));
+ char *tmpstr;
+ float lastscale = 1.0;
+ int lastfont = -1;
+ int margin = 0;
+ int extsegs = 0;
+
+ /* Write segments into string array, in forward order */
+
+ for (chrptr = chrtop; chrptr != NULL; chrptr = chrptr->nextpart) {
+ ostr = (char **)realloc(ostr, (segs + 1) * sizeof(char *));
+ if (chrtop->type == PARAM_END) { /* NULL parameter is empty string */
+ ostr[segs] = (char *)malloc(4);
+ strcpy(ostr[segs], "() ");
+ }
+ else {
+ tmpstr = writesegment(chrptr, &lastscale, &lastfont, &margin, &extsegs);
+ if (tmpstr[0] != '\0')
+ ostr[segs] = tmpstr;
+ else
+ segs--;
+ }
+ segs++;
+ }
+
+ /* Write string array to output in reverse order */
+ for (i = segs - 1; i >= 0; i--) {
+ dostcount(ps, stcount, strlen(ostr[i]));
+ fputs(ostr[i], ps);
+ free(ostr[i]);
+ }
+ free(ostr);
+
+ return segs + extsegs;
+}
+
+/*--------------------------------------------------------------*/
+/* Write a single label segment to the output */
+/* (Recursive, so we can write segments in the reverse order) */
+/*--------------------------------------------------------------*/
+
+char *writesegment(stringpart *chrptr, float *lastscale, int *lastfont, int *margin,
+ int *extsegs)
+{
+ int type = chrptr->type;
+ char *retstr, *validname;
+
+ switch(type) {
+ case PARAM_START:
+ validname = create_valid_psname(chrptr->data.string, TRUE);
+ sprintf(_STR, "%s ", validname);
+ break;
+ case PARAM_END:
+ _STR[0] = '\0';
+ chrptr->nextpart = NULL;
+ break;
+ case SUBSCRIPT:
+ sprintf(_STR, "{ss} ");
+ break;
+ case SUPERSCRIPT:
+ sprintf(_STR, "{Ss} ");
+ break;
+ case NORMALSCRIPT:
+ *lastscale = 1.0;
+ sprintf(_STR, "{ns} ");
+ break;
+ case UNDERLINE:
+ sprintf(_STR, "{ul} ");
+ break;
+ case OVERLINE:
+ sprintf(_STR, "{ol} ");
+ break;
+ case NOLINE:
+ sprintf(_STR, "{} ");
+ break;
+ case HALFSPACE:
+ sprintf(_STR, "{hS} ");
+ break;
+ case QTRSPACE:
+ sprintf(_STR, "{qS} ");
+ break;
+ case RETURN:
+ *lastscale = 1.0;
+ if (chrptr->data.flags == 0)
+ // Ignore automatically-generated line breaks
+ sprintf(_STR, "{CR} ");
+ else
+ sprintf(_STR, "");
+ break;
+ case TABSTOP:
+ sprintf(_STR, "{Ts} ");
+ break;
+ case TABFORWARD:
+ sprintf(_STR, "{Tf} ");
+ break;
+ case TABBACKWARD:
+ sprintf(_STR, "{Tb} ");
+ break;
+ case FONT_NAME:
+ /* If font specifier is followed by a scale specifier, then */
+ /* record the font change but defer the output. Otherwise, */
+ /* output the font record now. */
+
+ if ((chrptr->nextpart == NULL) || (chrptr->nextpart->type != FONT_SCALE))
+ {
+ if (*lastscale == 1.0)
+ sprintf(_STR, "{/%s cf} ", fonts[chrptr->data.font].psname);
+ else
+ sprintf(_STR, "{/%s %5.3f cf} ", fonts[chrptr->data.font].psname,
+ *lastscale);
+ }
+ else
+ _STR[0] = '\0';
+ *lastfont = chrptr->data.font;
+ break;
+ case FONT_SCALE:
+ if (*lastfont == -1) {
+ Fprintf(stderr, "Warning: Font may not be the one that was intended.\n");
+ *lastfont = 0;
+ }
+ *lastscale = chrptr->data.scale;
+ sprintf(_STR, "{/%s %5.3f cf} ", fonts[*lastfont].psname, *lastscale);
+ break;
+ case FONT_COLOR:
+ strcpy(_STR, "{");
+ if (chrptr->data.color == DEFAULTCOLOR)
+ strcat(_STR, "sce} ");
+ else
+ if (printRGBvalues(_STR + 1,
+ colorlist[chrptr->data.color].color.pixel, "scb} ") < 0)
+ strcat(_STR, "sce} ");
+ break;
+ case MARGINSTOP:
+ sprintf(_STR, "{%d MR} ", chrptr->data.width);
+ *margin = chrptr->data.width;
+ break;
+ case KERN:
+ sprintf(_STR, "{%d %d Kn} ", chrptr->data.kern[0], chrptr->data.kern[1]);
+ break;
+ case TEXT_STRING:
+ /* Everything except TEXT_STRING will always fit in the _STR fixed- */
+ /* length character array. */
+ return nosprint(chrptr->data.string, margin, extsegs);
+ }
+
+ retstr = (char *)malloc(1 + strlen(_STR));
+ strcpy(retstr, _STR);
+ return retstr;
+}
+
+/*--------------------------------------------------------------*/
+/* Routine to write all the label segments as stored in _STR */
+/*--------------------------------------------------------------*/
+
+int writelabelsegs(FILE *ps, short *stcount, stringpart *chrptr)
+{
+ Boolean ismultipart;
+ int segs;
+
+ if (chrptr == NULL) return 0;
+
+ ismultipart = ((chrptr->nextpart != NULL) &&
+ (chrptr->nextpart->type != PARAM_END)) ? True : False;
+
+ /* If there is only one part, but it is not a string or the */
+ /* end of a parameter (empty parameter), then set multipart */
+ /* anyway so we get the double brace {{ }}. */
+
+ if ((!ismultipart) && (chrptr->type != TEXT_STRING) &&
+ (chrptr->type != PARAM_END))
+ ismultipart = True;
+
+ /* nextpart is not NULL if there are multiple parts to the string */
+ if (ismultipart) {
+ fprintf(ps, "{");
+ (*stcount)++;
+ }
+ segs = writelabel(ps, chrptr, stcount);
+
+ if (ismultipart) {
+ fprintf(ps, "} ");
+ (*stcount) += 2;
+ }
+ return segs;
+}
+
+/*--------------------------------------------------------------*/
+/* Write the dictionary of parameters belonging to an object */
+/*--------------------------------------------------------------*/
+
+void printobjectparams(FILE *ps, objectptr localdata)
+{
+ int segs;
+ short stcount;
+ oparamptr ops;
+ char *ps_expr, *validkey;
+ float fp;
+
+ /* Check for parameters and default values */
+ if (localdata->params == NULL) return;
+
+ fprintf(ps, "<<");
+ stcount = 2;
+
+ for (ops = localdata->params; ops != NULL; ops = ops->next) {
+ validkey = create_valid_psname(ops->key, TRUE);
+ fprintf(ps, "/%s ", validkey);
+ dostcount (ps, &stcount, strlen(validkey) + 2);
+
+ switch (ops->type) {
+ case XC_EXPR:
+ ps_expr = evaluate_expr(localdata, ops, NULL);
+ if (ops->which == P_SUBSTRING || ops->which == P_EXPRESSION) {
+ dostcount(ps, &stcount, 3 + strlen(ps_expr));
+ fputs("(", ps);
+ fputs(ps_expr, ps);
+ fputs(") ", ps);
+ }
+ else if (ops->which == P_COLOR) {
+ int ccol;
+ /* Write R, G, B components for PostScript */
+ if (sscanf(ps_expr, "%d", &ccol) == 1) {
+ fputs("{", ps);
+ printRGBvalues(_STR, ccol, "} ");
+ dostcount(ps, &stcount, 1 + strlen(_STR));
+ fputs(_STR, ps);
+ }
+ else {
+ dostcount(ps, &stcount, 8);
+ fputs("{0 0 0} ", ps);
+ }
+ }
+ else if (sscanf(ps_expr, "%g", &fp) == 1) {
+ dostcount(ps, &stcount, 1 + strlen(ps_expr));
+ fputs(ps_expr, ps);
+ fputs(" ", ps);
+ }
+ else { /* Expression evaluates to error in object */
+ dostcount(ps, &stcount, 2);
+ fputs("0 ", ps);
+ }
+ dostcount(ps, &stcount, 7 + strlen(ops->parameter.expr));
+ fputs("(", ps);
+ fputs(ops->parameter.expr, ps);
+ fputs(") pop ", ps);
+ free(ps_expr);
+ break;
+ case XC_STRING:
+ segs = writelabelsegs(ps, &stcount, ops->parameter.string);
+ if (segs == 0) {
+ /* When writing object parameters, we cannot allow a */
+ /* NULL value. Instead, print an empty string (). */
+ dostcount(ps, &stcount, 3);
+ fputs("() ", ps);
+ }
+ break;
+ case XC_INT:
+ sprintf(_STR, "%d ", ops->parameter.ivalue);
+ dostcount(ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+ case XC_FLOAT:
+ sprintf(_STR, "%g ", ops->parameter.fvalue);
+ dostcount(ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+ }
+ }
+
+ fprintf(ps, ">> ");
+ dostcount (ps, &stcount, 3);
+}
+
+/*--------------------------------------------------------------*/
+/* Write the list of parameters belonging to an object instance */
+/*--------------------------------------------------------------*/
+
+short printparams(FILE *ps, objinstptr sinst, short stcount)
+{
+ int segs;
+ short loccount;
+ oparamptr ops, objops;
+ eparamptr epp;
+ char *ps_expr, *validkey, *validref;
+ short instances = 0;
+
+ if (sinst->params == NULL) return stcount;
+
+ for (ops = sinst->params; ops != NULL; ops = ops->next) {
+ validref = strdup(create_valid_psname(ops->key, TRUE));
+
+ /* Check for indirect parameter references */
+ for (epp = sinst->passed; epp != NULL; epp = epp->next) {
+ if ((epp->flags & P_INDIRECT) && (epp->pdata.refkey != NULL)) {
+ if (!strcmp(epp->pdata.refkey, ops->key)) {
+ if (instances++ == 0) {
+ fprintf(ps, "<<"); /* begin PostScript dictionary */
+ loccount = stcount + 2;
+ }
+ dostcount(ps, &loccount, strlen(validref + 3));
+ fprintf(ps, "/%s ", validref);
+ dostcount(ps, &loccount, strlen(epp->key + 1));
+ validkey = create_valid_psname(epp->key, TRUE);
+ fprintf(ps, "%s ", validkey);
+ break;
+ }
+ }
+ }
+ if (epp == NULL) { /* No indirection */
+ Boolean nondefault = TRUE;
+ char *deflt_expr = NULL;
+
+ /* For instance values that are expression results, ignore if */
+ /* the instance value is the same as the default value. */
+ /* Correction 9/08: We can't second-guess expression results, */
+ /* in particular, this doesn't work for an expression like */
+ /* "page", where the local and default values will evaluate to */
+ /* the same result, when clearly each page is intended to have */
+ /* its own instance value, and "page" for an object is not a */
+ /* well-defined concept. */
+
+// ps_expr = NULL;
+// objops = match_param(sinst->thisobject, ops->key);
+// if (objops && (objops->type == XC_EXPR)) {
+// int i;
+// float f;
+// deflt_expr = evaluate_expr(sinst->thisobject, objops, NULL);
+// switch (ops->type) {
+// case XC_STRING:
+// if (!textcomp(ops->parameter.string, deflt_expr, sinst))
+// nondefault = FALSE;
+// break;
+// case XC_EXPR:
+// ps_expr = evaluate_expr(sinst->thisobject, ops, sinst);
+// if (!strcmp(ps_expr, deflt_expr)) nondefault = FALSE;
+// break;
+// case XC_INT:
+// sscanf(deflt_expr, "%d", &i);
+// if (i == ops->parameter.ivalue) nondefault = FALSE;
+// break;
+// case XC_FLOAT:
+// sscanf(deflt_expr, "%g", &f);
+// if (f == ops->parameter.fvalue) nondefault = FALSE;
+// break;
+// }
+// if (deflt_expr) free(deflt_expr);
+// if (nondefault == FALSE) {
+// if (ps_expr) free(ps_expr);
+// continue;
+// }
+// }
+
+ if (instances++ == 0) {
+ fprintf(ps, "<<"); /* begin PostScript dictionary */
+ loccount = stcount + 2;
+ }
+ dostcount(ps, &loccount, strlen(validref) + 2);
+ fprintf(ps, "/%s ", validref);
+
+ switch (ops->type) {
+ case XC_STRING:
+ segs = writelabelsegs(ps, &loccount, ops->parameter.string);
+ if (segs == 0) {
+ /* When writing object parameters, we cannot allow a */
+ /* NULL value. Instead, print an empty string (). */
+ dostcount(ps, &stcount, 3);
+ fputs("() ", ps);
+ }
+ break;
+ case XC_EXPR:
+ ps_expr = evaluate_expr(sinst->thisobject, ops, sinst);
+ dostcount(ps, &loccount, 3 + strlen(ps_expr));
+ fputs("(", ps);
+ fputs(ps_expr, ps);
+ fputs(") ", ps);
+ free(ps_expr);
+
+ /* The instance parameter expression may have the */
+ /* same expression as the object but a different */
+ /* result if the expression uses another parameter. */
+ /* Only print the expression itself if it's different */
+ /* from the object's expression. */
+
+ objops = match_param(sinst->thisobject, ops->key);
+ if (objops && strcmp(ops->parameter.expr, objops->parameter.expr)) {
+ dostcount(ps, &loccount, 3 + strlen(ops->parameter.expr));
+ fputs("(", ps);
+ fputs(ops->parameter.expr, ps);
+ fputs(") pop ", ps);
+ }
+ break;
+ case XC_INT:
+ if (ops->which == P_COLOR) {
+ /* Write R, G, B components */
+ _STR[0] = '{';
+ printRGBvalues(_STR + 1, ops->parameter.ivalue, "} ");
+ }
+ else
+ sprintf(_STR, "%d ", ops->parameter.ivalue);
+ dostcount(ps, &loccount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+ case XC_FLOAT:
+ sprintf(_STR, "%g ", ops->parameter.fvalue);
+ dostcount(ps, &loccount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+ }
+ }
+ free(validref);
+ }
+ if (instances > 0) {
+ fprintf(ps, ">> "); /* end PostScript dictionary */
+ loccount += 3;
+ }
+ return loccount;
+}
+
+/*------------------------------------------------------------------*/
+/* Macro for point output (calls varpcheck() on x and y components) */
+/*------------------------------------------------------------------*/
+
+#define xyvarcheck(z, n, t) \
+ varpcheck(ps, (z).x, localdata, n, &stcount, *(t), P_POSITION_X); \
+ varpcheck(ps, (z).y, localdata, n, &stcount, *(t), P_POSITION_Y)
+
+#define xypathcheck(z, n, t, p) \
+ varpathcheck(ps, (z).x, localdata, n, &stcount, t, TOPATH(p), P_POSITION_X); \
+ varpathcheck(ps, (z).y, localdata, n, &stcount, t, TOPATH(p), P_POSITION_Y)
+
+/*--------------------------------------------------------------*/
+/* Main routine for writing the contents of a single object to */
+/* output file "ps". */
+/*--------------------------------------------------------------*/
+
+void printOneObject(FILE *ps, objectptr localdata, int ccolor)
+{
+ int i, curcolor = ccolor;
+ genericptr *savegen, *pgen;
+ objinstptr sobj;
+ graphicptr sg;
+ Imagedata *img;
+ pointlist savept;
+ short stcount;
+ short segs;
+ Boolean has_parameter;
+ char *fptr, *validname;
+
+ /* first, get a total count of all objects and give warning if large */
+
+
+ if ((is_page(localdata) == -1) && (localdata->parts > 255)) {
+ Wprintf("Warning: \"%s\" may exceed printer's PS limit for definitions",
+ localdata->name);
+ }
+
+ for (savegen = localdata->plist; savegen < localdata->plist +
+ localdata->parts; savegen++) {
+
+ /* Check if this color is parameterized */
+ eparamptr epp;
+ oparamptr ops;
+
+ for (epp = (*savegen)->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(localdata, epp->key);
+ if (ops != NULL && (ops->which == P_COLOR)) {
+ /* Ensure that the next element forces a color change */
+ curcolor = ERRORCOLOR;
+ sprintf(_STR, "%s scb\n", epp->key);
+ fputs(_STR, ps);
+ break;
+ }
+ }
+
+ /* Enforce the rule that clipmasks must always be DEFAULTCOLOR */
+
+ switch(ELEMENTTYPE(*savegen)) {
+ case POLYGON: case SPLINE: case ARC: case PATH:
+ if (TOPOLY(savegen)->style & CLIPMASK)
+ (*savegen)->color = DEFAULTCOLOR;
+ break;
+ }
+
+ /* change current color if different */
+
+ if ((epp == NULL) && ((*savegen)->color != curcolor)) {
+ if ((curcolor = (*savegen)->color) == DEFAULTCOLOR)
+ fprintf(ps, "sce\n");
+ else {
+ if (printRGBvalues(_STR, (*savegen)->color, "scb\n") < 0) {
+ fprintf(ps, "sce\n");
+ curcolor = DEFAULTCOLOR;
+ }
+ else
+ fputs(_STR, ps);
+ }
+ }
+
+ stcount = 0;
+ switch(ELEMENTTYPE(*savegen)) {
+
+ case(POLYGON):
+ varcheck(ps, TOPOLY(savegen)->style, localdata, &stcount,
+ *savegen, P_STYLE);
+ varfcheck(ps, TOPOLY(savegen)->width, localdata, &stcount,
+ *savegen, P_LINEWIDTH);
+ for (savept = TOPOLY(savegen)->points; savept < TOPOLY(savegen)->
+ points + TOPOLY(savegen)->number; savept++) {
+ varpcheck(ps, savept->x, localdata,
+ savept - TOPOLY(savegen)->points, &stcount, *savegen,
+ P_POSITION_X);
+ varpcheck(ps, savept->y, localdata,
+ savept - TOPOLY(savegen)->points, &stcount, *savegen,
+ P_POSITION_Y);
+ }
+ sprintf(_STR, "%hd ", TOPOLY(savegen)->number);
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ if (varpcheck(ps, 0, localdata, -1, &stcount, *savegen,
+ P_POSITION_X)) {
+ sprintf(_STR, "addtox ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ if (varpcheck(ps, 0, localdata, -1, &stcount, *savegen,
+ P_POSITION_Y)) {
+ sprintf(_STR, "addtoy ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ sprintf(_STR, "polygon\n");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+
+ case(PATH):
+ pgen = TOPATH(savegen)->plist;
+ switch(ELEMENTTYPE(*pgen)) {
+ case POLYGON:
+ xypathcheck(TOPOLY(pgen)->points[0], 0, pgen, savegen);
+ break;
+ case SPLINE:
+ xypathcheck(TOSPLINE(pgen)->ctrl[0], 0, pgen, savegen);
+ break;
+ }
+ dostcount(ps, &stcount, 9);
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_X)) {
+ sprintf(_STR, "addtox1 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_Y)) {
+ sprintf(_STR, "addtoy1 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ fprintf(ps, "beginpath\n");
+ for (pgen = TOPATH(savegen)->plist; pgen < TOPATH(savegen)->plist
+ + TOPATH(savegen)->parts; pgen++) {
+ switch(ELEMENTTYPE(*pgen)) {
+ case POLYGON:
+ for (savept = TOPOLY(pgen)->points + TOPOLY(pgen)->number
+ - 1; savept > TOPOLY(pgen)->points; savept--) {
+ xypathcheck(*savept, savept - TOPOLY(pgen)->points, pgen,
+ savegen);
+ }
+ sprintf(_STR, "%hd ", TOPOLY(pgen)->number - 1);
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_X)) {
+ sprintf(_STR, "addtox ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_Y)) {
+ sprintf(_STR, "addtoy ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ sprintf(_STR, "polyc\n");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ break;
+ case SPLINE:
+ xypathcheck(TOSPLINE(pgen)->ctrl[1], 1, pgen, savegen);
+ xypathcheck(TOSPLINE(pgen)->ctrl[2], 2, pgen, savegen);
+ xypathcheck(TOSPLINE(pgen)->ctrl[3], 3, pgen, savegen);
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_X)) {
+ sprintf(_STR, "addtox3 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ if (varpathcheck(ps, 0, localdata, -1, &stcount, pgen,
+ TOPATH(savegen), P_POSITION_Y)) {
+ sprintf(_STR, "addtoy3 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ fprintf(ps, "curveto\n");
+ break;
+ }
+ }
+ varcheck(ps, TOPATH(savegen)->style, localdata, &stcount,
+ *savegen, P_STYLE);
+ varfcheck(ps, TOPATH(savegen)->width, localdata, &stcount,
+ *savegen, P_LINEWIDTH);
+ fprintf(ps, "endpath\n");
+ break;
+
+ case(SPLINE):
+ varcheck(ps, TOSPLINE(savegen)->style, localdata, &stcount,
+ *savegen, P_STYLE);
+ varfcheck(ps, TOSPLINE(savegen)->width, localdata, &stcount,
+ *savegen, P_LINEWIDTH);
+ xyvarcheck(TOSPLINE(savegen)->ctrl[1], 1, savegen);
+ xyvarcheck(TOSPLINE(savegen)->ctrl[2], 2, savegen);
+ xyvarcheck(TOSPLINE(savegen)->ctrl[3], 3, savegen);
+ xyvarcheck(TOSPLINE(savegen)->ctrl[0], 0, savegen);
+ if (varpcheck(ps, 0, localdata, -1, &stcount, *savegen,
+ P_POSITION_X)) {
+ sprintf(_STR, "addtox4 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ if (varpcheck(ps, 0, localdata, -1, &stcount, *savegen,
+ P_POSITION_Y)) {
+ sprintf(_STR, "addtoy4 ");
+ dostcount (ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ fprintf(ps, "spline\n");
+ break;
+
+ case(ARC):
+ varcheck(ps, TOARC(savegen)->style, localdata, &stcount,
+ *savegen, P_STYLE);
+ varfcheck(ps, TOARC(savegen)->width, localdata, &stcount,
+ *savegen, P_LINEWIDTH);
+ xyvarcheck(TOARC(savegen)->position, 0, savegen);
+ varcheck(ps, abs(TOARC(savegen)->radius), localdata, &stcount,
+ *savegen, P_RADIUS);
+ if (abs(TOARC(savegen)->radius) == TOARC(savegen)->yaxis) {
+ varfcheck(ps, TOARC(savegen)->angle1, localdata, &stcount,
+ *savegen, P_ANGLE1);
+ varfcheck(ps, TOARC(savegen)->angle2, localdata, &stcount,
+ *savegen, P_ANGLE2);
+ fprintf(ps, "xcarc\n");
+ }
+ else {
+ varcheck(ps, abs(TOARC(savegen)->yaxis), localdata, &stcount,
+ *savegen, P_MINOR_AXIS);
+ varfcheck(ps, TOARC(savegen)->angle1, localdata, &stcount,
+ *savegen, P_ANGLE1);
+ varfcheck(ps, TOARC(savegen)->angle2, localdata, &stcount,
+ *savegen, P_ANGLE2);
+ fprintf(ps, "ellipse\n");
+ }
+ break;
+
+ case(OBJINST):
+ sobj = TOOBJINST(savegen);
+ varfcheck(ps, sobj->scale, localdata, &stcount, *savegen, P_SCALE);
+ if (!(sobj->style & LINE_INVARIANT)) fprintf(ps, "/sv ");
+ varcheck(ps, sobj->rotation, localdata, &stcount, *savegen, P_ROTATION);
+ xyvarcheck(sobj->position, 0, savegen);
+
+ opsubstitute(sobj->thisobject, sobj);
+ stcount = printparams(ps, sobj, stcount);
+
+ validname = create_valid_psname(sobj->thisobject->name, FALSE);
+
+ /* Names without technologies get a leading string '::' */
+ /* (blank technology) */
+
+ if (strstr(validname, "::") == NULL)
+ fprintf(ps, "::%s\n", validname);
+ else
+ fprintf(ps, "%s\n", validname);
+ break;
+
+ case(GRAPHIC):
+ sg = TOGRAPHIC(savegen);
+ for (i = 0; i < xobjs.images; i++) {
+ img = xobjs.imagelist + i;
+ if (img->image == sg->source)
+ break;
+ }
+
+ fptr = strrchr(img->filename, '/');
+ if (fptr == NULL)
+ fptr = img->filename;
+ else
+ fptr++;
+ fprintf(ps, "/%s ", fptr);
+ stcount += (2 + strlen(fptr));
+
+ varfcheck(ps, sg->scale, localdata, &stcount, *savegen, P_SCALE);
+ varcheck(ps, sg->rotation, localdata, &stcount, *savegen, P_ROTATION);
+ xyvarcheck(sg->position, 0, savegen);
+ fprintf(ps, "graphic\n");
+ break;
+
+ case(LABEL):
+
+ /* Don't save temporary labels from schematic capture system */
+ if (TOLABEL(savegen)->string->type != FONT_NAME) break;
+
+ /* Check for parameter --- must use "mark" to count # segments */
+ has_parameter = hasparameter(TOLABEL(savegen));
+
+ if (has_parameter) {
+ fprintf(ps, "mark ");
+ stcount += 5;
+ }
+
+ segs = writelabel(ps, TOLABEL(savegen)->string, &stcount);
+
+ if (segs > 0) {
+ if (has_parameter)
+ sprintf(_STR, "ctmk ");
+ else
+ sprintf(_STR, "%hd ", segs);
+ dostcount(ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ varcheck(ps, TOLABEL(savegen)->justify, localdata, &stcount,
+ *savegen, P_JUSTIFY);
+ varcheck(ps, TOLABEL(savegen)->rotation, localdata, &stcount,
+ *savegen, P_ROTATION);
+ varfcheck(ps, TOLABEL(savegen)->scale, localdata, &stcount,
+ *savegen, P_SCALE);
+ xyvarcheck(TOLABEL(savegen)->position, 0, savegen);
+
+ switch(TOLABEL(savegen)->pin) {
+ case LOCAL:
+ strcpy(_STR, "pinlabel\n"); break;
+ case GLOBAL:
+ strcpy(_STR, "pinglobal\n"); break;
+ case INFO:
+ strcpy(_STR, "infolabel\n"); break;
+ default:
+ strcpy(_STR, "label\n");
+ }
+ dostcount(ps, &stcount, strlen(_STR));
+ fputs(_STR, ps);
+ }
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive routine to print out the library objects used in this */
+/* drawing, starting at the bottom of the object hierarchy so that each */
+/* object is defined before it is called. A list of objects already */
+/* written is maintained so that no object is written twice. */
+/* */
+/* When object "localdata" is not a top-level page, call this routine */
+/* with mpage=-1 (simpler than checking whether localdata is a page). */
+/*----------------------------------------------------------------------*/
+
+void printobjects(FILE *ps, objectptr localdata, objectptr **wrotelist,
+ short *written, int ccolor)
+{
+ genericptr *gptr;
+ objectptr *optr;
+ /* oparamptr ops; (jdk) */
+ char *validname;
+ int curcolor = ccolor;
+ /* int libno; (jdk) */
+
+ /* Search among the list of objects already written to the output */
+ /* If this object has been written previously, then we ignore it. */
+
+ for (optr = *wrotelist; optr < *wrotelist + *written; optr++)
+ if (*optr == localdata)
+ return;
+
+ /* If this page is a schematic, write out the definiton of any symbol */
+ /* attached to it, because that symbol may not be used anywhere else. */
+
+ if (localdata->symschem && (localdata->schemtype == PRIMARY))
+ printobjects(ps, localdata->symschem, wrotelist, written, curcolor);
+
+ /* Search for all object definitions instantiated in this object, */
+ /* and (recursively) print them to the output. */
+
+ for (gptr = localdata->plist; gptr < localdata->plist + localdata->parts; gptr++)
+ if (IS_OBJINST(*gptr))
+ printobjects(ps, TOOBJINST(gptr)->thisobject, wrotelist, written, curcolor);
+
+ /* Update the list of objects already written to the output */
+
+ *wrotelist = (objectptr *)realloc(*wrotelist, (*written + 1) *
+ sizeof(objectptr));
+ *(*wrotelist + *written) = localdata;
+ (*written)++;
+
+ validname = create_valid_psname(localdata->name, FALSE);
+ if (strstr(validname, "::") == NULL)
+ fprintf(ps, "/::%s {\n", validname);
+ else
+ fprintf(ps, "/%s {\n", validname);
+
+ /* No longer writes "bbox" record */
+ if (localdata->hidden == True) fprintf(ps, "%% hidden\n");
+
+ /* For symbols with schematics, and "trivial" schematics */
+ if (localdata->symschem != NULL)
+ fprintf(ps, "%% %s is_schematic\n", localdata->symschem->name);
+ else if (localdata->schemtype == TRIVIAL)
+ fprintf(ps, "%% trivial\n");
+ else if (localdata->schemtype == NONETWORK)
+ fprintf(ps, "%% nonetwork\n");
+
+ printobjectparams(ps, localdata);
+ fprintf(ps, "begingate\n");
+
+ /* Write all the elements in order */
+
+ opsubstitute(localdata, NULL);
+ printOneObject(ps, localdata, curcolor);
+
+ /* Write object (gate) trailer */
+
+ fprintf(ps, "endgate\n} def\n\n");
+}
+
+/*--------------------------------------------------------------*/
+/* Print a page header followed by everything in the page. */
+/* this routine assumes that all objects used by the page have */
+/* already been handled and written to the output. */
+/* */
+/* "page" is the page number, counting consecutively from one. */
+/* "mpage" is the page number in xcircuit's pagelist structure. */
+/*--------------------------------------------------------------*/
+
+void printpageobject(FILE *ps, objectptr localdata, short page, short mpage)
+{
+ /* genericptr *gptr; (jdk) */
+ XPoint origin, corner;
+ objinstptr writepage;
+ int width, height;
+ float psnorm, psscale;
+ float xmargin, ymargin;
+ char *rootptr = NULL;
+ polyptr framebox;
+
+ /* Output page header information */
+
+ if (xobjs.pagelist[mpage]->filename)
+ rootptr = strrchr(xobjs.pagelist[mpage]->filename, '/');
+ if (rootptr == NULL)
+ rootptr = xobjs.pagelist[mpage]->filename;
+ else rootptr++;
+
+ writepage = xobjs.pagelist[mpage]->pageinst;
+
+ psnorm = xobjs.pagelist[mpage]->outscale;
+ psscale = getpsscale(psnorm, mpage);
+
+ /* Determine the margins (offset of drawing from page corner) */
+ /* If a bounding box has been declared in the drawing, it is */
+ /* centered on the page. Otherwise, the drawing itself is */
+ /* centered on the page. If encapsulated, the bounding box */
+ /* encompasses only the object itself. */
+
+ width = toplevelwidth(writepage, &origin.x);
+ height = toplevelheight(writepage, &origin.y);
+
+ corner.x = origin.x + width;
+ corner.y = origin.y + height;
+
+ if (xobjs.pagelist[mpage]->pmode & 1) { /* full page */
+
+ if (xobjs.pagelist[mpage]->orient == 90) {
+ xmargin = (xobjs.pagelist[mpage]->pagesize.x -
+ ((float)height * psscale)) / 2;
+ ymargin = (xobjs.pagelist[mpage]->pagesize.y -
+ ((float)width * psscale)) / 2;
+ }
+ else {
+ xmargin = (xobjs.pagelist[mpage]->pagesize.x -
+ ((float)width * psscale)) / 2;
+ ymargin = (xobjs.pagelist[mpage]->pagesize.y -
+ ((float)height * psscale)) / 2;
+ }
+ }
+ else { /* encapsulated --- should have 1" border so that any */
+ /* drawing passed directly to a printer will not clip */
+ xmargin = xobjs.pagelist[mpage]->margins.x;
+ ymargin = xobjs.pagelist[mpage]->margins.y;
+ }
+
+ /* If a framebox is declared, then we adjust the page to be */
+ /* centered on the framebox by translating through the */
+ /* difference between the object center and the framebox */
+ /* center. */
+
+ if ((framebox = checkforbbox(localdata)) != NULL) {
+ int i, fcentx = 0, fcenty = 0;
+
+ for (i = 0; i < framebox->number; i++) {
+ fcentx += framebox->points[i].x;
+ fcenty += framebox->points[i].y;
+ }
+ fcentx /= framebox->number;
+ fcenty /= framebox->number;
+
+ xmargin += psscale * (float)(origin.x + (width >> 1) - fcentx);
+ ymargin += psscale * (float)(origin.y + (height >> 1) - fcenty);
+ }
+
+ /* If the page label is just the root name of the file, or has been left */
+ /* as "Page n" or "Page_n", just do the normal page numbering. Otherwise, */
+ /* write out the page label explicitly. */
+
+ if ((rootptr == NULL) || (!strcmp(rootptr, localdata->name))
+ || (strchr(localdata->name, ' ') != NULL)
+ || (strstr(localdata->name, "Page_") != NULL))
+ fprintf (ps, "%%%%Page: %d %d\n", page, page);
+ else
+ fprintf (ps, "%%%%Page: %s %d\n", localdata->name, page);
+
+ if (xobjs.pagelist[mpage]->orient == 90)
+ fprintf (ps, "%%%%PageOrientation: Landscape\n");
+ else
+ fprintf (ps, "%%%%PageOrientation: Portrait\n");
+
+ if (xobjs.pagelist[mpage]->pmode & 1) { /* full page */
+ fprintf(ps, "%%%%PageBoundingBox: 0 0 %d %d\n",
+ xobjs.pagelist[mpage]->pagesize.x,
+ xobjs.pagelist[mpage]->pagesize.y);
+ }
+
+ /* Encapsulated files do not get a PageBoundingBox line, */
+ /* unless the bounding box was explicitly drawn. */
+
+ else if (framebox != NULL) {
+ fprintf(ps, "%%%%PageBoundingBox: %g %g %g %g\n",
+ xmargin, ymargin,
+ xmargin + psscale * (float)(width),
+ ymargin + psscale * (float)(height));
+ }
+
+ fprintf (ps, "/pgsave save def bop\n");
+
+ /* Top-page definitions */
+ if (localdata->params != NULL) {
+ printobjectparams(ps, localdata);
+ fprintf(ps, "begin\n");
+ }
+
+ if (localdata->symschem != NULL) {
+ if (is_page(localdata->symschem) == -1)
+ fprintf(ps, "%% %s is_symbol\n", localdata->symschem->name);
+ else if (localdata->schemtype == SECONDARY)
+ fprintf(ps, "%% %s is_primary\n", localdata->symschem->name);
+ else
+ Wprintf("Something is wrong. . . schematic \"%s\" is connected to"
+ " schematic \"%s\" but is not declared secondary.\n",
+ localdata->name, localdata->symschem->name);
+ }
+
+ /* Extend bounding box around schematic pins */
+ extendschembbox(xobjs.pagelist[mpage]->pageinst, &origin, &corner);
+
+ if (xobjs.pagelist[mpage]->drawingscale.x != 1
+ || xobjs.pagelist[mpage]->drawingscale.y != 1)
+ fprintf(ps, "%% %hd:%hd drawingscale\n", xobjs.pagelist[mpage]->drawingscale.x,
+ xobjs.pagelist[mpage]->drawingscale.y);
+
+ if (xobjs.pagelist[mpage]->gridspace != 32
+ || xobjs.pagelist[mpage]->snapspace != 16)
+ fprintf(ps, "%% %4.2f %4.2f gridspace\n", xobjs.pagelist[mpage]->gridspace,
+ xobjs.pagelist[mpage]->snapspace);
+
+ if (xobjs.pagelist[mpage]->background.name != (char *)NULL) {
+ /* float iscale = (xobjs.pagelist[mpage]->coordstyle == CM) ? CMSCALE : INCHSCALE; (jdk) */
+ if (xobjs.pagelist[mpage]->orient == 90)
+ fprintf(ps, "%5.4f %d %d 90 psinsertion\n", psnorm,
+ (int)(ymargin - xmargin),
+ -((int)((float)(corner.y - origin.y) * psscale) +
+ (int)(xmargin + ymargin)));
+ else
+ fprintf(ps, "%5.4f %d %d 0 psinsertion\n", psnorm,
+ (int)(xmargin / psscale) - origin.x,
+ (int)(ymargin / psscale) - origin.y);
+ savebackground(ps, xobjs.pagelist[mpage]->background.name);
+ fprintf(ps, "\nend_insert\n");
+ }
+
+ if (xobjs.pagelist[mpage]->orient == 90)
+ fprintf(ps, "90 rotate %d %d translate\n", (int)(ymargin - xmargin),
+ -((int)((float)(corner.y - origin.y) * psscale) +
+ (int)(xmargin + ymargin)));
+
+ fprintf(ps, "%5.4f ", psnorm);
+ switch(xobjs.pagelist[mpage]->coordstyle) {
+ case CM:
+ fprintf(ps, "cmscale\n");
+ break;
+ default:
+ fprintf(ps, "inchscale\n");
+ break;
+ }
+
+ /* Final scale and translation */
+ fprintf(ps, "%5.4f setlinewidth %d %d translate\n\n",
+ 1.3 * xobjs.pagelist[mpage]->wirewidth,
+ (int)(xmargin / psscale) - origin.x,
+ (int)(ymargin / psscale) - origin.y);
+
+ /* Output all the elements in the page */
+ printOneObject(ps, localdata, DEFAULTCOLOR);
+
+ /* Page trailer */
+ if (localdata->params != NULL) fprintf(ps, "end ");
+ fprintf(ps, "pgsave restore showpage\n");
+}
+
+/*--------------------------------------------------------------*/
+/* Print objects referenced from a particular page. These get */
+/* bundled together at the beginning of the output file under */
+/* the DSC "Setup" section, so that the PostScript */
+/* interpreter knows that these definitions may be used by any */
+/* page. This prevents ghostscript from producing an error */
+/* when backing up in a multi-page document. */
+/*--------------------------------------------------------------*/
+
+void printrefobjects(FILE *ps, objectptr localdata, objectptr **wrotelist,
+ short *written)
+{
+ genericptr *gptr;
+
+ /* If this page is a schematic, write out the definiton of any symbol */
+ /* attached to it, because that symbol may not be used anywhere else. */
+
+ if (localdata->symschem && (localdata->schemtype == PRIMARY))
+ printobjects(ps, localdata->symschem, wrotelist, written, DEFAULTCOLOR);
+
+ /* Search for all object definitions instantiated on the page and */
+ /* write them to the output. */
+
+ for (gptr = localdata->plist; gptr < localdata->plist + localdata->parts; gptr++)
+ if (IS_OBJINST(*gptr))
+ printobjects(ps, TOOBJINST(gptr)->thisobject, wrotelist, written,
+ DEFAULTCOLOR);
+}
+
+/*----------------------------------------------------------------------*/
diff --git a/flate.c b/flate.c
new file mode 100644
index 0000000..c94eed3
--- /dev/null
+++ b/flate.c
@@ -0,0 +1,147 @@
+/*
+ * flate.c
+ *
+ * Copyright (c) Sergei Gerasenko 2003-2004.
+ *
+ * This defines the prototypes of the functions used for compressing
+ * and decompressing PDF streams. All of them utilize the zlib library
+ * and in fact the functions themselves are slightly modified versions
+ * of those included in an example file that came with the library. Kudos
+ * to the authors of zlib and everybody else involved in its development.
+ *
+ * This file was taken from the SourceForge project "acroformtool". Files
+ * "compression.c" and "compression.h" have been merged and modified as
+ * needed to facilitate compilation in xcircuit. Thanks once again to the
+ * open source community.
+ */
+
+#ifdef HAVE_LIBZ
+
+#include <stdio.h>
+#include <zlib.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#include "Xw/Xw.h"
+#endif
+
+#include "xcircuit.h"
+#include "prototypes.h" /* (jdk) */
+
+/*
+ * Substitute for original macro CHECK_ERROR
+ * Return 1 on error, 0 on success
+ */
+
+int check_error(int err, char *prompt, char *msg) {
+ if (err != Z_OK) {
+ Fprintf(stderr, "%s error: %d", prompt, err);
+ if (msg) Fprintf(stderr, "(%s)", msg);
+ Fprintf(stderr, "\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * deflate() with large buffers
+ */
+
+u_long large_deflate (u_char *compr, u_long compr_len,
+ u_char *uncompr, u_long uncompr_len) {
+
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ if (check_error(err, "deflateInit", c_stream.msg)) return 0;
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (u_int)compr_len;
+
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (u_int)uncompr_len;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ if (check_error(err, "deflate", c_stream.msg)) return 0;
+ if (c_stream.avail_in != 0) {
+ Fprintf(stderr, "deflate not greedy");
+ }
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ Fprintf(stderr, "deflate should report Z_STREAM_END");
+ }
+ err = deflateEnd(&c_stream);
+ if (check_error(err, "deflateEnd", c_stream.msg)) return 0;
+
+ /* Fprintf(stdout, "large_deflate(): OK\n"); */
+
+ return c_stream.total_out;
+}
+
+/*
+ * inflate() with large buffers
+ */
+
+u_long large_inflate(u_char *compr, u_long compr_len,
+ u_char **uncompr, u_long uncompr_len) {
+
+ char *new_out_start;
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (u_int)compr_len;
+
+ err = inflateInit(&d_stream);
+ if (check_error(err, "inflateInit", d_stream.msg)) return 0;
+
+ d_stream.next_out = *uncompr;
+ d_stream.avail_out = (u_int)uncompr_len;
+
+ for (;;) {
+ if (!d_stream.avail_out) {
+ /* Make more memory for the decompression buffer */
+ *uncompr = realloc(*uncompr, uncompr_len * 2);
+
+ /* Initialize new memory */
+ new_out_start = *uncompr + uncompr_len;
+ memset(new_out_start, 0, uncompr_len);
+
+ /* Point next_out to the next unused byte */
+ d_stream.next_out = new_out_start;
+
+ /* Update the size of the uncompressed buffer */
+ d_stream.avail_out = (u_int)uncompr_len;
+ }
+
+ err = inflate(&d_stream, Z_NO_FLUSH);
+
+ if (err == Z_STREAM_END) break;
+
+ if (check_error(err, "large inflate", d_stream.msg)) return 0;
+ }
+
+ err = inflateEnd(&d_stream);
+ if (check_error(err, "inflateEnd", d_stream.msg)) return 0;
+
+ /* Fprintf(stdout, "large_inflate(): OK\n"); */
+
+ return d_stream.total_out;
+}
+
+#endif /* HAVE_LIBZ */
diff --git a/fontfile.c b/fontfile.c
new file mode 100644
index 0000000..19bf64a
--- /dev/null
+++ b/fontfile.c
@@ -0,0 +1,384 @@
+/*-------------------------------------------------------------------------*/
+/* fontfile.c --- Load font character and encoding defitions */
+/* Copyright (c) 2001 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*-------------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*-------------------------------------------------------------------------*/
+
+extern char _STR2[250], _STR[150];
+
+extern short fontcount;
+extern fontinfo *fonts;
+
+extern Globaldata xobjs;
+extern short beeper;
+
+extern float version;
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Find the file containing the encoding for the given font */
+/*----------------------------------------------------------------------*/
+
+FILE *findfontfile(char *fontname)
+{
+ int i;
+ char tempname[256];
+ FILE *fd;
+
+ /* Add subdirectory "fonts". We will try both with and */
+ /* without the subdirectory. */
+
+ sprintf(_STR, "fonts/%s", fontname);
+
+ /* change string to all lowercase and remove dashes */
+
+ for (i = 0; i < strlen(_STR); i++) {
+ _STR[i] = tolower(_STR[i]);
+ if (_STR[i] == '-') _STR[i] = '_';
+ }
+
+ /* Fprintf(stdout, "Searching for font file \"%s\"\n", _STR); */
+
+ /* Use the mechanism of "libopen" to find the encoding file */
+ /* in the search path */
+
+ fd = libopen(_STR + 6, FONTENCODING, NULL, 0);
+
+ if (fd == NULL) fd = libopen(_STR, FONTENCODING, NULL, 0);
+
+ /* Some other, probably futile, attempts (call findfontfile recursively) */
+
+ if (fd == NULL) {
+ char *dashptr;
+
+ /* If this font has a suffix, remove it and look for its root */
+ /* font on the supposition that this font is derived from the */
+ /* root font. */
+
+ strncpy(tempname, fontname, 99);
+ if ((dashptr = strrchr(tempname, '-')) != NULL) {
+ *dashptr = '\0';
+ if ((fd = findfontfile(tempname)) != NULL) return fd;
+
+ /* And finally, because it's a common case, try adding */
+ /* -Roman and trying again (but don't infinite loop!) */
+
+ if (strcmp(dashptr + 1, "Roman")) {
+ strcat(dashptr, "-Roman");
+ if ((fd = findfontfile(tempname)) != NULL) return fd;
+ }
+ }
+
+ Wprintf("No font encoding file found.");
+ if (fontcount > 0) { /* Make font substitution */
+ char *dchr, *psname = NULL;
+ short fval;
+
+ if ((dchr = strrchr(_STR, '.')) != NULL) *dchr = '\0';
+ if ((fval = findhelvetica()) == fontcount) {
+ /* This will cause some chaos. . . */
+ Fprintf(stderr, "Error: No fonts available! Check library path?\n");
+ exit(1);
+ }
+
+ psname = (char *)malloc((1 + strlen(fontname)) * sizeof(char));
+ strcpy(psname, fontname);
+ Wprintf("No encoding file found for font %s: substituting %s",
+ psname, fonts[fval].psname);
+ fonts = (fontinfo *)realloc(fonts, (fontcount + 1) * sizeof(fontinfo));
+ fonts[fontcount].psname = psname;
+ fonts[fontcount].family = psname;
+ fonts[fontcount].encoding = fonts[fval].encoding;
+ fonts[fontcount].flags = 0;
+ fonts[fontcount].scale = 1.0;
+ fontcount++;
+ makenewfontbutton();
+ }
+ else {
+ Fprintf(stderr, "Error: font encoding file missing for font \"%s\"\n",
+ fontname);
+ Fprintf(stderr, "No fonts exist for a subsitution. Make sure "
+ "fonts are installed or that\nenvironment variable "
+ "XCIRCUIT_LIB_DIR points to a directory of valid fonts.\n");
+ }
+ return (FILE *)NULL;
+ }
+ return fd;
+}
+
+/*----------------------------------------------------------------------*/
+/* Load a named font */
+/* Return 1 if successful, 0 if font is already present, and -1 if any */
+/* other error occurred. */
+/*----------------------------------------------------------------------*/
+
+int loadfontfile(char *fontname)
+{
+ FILE *fd;
+ char temp[250], commandstr[30], tempname[100];
+ char *psname = NULL, *family = NULL;
+ char *cmdptr;
+ int flags = 0;
+ int i;
+ float fontscale = 1.0;
+ objectptr *j, *eptr;
+ objectptr *encoding = NULL;
+ float saveversion = version;
+
+ /* check to see if font name is in list of fonts */
+
+ for (i = 0; i < fontcount; i++) {
+ if (!strcmp(fonts[i].psname, fontname)) {
+ return 0;
+ }
+ }
+ if ((fd = findfontfile(fontname)) == NULL) return -1;
+
+ while (fgets(temp, 249, fd) != NULL) {
+ if (*temp == '\n') continue;
+ sscanf(temp, "%29s", commandstr);
+ for(cmdptr = commandstr; isspace(*cmdptr); cmdptr++);
+
+ /* very liberal about comment line characters */
+
+ if (*cmdptr == '#' || *cmdptr == '%' || *cmdptr == ';');
+
+ else if (!strcmp(cmdptr, "name:")) {
+ sscanf(temp, "%*s %99s", tempname);
+
+ /* If font is already in list, ignore it */
+ /* This condition should be caught at the top of the routine. . . */
+
+ for (i = 0; i < fontcount; i++) {
+ if (!strcmp(fonts[i].psname, tempname)) {
+ /* Fprintf(stdout, "Font already loaded.\n"); */
+ fclose(fd);
+ return 0;
+ }
+ }
+ psname = (char *)malloc((1 + strlen(tempname)) * sizeof(char));
+ strcpy(psname, tempname);
+ }
+
+ else if (!strcmp(cmdptr, "file:") || !strcmp(cmdptr, "load:")) {
+ /* Fprintf(stdout, "found file identifier in xfe file\n"); */
+ sscanf(temp, "%*s %149s", _STR);
+
+ /* since we can be in the middle of a file load, protect the */
+ /* current version number for the file load. */
+
+ version = PROG_VERSION;
+ if (loadlibrary(FONTLIB) == FALSE) {
+ };
+ version = saveversion;
+ }
+
+ else if (!strcmp(cmdptr, "family:")){
+ sscanf(temp, "%*s %99s", tempname);
+ family = (char *)malloc((1 + strlen(tempname)) * sizeof(char));
+ strcpy(family, tempname);
+ }
+
+ else if (!strcmp(cmdptr, "weight:")){
+ sscanf(temp, "%*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "bold"))
+ flags |= 0x01;
+ }
+
+ else if (!strcmp(cmdptr, "shape:")){
+ sscanf(temp, "%*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "italic") || !strcmp(tempname, "oblique")
+ || !strcmp(tempname, "slanted"))
+ flags |= 0x02;
+ }
+
+ else if (!strcmp(cmdptr, "scale:")){
+ sscanf(temp, "%*s %f", &fontscale);
+ }
+
+ else if (!strcmp(cmdptr, "type:")) {
+ sscanf(temp, "%*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "drawn") || !strcmp(tempname, "vectored"))
+ flags |= 0x08;
+ }
+
+ else if (!strcmp(cmdptr, "derived:")) {
+ if (encoding == NULL) {
+ Fprintf(stdout, "Font warning: \"derived\" statement must come "
+ "after encoding\n");
+ }
+ else {
+ char *psname2;
+ sscanf(temp, "%*s %99s", tempname);
+ psname2 = (char *)malloc((1 + strlen(tempname)) * sizeof(char));
+ strcpy(psname2, tempname);
+ flags &= 0xffe0; /* shares these flags with original */
+ flags |= 0x020; /* derived font flag */
+
+ /* determine rest of flags */
+
+ sscanf(temp, "%*s %*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "bold"))
+ flags |= 0x1;
+
+ sscanf(temp, "%*s %*s %*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "italic") || !strcmp(tempname, "oblique"))
+ flags |= 0x2;
+
+ sscanf(temp, "%*s %*s %*s %*s %99s", tempname);
+ tempname[0] = tolower(tempname[0]);
+ if (!strcmp(tempname, "drawn") || !strcmp(tempname, "vectored"))
+ flags |= 0x08;
+ else if (!strcmp(tempname, "special"))
+ flags |= 0x10;
+
+ /* generate a new fontinfo entry for the derived font */
+
+ fonts = (fontinfo *) realloc (fonts, (fontcount + 1) * sizeof(fontinfo));
+ fonts[fontcount].psname = psname2;
+ if (family == NULL)
+ fonts[fontcount].family = psname;
+ else
+ fonts[fontcount].family = family;
+ fonts[fontcount].encoding = encoding; /* use original encoding */
+ fonts[fontcount].flags = flags;
+ fonts[fontcount].scale = fontscale;
+ fontcount++;
+ }
+ }
+
+ else if (!strcmp(cmdptr, "encoding:")) {
+ sscanf(temp, "%*s %99s", tempname);
+
+ if (!strcmp(tempname, "special") || !strcmp(tempname, "Special")) {
+ flags |= 0x80;
+#ifdef TCL_WRAPPER
+ XcInternalTagCall(xcinterp, 3, "label", "encoding", "Special");
+#else
+ makenewencodingbutton("Special", (char)1);
+#endif
+ }
+
+ /* ISO-LatinX encodings where X=1 to 6 */
+
+ if (strstr(tempname, "ISO") != NULL) {
+ char estr[12];
+ for (i = 0; i < 6; i++) {
+ if (strchr(tempname, '1' + (char)i) != NULL) {
+ flags |= ((i + 2) << 7);
+#ifdef TCL_WRAPPER
+ snprintf(estr, sizeof(estr), "ISOLatin%d", i + 1);
+ XcInternalTagCall(xcinterp, 3, "label", "encoding", estr);
+#else
+ snprintf(estr, sizeof(estr), "ISO-Latin%d", i + 1);
+ makenewencodingbutton(estr, (char)(i + 2));
+#endif
+ break;
+ }
+ }
+ }
+
+ /* Make space for the font encoding vector */
+
+ encoding = (objectptr *)malloc(256 * sizeof(objectptr));
+ eptr = encoding;
+
+ while (fgets(temp, 249, fd) != NULL) {
+ char *temp2 = temp;
+ while (*temp2 != '\0') {
+ if ((int)(eptr - encoding) == 256) break;
+ sscanf(temp2, "%99s", tempname);
+ *eptr = (objectptr) NULL;
+ for (j = xobjs.fontlib.library; j < xobjs.fontlib.library +
+ xobjs.fontlib.number; j++) {
+ if (!strcmp(tempname, (*j)->name)) {
+ *eptr = (*j);
+ break;
+ }
+ }
+ if (j == xobjs.fontlib.library + xobjs.fontlib.number) {
+ Fprintf(stdout, "Font load warning: character \"%s\" at code ",
+ tempname);
+ Fprintf(stdout, "position %d not found.\n", (int)(eptr - encoding));
+ }
+ eptr++;
+ while (*temp2 != ' ' && *temp2 != '\n' && *temp2 != '\0') temp2++;
+ while (*temp2 == ' ' || *temp2 == '\n') temp2++;
+ }
+ if ((int)(eptr - encoding) == 256) break;
+ }
+ if ((int)(eptr - encoding) != 256) {
+ Fprintf(stdout, "Font load warning: Only %d characters encoded.\n",
+ (int)(eptr - encoding));
+ while (eptr < encoding + 256)
+ *eptr++ = (objectptr) NULL;
+ }
+
+ /* If successful, register the font */
+
+ fonts = (fontinfo *) realloc (fonts, (fontcount + 1) * sizeof(fontinfo));
+ fonts[fontcount].psname = psname;
+ if (family == NULL)
+ fonts[fontcount].family = psname;
+ else
+ fonts[fontcount].family = family;
+ fonts[fontcount].encoding = encoding;
+ fonts[fontcount].flags = flags;
+ fonts[fontcount].scale = fontscale;
+ fontcount++;
+
+ /* Create a new menu button for the font family, if this is the first */
+ /* (In Tcl, this just registers the family name for cycling through */
+ /* via Alt-F; the menu update is done via command tag callback). */
+
+ for (i = 0; i < fontcount - 1; i++)
+ if (!strcmp(fonts[i].family, fonts[fontcount - 1].family))
+ break;
+
+ if (i == fontcount - 1)
+ makenewfontbutton();
+ }
+ }
+ fclose(fd);
+ return 1;
+}
diff --git a/formats.c b/formats.c
new file mode 100644
index 0000000..5c86c99
--- /dev/null
+++ b/formats.c
@@ -0,0 +1,676 @@
+/*-----------------------------------------------------------------------*/
+/* formats.c --- input file support for xcircuit */
+/* Copyright (c) 2001 Tim Edwards, Johns Hopkins University */
+/*-----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+/*------------------------------------------------------------------------*/
+/* Local includes */
+/*------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*------------------------------------------------------------------------*/
+/* Useful (local) defines */
+/*------------------------------------------------------------------------*/
+
+#define xmat(a) (((a) - 3300) << 4)
+#define ymat(a) ((3300 - (a)) << 4)
+#define S_OBLIQUE 13 /* position of Symbol-Oblique in font array */
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+extern char _STR[150];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern Display *dpy;
+extern int *appcolors;
+
+/*----------------------------------------------*/
+#ifdef LGF
+
+/*----------------------------------------------*/
+/* loadlgf: Load an analog LGF file */
+/* mode = 1: import into current page; */
+/* mode = 0 clear current page and load */
+/*----------------------------------------------*/
+
+void loadlgf(int mode)
+{
+ FILE *ps;
+ char inname[150], temp[500], *pdchar;
+ char **signals;
+ short *signets;
+ objectptr *libobj;
+ genericptr *iolabel;
+ int i, sigs;
+
+ sscanf(_STR, "%149s", inname);
+
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ sprintf(inname, "%s.lgf", _STR);
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ sprintf(inname, "%s.lfo", _STR);
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ Wprintf("Can't open LGF file %s", inname);
+ return;
+ }
+ }
+ }
+
+ /* for PostScript file, remove ".lgf" or ".lfo" (to be replaced with ".ps") */
+
+ if ((pdchar = strstr(inname, ".l")) != NULL) *pdchar = '\0';
+
+ Wprintf("Loaded file: %s", inname);
+
+ /* Make sure that LGF object library has been loaded by loading it now. */
+
+ if (NameToLibrary(LGF_LIB) < 0) {
+ int ilib;
+ strcpy(_STR, LGF_LIB);
+ ilib = createlibrary(FALSE);
+ loadlibrary(ilib);
+ }
+
+ /* Read header information */
+
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: end of file.");
+ return;
+ }
+ for (pdchar = temp; *pdchar != '-' && *pdchar != '\n'; pdchar++);
+ if (*pdchar == '\n') {
+ Wprintf("Not an LGF file?");
+ return;
+ }
+ if (*(++pdchar) != '5') {
+ Wprintf("Don't know how to read version %c.", *pdchar);
+ return;
+ }
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: end of file.");
+ return;
+ }
+ for (pdchar = temp; *pdchar != 'f' && *pdchar != '\n'; pdchar++);
+ for (; *pdchar != 's' && *pdchar != '\n'; pdchar++);
+ if (*pdchar == '\n') {
+ Wprintf("Something wrong with the LGF file?");
+ return;
+ }
+
+ /* Done with header. . . okay to clear current page now unless importing */
+
+ if (mode == 0) {
+ reset(topobject, NORMAL);
+ pagereset(areawin->page);
+ }
+
+ /* Set up filename and object (page) name */
+
+ xobjs.pagelist[areawin->page]->filename = (char *) realloc (
+ xobjs.pagelist[areawin->page]->filename, (strlen(inname) + 1) * sizeof(char));
+ strcpy(xobjs.pagelist[areawin->page]->filename, inname);
+
+ /* If the filename has a path component, use only the root */
+
+ if ((pdchar = strrchr(inname, '/')) != NULL)
+ sprintf(topobject->name, "%s", pdchar + 1);
+ else
+ sprintf(topobject->name, "%s", inname);
+
+ renamepage(areawin->page);
+ printname(topobject);
+
+ /* Read objects */
+
+ for(;;) {
+ char *lineptr, keyptr, tmpstring[256];
+ int dval;
+ short pvalx, pvaly, pvalx2, pvaly2;
+
+ if (fgets(temp, 499, ps) == NULL) break; /* End-Of-File */
+
+ /* ignore whitespace */
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ if (*lineptr == '\n') continue; /* ignore blank lines */
+ switch(keyptr = *lineptr) {
+
+ case '#': /* comment */
+ break;
+
+ case 'n': /* nodes */
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in node section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+ }
+ break;
+
+ case 's': /* signal names --- save for future reference */
+
+ sscanf(++lineptr, "%d", &sigs);
+ signals = (char **) malloc(sigs * sizeof(char *));
+ signets = (short *) malloc(sigs * sizeof(short));
+ for (i = 0; i < sigs; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in signal section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ sscanf(lineptr, "%hd %249s", &signets[i], tmpstring);
+
+ signals[i] = (char *)malloc((strlen(tmpstring) + 1) * sizeof(char));
+ sprintf(signals[i], "%s", tmpstring);
+ }
+ break;
+
+ case 'l': { /* labels */
+
+ labelptr *newlabel;
+ char *tstrp;
+
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in signal section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ /* Allocate label, and put node number into X value, to be replaced */
+ /* Flag it using an inappropriate rotation value (= 500) */
+
+ sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);
+
+ /* Get rid of newline character, if any */
+
+ ridnewline(lineptr);
+
+ /* forward to the label part of the input line */
+
+ tstrp = lineptr - 1;
+ while (isdigit(*(++tstrp)));
+ while (isspace(*(++tstrp)));
+ while (isdigit(*(++tstrp)));
+ while (isspace(*(++tstrp)));
+ while (isdigit(*(++tstrp)));
+ while (isspace(*(++tstrp)));
+
+ if (tstrp != NULL) { /* could be a blank line */
+ stringpart *strptr;
+
+ NEW_LABEL(newlabel, topobject);
+
+ labeldefaults(*newlabel, False, xmat(pvalx), ymat(pvaly));
+ (*newlabel)->justify = TOP | NOTBOTTOM;
+ (*newlabel)->color = DEFAULTCOLOR;
+ (*newlabel)->string->data.font = 0;
+ strptr = makesegment(&((*newlabel)->string), NULL);
+ strptr->type = TEXT_STRING;
+ strptr->data.string = (char *)malloc(1 + strlen(tstrp));
+ strcpy(strptr->data.string, tstrp);
+ (*newlabel)->pin = NORMAL;
+ }
+ }}
+ break;
+
+ case 'w': { /* wires, implemented as single-segment polygons */
+ polyptr *newwire;
+ XPoint *tmppnts;
+
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in wire section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ /* Allocate wire */
+
+ NEW_POLY(newwire, topobject);
+
+ sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
+ (*newwire)->number = 2;
+ (*newwire)->points = (XPoint *)malloc(2 * sizeof(XPoint));
+ (*newwire)->width = 1.0;
+ (*newwire)->style = UNCLOSED;
+ (*newwire)->color = DEFAULTCOLOR;
+ (*newwire)->passed = NULL;
+ tmppnts = (*newwire)->points;
+ tmppnts->x = xmat(pvalx);
+ tmppnts->y = ymat(pvaly);
+ (++tmppnts)->x = xmat(pvalx2);
+ tmppnts->y = ymat(pvaly2);
+
+ }}
+ break;
+
+ case 'p': /* solder dot */
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in solder dot section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ /* Allocate arc */
+
+ sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);
+ drawdot(xmat(pvalx), ymat(pvaly));
+ }
+ break;
+
+ case 'b': { /* boxes */
+ polyptr *newpoly;
+ pointlist newpoints;
+
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in box section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ NEW_POLY(newpoly, topobject);
+
+ (*newpoly)->style = DASHED;
+ (*newpoly)->color = DEFAULTCOLOR;
+ (*newpoly)->width = 1.0;
+ (*newpoly)->number = 4;
+ (*newpoly)->points = (pointlist) malloc(4 * sizeof(XPoint));
+ (*newpoly)->passed = NULL;
+
+ newpoints = (*newpoly)->points;
+ sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
+ newpoints->x = xmat(pvalx);
+ newpoints->y = ymat(pvaly);
+ (newpoints + 1)->x = xmat(pvalx2);
+ (newpoints + 2)->y = ymat(pvaly2);
+
+ (newpoints + 2)->x = (newpoints + 1)->x;
+ (newpoints + 3)->x = newpoints->x;
+ (newpoints + 1)->y = newpoints->y;
+ (newpoints + 3)->y = (newpoints + 2)->y;
+ }}
+ break;
+
+ case 'g': { /* gates */
+
+ objinstptr *newinst;
+ labelptr *newlabel;
+ int j, k, hval, flip;
+
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in gates section");
+ return;
+ }
+ for (lineptr = temp; *lineptr != '\n'; lineptr++); *lineptr = '\0';
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\0'; lineptr++);
+ } while (*lineptr == '\0');
+
+ /* double loop through user libraries */
+
+ for (j = 0; j < xobjs.numlibs; j++) {
+ for (k = 0; k < xobjs.userlibs[j].number; k++) {
+ libobj = xobjs.userlibs[j].library + k;
+ if (!strcmp(lineptr, (*libobj)->name)) break;
+ }
+ if (k < xobjs.userlibs[j].number) break;
+ }
+ strcpy(tmpstring, lineptr);
+
+ /* read gate definition */
+
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file during gate read");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+
+ if (j < xobjs.numlibs || k < xobjs.userlibs[xobjs.numlibs - 1].number) {
+
+ NEW_OBJINST(newinst, topobject);
+
+ sscanf(lineptr, "%hd %hd %hd %*d %*d %*d %d", &pvalx, &pvaly,
+ &pvalx2, &hval);
+
+ flip = (pvalx2 >= 4) ? 1 : 0;
+ if (!strcmp(tmpstring, "FROM")) flip = 1 - flip;
+
+ (*newinst)->position.x = xmat(pvalx);
+ (*newinst)->position.y = ymat(pvaly);
+ (*newinst)->scale = 1.0;
+ (*newinst)->color = DEFAULTCOLOR;
+ (*newinst)->params = NULL;
+ (*newinst)->passed = NULL;
+
+ if (pvalx2 & 0x01) pvalx2 ^= 0x02;
+ if (pvalx2 >= 4) (*newinst)->rotation = -(((pvalx2 - 4) * 90) + 1);
+ else (*newinst)->rotation = (pvalx2 * 90) + 1;
+ (*newinst)->thisobject = *libobj;
+ (*newinst)->bbox.lowerleft.x = (*libobj)->bbox.lowerleft.x;
+ (*newinst)->bbox.lowerleft.y = (*libobj)->bbox.lowerleft.y;
+ (*newinst)->bbox.width = (*libobj)->bbox.width;
+ (*newinst)->bbox.height = (*libobj)->bbox.height;
+
+ /* Add label to "TO" and "FROM" */
+
+ if (!strcmp(tmpstring, "FROM") || !strcmp(tmpstring, "TO")) {
+ int nval;
+
+ hval--;
+ fgets(temp, 499, ps);
+ sscanf(temp, "%d", &nval);
+
+ for (k = 0; k < sigs; k++)
+ if (signets[k] == nval) {
+ stringpart *strptr;
+
+ NEW_LABEL(newlabel, topobject);
+ /* reconnect newinst if displaced by realloc() */
+ newinst = (objinstptr *)(topobject->plist
+ + topobject->parts - 2);
+
+ labeldefaults(*newlabel, False, (*newinst)->position.x,
+ (*newinst)->position.y);
+ (*newlabel)->color = DEFAULTCOLOR;
+ (*newlabel)->pin = LOCAL;
+ (*newlabel)->color = LOCALPINCOLOR;
+ if (!strcmp(tmpstring, "TO"))
+ (*newlabel)->position.x += ((flip) ? 48 : -48);
+ else
+ (*newlabel)->position.x += ((flip) ? 54 : -54);
+
+ (*newlabel)->justify = NOTBOTTOM;
+ if (flip) (*newlabel)->justify |= (RIGHT | NOTLEFT);
+ (*newlabel)->string->data.font = 0;
+ strptr = makesegment(&((*newlabel)->string), NULL);
+ strptr->type = TEXT_STRING;
+ strptr->data.string = (char *)malloc(1 + strlen(signals[k]));
+ strcpy(strptr->data.string, signals[k]);
+ break;
+ }
+ }
+ }
+
+ /* read through list of attributes */
+
+ else {
+ sscanf(lineptr, "%*d %*d %*d %*d %*d %*d %d", &hval);
+ Wprintf("No library object %s", tmpstring);
+ }
+
+ for (j = 0; j < hval + 1; j++) {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("Unexpected end of file");
+ return;
+ }
+ }
+ /* read to next blank line */
+ do {
+ if (fgets(temp, 499, ps) == NULL) break;
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr != '\n');
+ }}
+ break;
+
+ case 'h': { /* history */
+ int j, hval;
+
+ sscanf(++lineptr, "%d", &dval);
+ for (i = 0; i < dval; i++) {
+ do {
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("End of file in history section");
+ return;
+ }
+ for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
+ } while (*lineptr == '\n');
+
+ /* read through history */
+
+ sscanf(lineptr, "%*d %d", &hval);
+ for (j = 0; j < hval; j++)
+ if (fgets(temp, 499, ps) == NULL) {
+ Wprintf("Unexpected end of file");
+ return;
+ }
+ }}
+ break;
+
+ case '.': /* blank, don't use for EOF */
+ break;
+
+ default:
+ Wprintf("Don't understand statement '%c'", *lineptr);
+ break;
+ }
+ }
+
+ /* check for unattached labels and delete them */
+
+ for (iolabel = topobject->plist; iolabel < topobject->plist +
+ topobject->parts; iolabel++)
+ if (IS_LABEL(*iolabel)) {
+ if (TOLABEL(iolabel)->rotation == 500) {
+ genericptr *tmplabel;
+
+ free(TOLABEL(iolabel)->string);
+ free(*iolabel);
+ for (tmplabel = iolabel + 1; tmplabel < topobject->plist +
+ topobject->parts; tmplabel++) *(tmplabel - 1) = *tmplabel;
+ topobject->parts--;
+ iolabel--;
+ }
+ }
+
+ calcbbox(areawin->topinstance);
+ centerview(areawin->topinstance);
+
+ for (i = 0; i < sigs; i++) free(signals[i]);
+ free(signals);
+ free(signets);
+}
+
+#endif
+/* (LGF) */
+
+/*-------------------------*/
+#ifdef MATLAB_4X
+
+/*------------------------*/
+/* Load a Matlab .ps file */
+/*------------------------*/
+/*------------------------------------------------------------------*/
+/* This is unfinished. . . needs a lot of thought and a lot of work */
+/*------------------------------------------------------------------*/
+
+void loadmat4(caddr_t nullval)
+{
+ char inname[150], *temp, *buffer, keyword[30], percentc, *pdchar;
+ int bufsize = 256;
+ short curcolor = DEFAULTCOLOR;
+ char colorstr[100][5];
+ short matcolors = 0;
+ float curwidth = 1.0;
+ int tmpstyle = UNCLOSED;
+
+ sscanf(_STR, "%149s", inname);
+
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ sprintf(inname, "%s.ps", _STR);
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ sprintf(inname, "%s.eps", _STR);
+ ps = fopen(inname, "r");
+ if (ps == NULL) {
+ Wprintf("Can't open Matlab PostScript file %s", inname);
+ return;
+ }
+ }
+ }
+
+ /* Keep same filename---overwriting file is end-user's own risk */
+
+ if ((pdchar = strstr(_STR, ".ps")) != NULL) *pdchar = '\0';
+ sprintf(topobject->name, "%s", _STR);
+ Wprintf("Loaded file: %s", inname);
+ renamepage(areawin->page);
+ printname(topobject);
+
+ /* Create input string buffer */
+
+ buffer = (char *)malloc(bufsize * sizeof(char));
+ temp = buffer;
+
+ /* Read header information */
+
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: end of file.");
+ return;
+ }
+ if (*temp != '%' || *(temp + 1) != '!') {
+ Wprintf("Not a PostScript file?");
+ return;
+ }
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: end of file.");
+ return;
+ }
+ if (!strstr(temp, "MATLAB")) {
+ Wprintf("Not a Matlab PostScript file?");
+ return;
+ }
+
+ /* Read through to Page start */
+
+ do {
+ if (fgets(temp, 149, ps) == NULL) {
+ Wprintf("Error: no pages in input.");
+ return;
+ }
+ if (strstr(temp, "%%Page:") != NULL) break;
+ } while (1);
+
+ /* Read objects */
+
+ do {
+ char *lineptr, keyptr;
+
+ if (fgets(temp, 255, ps) == NULL) break; /* End-Of-File */
+ temp = buffer;
+
+ /* scan from the end; ignore blank lines. */
+
+ for (lineptr = buffer; (*lineptr != '\n') && (*lineptr != '\0'); lineptr++);
+
+ /* ignore any blank lines and PostScript comment lines */
+
+ if (lineptr != buffer && *buffer != '%') {
+ for (keyptr = lineptr - 1; isspace(*keyptr) && keyptr != buffer; keyptr--);
+ for (; !isspace(*keyptr) && keyptr != buffer; keyptr--);
+ sscanf(keyptr, "%29s", keyword);
+
+ if (!strcmp(keyword, "showpage")) {
+ free(buffer);
+ return False; /* end of page */
+ }
+
+ else if (!strcmp(keyword, "bdef")) { /* new color definition */
+ char *bb;
+ float red, green, blue;
+ if ((bb = strchr(buffer, '{')) != NULL) {
+ sscanf(bb + 1, "%f %f %f", &red, &green, &blue);
+ curcolor = rgb_alloccolor((int)(red * 65535), (int)(green * 65535),
+ (int)(blue * 65535));
+ addnewcolorentry(curcolor);
+ }
+ if ((bb = strchr(buffer, '/')) != NULL) {
+ sscanf(bb, "%4s", &colorstr[matcolors]);
+ matcolors++;
+ }
+ }
+
+ else if (!strcmp(keyword, "w")) { /* linewidth */
+ float tmpwidth;
+ sscanf(buffer, "%f", &tmpwidth)
+ }
+ else if (!strcmp(keyword, "DO")) { /* style */
+ tmpstyle = DOTTED | UNCLOSED;
+ }
+ else if (!strcmp(keyword, "SO")) { /* style */
+ tmpstyle = UNCLOSED;
+ }
+ else if (!strcmp(keyword, "DA")) { /* style */
+ tmpstyle = DASHED | UNCLOSED;
+ }
+ else if (!strcmp(keyword, "FMSR")) ; /* ignore font spec for now */
+ else if (!strcmp(keyword, "j")) ; /* ignore line join */
+ else if (!strcmp(keyword, "def")) ; /* ignore */
+ else if (!strcmp(keyword, "dictionary")) ; /* ignore */
+ else if (!strcmp(keyword, "np")) ; /* ignore clip paths */
+ else { /* continuation line ? */
+ for (lineptr = buffer; (*lineptr != '\n') && (*lineptr != '\0');
+ lineptr++);
+ if (*lineptr == '\n') *lineptr = ' ';
+
+ bufsize = (int)(lineptr - buffer) + 256;
+ buffer = (char *)realloc(buffer, bufsize * sizeof(char));
+ temp = buffer + (bufsize - 256);
+ }
+ }
+ } while (1);
+
+ free(buffer);
+}
+
+#endif
+/* (MATLAB_4X) */
+/*---------------------------------------------------------------------------*/
diff --git a/functions.c b/functions.c
new file mode 100644
index 0000000..f13e971
--- /dev/null
+++ b/functions.c
@@ -0,0 +1,2888 @@
+/*-------------------------------------------------------------------------*/
+/* functions.c */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/13/93 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*-------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*-------------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern Pixmap STIPPLE[8];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern int *appcolors;
+
+/*------------------------------------------------------------------------*/
+/* find the squared length of a wire (or distance between two points in */
+/* user space). */
+/*------------------------------------------------------------------------*/
+
+long sqwirelen(XPoint *userpt1, XPoint *userpt2)
+{
+ long xdist, ydist;
+
+ xdist = (long)userpt2->x - (long)userpt1->x;
+ ydist = (long)userpt2->y - (long)userpt1->y;
+ return (xdist * xdist + ydist * ydist);
+}
+
+/*------------------------------------------------------------------------*/
+/* floating-point version of the above */
+/*------------------------------------------------------------------------*/
+
+float fsqwirelen(XfPoint *userpt1, XfPoint *userpt2)
+{
+ float xdist, ydist;
+
+ xdist = userpt2->x - userpt1->x;
+ ydist = userpt2->y - userpt1->y;
+ return (xdist * xdist + ydist * ydist);
+}
+
+/*------------------------------------------------------------------------*/
+/* Find absolute distance between two points in user space */
+/*------------------------------------------------------------------------*/
+
+int wirelength(XPoint *userpt1, XPoint *userpt2)
+{
+ u_long xdist, ydist;
+
+ xdist = (long)(userpt2->x) - (long)(userpt1->x);
+ ydist = (long)(userpt2->y) - (long)(userpt1->y);
+ return (int)sqrt((double)(xdist * xdist + ydist * ydist));
+}
+
+/*------------------------------------------------------------------------*/
+/* Find the closest (squared) distance from a point to a line */
+/*------------------------------------------------------------------------*/
+
+long finddist(XPoint *linept1, XPoint *linept2, XPoint *userpt)
+{
+ long a, b, c, frac;
+ float protod;
+
+ c = sqwirelen(linept1, linept2);
+ a = sqwirelen(linept1, userpt);
+ b = sqwirelen(linept2, userpt);
+ frac = a - b;
+ if (frac >= c) return b; /* "=" is important if c = 0 ! */
+ else if (-frac >= c) return a;
+ else {
+ protod = (float)(c + a - b);
+ return (a - (long)((protod * protod) / (float)(c << 2)));
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Decompose an arc segment into one to four bezier curves according */
+/* the approximation algorithm lifted from the paper by L. Maisonobe */
+/* (spaceroots.org). This decomposition is done when an arc in a path */
+/* is read from an (older) xcircuit file, or when an arc is a selected */
+/* item when a path is created. Because arcs are decomposed when */
+/* encountered, we assume that the arc is the last element of the path. */
+/*----------------------------------------------------------------------*/
+
+void decomposearc(pathptr thepath)
+{
+ float fnc, ang1, ang2;
+ short ncurves, i;
+ arcptr thearc;
+ genericptr *pgen;
+ splineptr *newspline;
+ double nu1, nu2, lambda1, lambda2, alpha, tansq;
+ XfPoint E1, E2, Ep1, Ep2;
+ Boolean reverse = FALSE;
+
+ pgen = thepath->plist + thepath->parts - 1;
+ if (ELEMENTTYPE(*pgen) != ARC) return;
+ thearc = TOARC(pgen);
+
+ if (thearc->radius < 0) {
+ reverse = TRUE;
+ thearc->radius = -thearc->radius;
+ }
+
+ fnc = (thearc->angle2 - thearc->angle1) / 90.0;
+ ncurves = (short)fnc;
+ if (fnc - (float)((int)fnc) > 0.01) ncurves++;
+
+ thepath->parts--; /* Forget the arc */
+
+ for (i = 0; i < ncurves; i++) {
+ if (reverse) { /* arc path is reverse direction */
+ if (i == 0)
+ ang1 = thearc->angle2;
+ else
+ ang1 -= 90;
+
+ if (i == ncurves - 1)
+ ang2 = thearc->angle1;
+ else
+ ang2 = ang1 - 90;
+ }
+ else { /* arc path is forward direction */
+ if (i == 0)
+ ang1 = thearc->angle1;
+ else
+ ang1 += 90;
+
+ if (i == ncurves - 1)
+ ang2 = thearc->angle2;
+ else
+ ang2 = ang1 + 90;
+ }
+
+ lambda1 = (double)ang1 * RADFAC;
+ lambda2 = (double)ang2 * RADFAC;
+
+ nu1 = atan2(sin(lambda1) / (double)thearc->yaxis,
+ cos(lambda1) / (double)thearc->radius);
+ nu2 = atan2(sin(lambda2) / (double)thearc->yaxis,
+ cos(lambda2) / (double)thearc->radius);
+ E1.x = (float)thearc->position.x +
+ (float)thearc->radius * (float)cos(nu1);
+ E1.y = (float)thearc->position.y +
+ (float)thearc->yaxis * (float)sin(nu1);
+ E2.x = (float)thearc->position.x +
+ (float)thearc->radius * (float)cos(nu2);
+ E2.y = (float)thearc->position.y +
+ (float)thearc->yaxis * (float)sin(nu2);
+ Ep1.x = -(float)thearc->radius * (float)sin(nu1);
+ Ep1.y = (float)thearc->yaxis * (float)cos(nu1);
+ Ep2.x = -(float)thearc->radius * (float)sin(nu2);
+ Ep2.y = (float)thearc->yaxis * (float)cos(nu2);
+
+ tansq = tan((nu2 - nu1) / 2.0);
+ tansq *= tansq;
+ alpha = sin(nu2 - nu1) * 0.33333 * (sqrt(4 + (3 * tansq)) - 1);
+
+ NEW_SPLINE(newspline, thepath);
+ splinedefaults(*newspline, 0, 0);
+ (*newspline)->style = thearc->style;
+ (*newspline)->color = thearc->color;
+ (*newspline)->width = thearc->width;
+
+ (*newspline)->ctrl[0].x = E1.x;
+ (*newspline)->ctrl[0].y = E1.y;
+
+ (*newspline)->ctrl[1].x = E1.x + alpha * Ep1.x;
+ (*newspline)->ctrl[1].y = E1.y + alpha * Ep1.y;
+
+ (*newspline)->ctrl[2].x = E2.x - alpha * Ep2.x;
+ (*newspline)->ctrl[2].y = E2.y - alpha * Ep2.y;
+
+ (*newspline)->ctrl[3].x = E2.x;
+ (*newspline)->ctrl[3].y = E2.y;
+
+ calcspline(*newspline);
+ }
+
+ /* Delete the arc */
+ free_single((genericptr)thearc);
+}
+
+/*----------------------------------------------------------------------*/
+/* Calculate points for an arc */
+/*----------------------------------------------------------------------*/
+
+void calcarc(arcptr thearc)
+{
+ short idx;
+ int sarc;
+ float theta, delta;
+
+ /* assume that angle2 > angle1 always: must be guaranteed by other routines */
+
+ sarc = (int)(thearc->angle2 - thearc->angle1) * RSTEPS;
+ thearc->number = (sarc / 360) + 1;
+ if (sarc % 360 != 0) thearc->number++;
+
+ delta = RADFAC * ((float)(thearc->angle2 - thearc->angle1) / (thearc->number - 1));
+ theta = thearc->angle1 * RADFAC;
+
+ for (idx = 0; idx < thearc->number - 1; idx++) {
+ thearc->points[idx].x = (float)thearc->position.x +
+ fabs((float)thearc->radius) * cos(theta);
+ thearc->points[idx].y = (float)thearc->position.y +
+ (float)thearc->yaxis * sin(theta);
+ theta += delta;
+ }
+
+ /* place last point exactly to avoid roundoff error */
+
+ theta = thearc->angle2 * RADFAC;
+ thearc->points[thearc->number - 1].x = (float)thearc->position.x +
+ fabs((float)thearc->radius) * cos(theta);
+ thearc->points[thearc->number - 1].y = (float)thearc->position.y +
+ (float)thearc->yaxis * sin(theta);
+
+ if (thearc->radius < 0) reversefpoints(thearc->points, thearc->number);
+}
+
+/*------------------------------------------------------------------------*/
+/* Create a Bezier curve approximation from control points */
+/* (using PostScript formula for Bezier cubic curve) */
+/*------------------------------------------------------------------------*/
+
+float par[INTSEGS];
+float parsq[INTSEGS];
+float parcb[INTSEGS];
+
+void initsplines()
+{
+ float t;
+ short idx;
+
+ for (idx = 0; idx < INTSEGS; idx++) {
+ t = (float)(idx + 1) / (INTSEGS + 1);
+ par[idx] = t;
+ parsq[idx] = t * t;
+ parcb[idx] = parsq[idx] * t;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* Compute spline coefficients */
+/*------------------------------------------------------------------------*/
+
+void computecoeffs(splineptr thespline, float *ax, float *bx, float *cx,
+ float *ay, float *by, float *cy)
+{
+ *cx = 3.0 * (float)(thespline->ctrl[1].x - thespline->ctrl[0].x);
+ *bx = 3.0 * (float)(thespline->ctrl[2].x - thespline->ctrl[1].x) - *cx;
+ *ax = (float)(thespline->ctrl[3].x - thespline->ctrl[0].x) - *cx - *bx;
+
+ *cy = 3.0 * (float)(thespline->ctrl[1].y - thespline->ctrl[0].y);
+ *by = 3.0 * (float)(thespline->ctrl[2].y - thespline->ctrl[1].y) - *cy;
+ *ay = (float)(thespline->ctrl[3].y - thespline->ctrl[0].y) - *cy - *by;
+}
+
+/*------------------------------------------------------------------------*/
+
+void calcspline(splineptr thespline)
+{
+ float ax, bx, cx, ay, by, cy;
+ short idx;
+
+ computecoeffs(thespline, &ax, &bx, &cx, &ay, &by, &cy);
+ for (idx = 0; idx < INTSEGS; idx++) {
+ thespline->points[idx].x = ax * parcb[idx] + bx * parsq[idx] +
+ cx * par[idx] + (float)thespline->ctrl[0].x;
+ thespline->points[idx].y = ay * parcb[idx] + by * parsq[idx] +
+ cy * par[idx] + (float)thespline->ctrl[0].y;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* Find the (x,y) position and tangent rotation of a point on a spline */
+/*------------------------------------------------------------------------*/
+
+void findsplinepos(splineptr thespline, float t, XPoint *retpoint, int *retrot)
+{
+ float ax, bx, cx, ay, by, cy;
+ float tsq = t * t;
+ float tcb = tsq * t;
+ double dxdt, dydt;
+
+ computecoeffs(thespline, &ax, &bx, &cx, &ay, &by, &cy);
+ retpoint->x = (short)(ax * tcb + bx * tsq + cx * t + (float)thespline->ctrl[0].x);
+ retpoint->y = (short)(ay * tcb + by * tsq + cy * t + (float)thespline->ctrl[0].y);
+
+ if (retrot != NULL) {
+ dxdt = (double)(3 * ax * tsq + 2 * bx * t + cx);
+ dydt = (double)(3 * ay * tsq + 2 * by * t + cy);
+ *retrot = (int)(INVRFAC * atan2(dxdt, dydt)); /* reversed y, x */
+ if (*retrot < 0) *retrot += 360;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* floating-point version of the above */
+/*------------------------------------------------------------------------*/
+
+void ffindsplinepos(splineptr thespline, float t, XfPoint *retpoint)
+{
+ float ax, bx, cx, ay, by, cy;
+ float tsq = t * t;
+ float tcb = tsq * t;
+
+ computecoeffs(thespline, &ax, &bx, &cx, &ay, &by, &cy);
+ retpoint->x = ax * tcb + bx * tsq + cx * t + (float)thespline->ctrl[0].x;
+ retpoint->y = ay * tcb + by * tsq + cy * t + (float)thespline->ctrl[0].y;
+}
+
+/*------------------------------------------------------------------------*/
+/* Find the closest distance between a point and a spline and return the */
+/* fractional distance along the spline of this point. */
+/*------------------------------------------------------------------------*/
+
+float findsplinemin(splineptr thespline, XPoint *upoint)
+{
+ XfPoint *spt, flpt, newspt;
+ float minval = 1000000, tval, hval, ndist;
+ short j, ival;
+
+ flpt.x = (float)(upoint->x);
+ flpt.y = (float)(upoint->y);
+
+ /* get estimate from precalculated spline points */
+
+ for (spt = thespline->points; spt < thespline->points + INTSEGS;
+ spt++) {
+ ndist = fsqwirelen(spt, &flpt);
+ if (ndist < minval) {
+ minval = ndist;
+ ival = (short)(spt - thespline->points);
+ }
+ }
+ tval = (float)(ival + 1) / (INTSEGS + 1);
+ hval = 0.5 / (INTSEGS + 1);
+
+ /* short fixed iterative loop to converge on minimum t */
+
+ for (j = 0; j < 5; j++) {
+ tval += hval;
+ ffindsplinepos(thespline, tval, &newspt);
+ ndist = fsqwirelen(&newspt, &flpt);
+ if (ndist < minval) minval = ndist;
+ else {
+ tval -= hval * 2;
+ ffindsplinepos(thespline, tval, &newspt);
+ ndist = fsqwirelen(&newspt, &flpt);
+ if (ndist < minval) minval = ndist;
+ else tval += hval;
+ }
+ hval /= 2;
+ }
+
+ if (tval < 0.1) {
+ if ((float)sqwirelen(&(thespline->ctrl[0]), upoint) < minval) tval = 0;
+ }
+ else if (tval > 0.9) {
+ if ((float)sqwirelen(&(thespline->ctrl[3]), upoint) < minval) tval = 1;
+ }
+ return tval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Convert a polygon to a Bezier curve path */
+/* Curve must be selected and there must be only one selection. */
+/* */
+/* Note that this routine will draw inside the perimeter of a convex */
+/* hull. A routine that places spline endpoints on the polygon */
+/* vertices will draw outside the perimeter of a convex hull. An */
+/* optimal algorithm presumably zeros the total area between the curve */
+/* and the polygon (positive and negative), but I haven't worked out */
+/* what that solution is. The algorithm below seems good enough for */
+/* most purposes. */
+/*----------------------------------------------------------------------*/
+
+void converttocurve()
+{
+ genericptr *ggen;
+ splineptr *newspline;
+ polyptr thispoly;
+ pathptr *newpath;
+ short *newselect;
+ XPoint firstpoint, lastpoint, initpoint;
+ int i, numpoints;
+
+ if (areawin->selects != 1) return;
+
+ thispoly = TOPOLY(topobject->plist + (*areawin->selectlist));
+ if (ELEMENTTYPE(thispoly) != POLYGON) return;
+ if (thispoly->number < 3) return; /* Will not convert */
+
+ standard_element_delete(ERASE);
+ if ((thispoly->style & UNCLOSED) && (thispoly->number == 3)) {
+ NEW_SPLINE(newspline, topobject);
+ splinedefaults(*newspline, 0, 0);
+ (*newspline)->ctrl[0] = thispoly->points[0];
+ (*newspline)->ctrl[1] = thispoly->points[1];
+ (*newspline)->ctrl[2] = thispoly->points[1];
+ (*newspline)->ctrl[3] = thispoly->points[2];
+ }
+ else {
+ numpoints = thispoly->number;
+
+ /* If the polygon is closed but the first and last points */
+ /* overlap, treat the last point as if it doesn't exist. */
+
+ if (!(thispoly->style & UNCLOSED))
+ if ((thispoly->points[0].x == thispoly->points[thispoly->number - 1].x)
+ && (thispoly->points[0].y ==
+ thispoly->points[thispoly->number - 1].y))
+ numpoints--;
+
+ NEW_PATH(newpath, topobject);
+ pathdefaults(*newpath, 0, 0);
+ (*newpath)->style = thispoly->style;
+
+ if (!(thispoly->style & UNCLOSED)) {
+ lastpoint = thispoly->points[numpoints - 1];
+ initpoint.x = (lastpoint.x + thispoly->points[0].x) / 2;
+ initpoint.y = (lastpoint.y + thispoly->points[0].y) / 2;
+ firstpoint.x = (thispoly->points[0].x
+ + thispoly->points[1].x) / 2;
+ firstpoint.y = (thispoly->points[0].y
+ + thispoly->points[1].y) / 2;
+
+ NEW_SPLINE(newspline, (*newpath));
+ splinedefaults(*newspline, 0, 0);
+ (*newspline)->ctrl[0] = initpoint;
+ (*newspline)->ctrl[1] = thispoly->points[0];
+ (*newspline)->ctrl[2] = thispoly->points[0];
+ (*newspline)->ctrl[3] = firstpoint;
+ calcspline(*newspline);
+ }
+ else
+ firstpoint = thispoly->points[0];
+
+ for (i = 0; i < numpoints - ((!(thispoly->style & UNCLOSED)) ?
+ 2 : 3); i++) {
+ lastpoint.x = (thispoly->points[i + 1].x
+ + thispoly->points[i + 2].x) / 2;
+ lastpoint.y = (thispoly->points[i + 1].y
+ + thispoly->points[i + 2].y) / 2;
+
+ NEW_SPLINE(newspline, (*newpath));
+ splinedefaults(*newspline, 0, 0);
+ (*newspline)->ctrl[0] = firstpoint;
+ (*newspline)->ctrl[1] = thispoly->points[i + 1];
+ (*newspline)->ctrl[2] = thispoly->points[i + 1];
+ (*newspline)->ctrl[3] = lastpoint;
+ firstpoint = lastpoint;
+ calcspline(*newspline);
+ }
+ if (!(thispoly->style & UNCLOSED))
+ lastpoint = initpoint;
+ else
+ lastpoint = thispoly->points[i + 2];
+
+ NEW_SPLINE(newspline, (*newpath));
+ splinedefaults(*newspline, 0, 0);
+ (*newspline)->ctrl[0] = firstpoint;
+ (*newspline)->ctrl[1] = thispoly->points[i + 1];
+ (*newspline)->ctrl[2] = thispoly->points[i + 1];
+ (*newspline)->ctrl[3] = lastpoint;
+ }
+ calcspline(*newspline);
+ calcbbox(areawin->topinstance);
+ setoptionmenu();
+ drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------------*/
+/* Find closest point of a polygon to the cursor */
+/*----------------------------------------------------------------------*/
+
+short closepointdistance(polyptr curpoly, XPoint *cursloc, short *mindist)
+{
+ short curdist;
+ XPoint *curpt, *savept;
+
+ curpt = savept = curpoly->points;
+ *mindist = wirelength(curpt, cursloc);
+ while (++curpt < curpoly->points + curpoly->number) {
+ curdist = wirelength(curpt, cursloc);
+ if (curdist < *mindist) {
+ *mindist = curdist;
+ savept = curpt;
+ }
+ }
+ return (short)(savept - curpoly->points);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Find closest point of a polygon to the cursor */
+/*----------------------------------------------------------------------------*/
+
+short closepoint(polyptr curpoly, XPoint *cursloc)
+{
+ short mindist;
+ return closepointdistance(curpoly, cursloc, &mindist);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Find the distance to the closest point of a polygon to the cursor */
+/*----------------------------------------------------------------------------*/
+
+short closedistance(polyptr curpoly, XPoint *cursloc)
+{
+ short mindist;
+ closepointdistance(curpoly, cursloc, &mindist);
+ return mindist;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Coordinate system transformations */
+/*----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------*/
+/* Check screen bounds: minimum, maximum scale and translation is determined */
+/* by values which fit in an X11 type XPoint (short int). If the window */
+/* extremes exceed type short when mapped to user space, or if the page */
+/* bounds exceed type short when mapped to X11 window space, return error. */
+/*------------------------------------------------------------------------------*/
+
+short checkbounds()
+{
+ long lval;
+
+ /* check window-to-user space */
+
+ lval = 2 * (long)((float) (areawin->width) / areawin->vscale) +
+ (long)areawin->pcorner.x;
+ if (lval != (long)((short)lval)) return -1;
+ lval = 2 * (long)((float) (areawin->height) / areawin->vscale) +
+ (long)areawin->pcorner.y;
+ if (lval != (long)((short)lval)) return -1;
+
+ /* check user-to-window space */
+
+ lval = (long)((float)(topobject->bbox.lowerleft.x - areawin->pcorner.x) *
+ areawin->vscale);
+ if (lval != (long)((short)lval)) return -1;
+ lval = (long)areawin->height - (long)((float)(topobject->bbox.lowerleft.y -
+ areawin->pcorner.y) * areawin->vscale);
+ if (lval != (long)((short)lval)) return -1;
+
+ lval = (long)((float)(topobject->bbox.lowerleft.x + topobject->bbox.width -
+ areawin->pcorner.x) * areawin->vscale);
+ if (lval != (long)((short)lval)) return -1;
+ lval = (long)areawin->height - (long)((float)(topobject->bbox.lowerleft.y +
+ topobject->bbox.height - areawin->pcorner.y) * areawin->vscale);
+ if (lval != (long)((short)lval)) return -1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+/* Transform X-window coordinate to xcircuit coordinate system */
+/*------------------------------------------------------------------------*/
+
+void window_to_user(short xw, short yw, XPoint *upt)
+{
+ float tmpx, tmpy;
+
+ tmpx = (float)xw / areawin->vscale + (float)areawin->pcorner.x;
+ tmpy = (float)(areawin->height - yw) / areawin->vscale +
+ (float)areawin->pcorner.y;
+
+ tmpx += (tmpx > 0) ? 0.5 : -0.5;
+ tmpy += (tmpy > 0) ? 0.5 : -0.5;
+
+ upt->x = (short)tmpx;
+ upt->y = (short)tmpy;
+}
+
+/*------------------------------------------------------------------------*/
+/* Transform xcircuit coordinate back to X-window coordinate system */
+/*------------------------------------------------------------------------*/
+
+void user_to_window(XPoint upt, XPoint *wpt)
+{
+ float tmpx, tmpy;
+
+ tmpx = (float)(upt.x - areawin->pcorner.x) * areawin->vscale;
+ tmpy = (float)areawin->height - (float)(upt.y - areawin->pcorner.y)
+ * areawin->vscale;
+
+ tmpx += (tmpx > 0) ? 0.5 : -0.5;
+ tmpy += (tmpy > 0) ? 0.5 : -0.5;
+
+ wpt->x = (short)tmpx;
+ wpt->y = (short)tmpy;
+}
+
+/*----------------------------------------------------------------------*/
+/* Transformations in the object hierarchy */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Return rotation relative to a specific CTM */
+/*----------------------------------------------------------------------*/
+
+int UGetCTMRotation(Matrix *ctm)
+{
+ float rads = (float)atan2((double)(ctm->d), (double)(ctm->a));
+ return (int)(rads / RADFAC);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return rotation relative to the top level */
+/* Note that UTopRotation() is also the rotation relative to the window */
+/* since the top-level drawing page is always upright relative to the */
+/* window. Thus, there is no routine UTopDrawingRotation(). */
+/*----------------------------------------------------------------------*/
+
+int UTopRotation()
+{
+ return UGetCTMRotation(DCTM);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return scale relative to a specific CTM */
+/*----------------------------------------------------------------------*/
+
+float UGetCTMScale(Matrix *ctm)
+{
+ return (float)(sqrt((double)(ctm->a * ctm->a + ctm->d * ctm->d)));
+}
+
+/*----------------------------------------------------------------------*/
+/* Return scale relative to window */
+/*----------------------------------------------------------------------*/
+
+float UTopScale()
+{
+ return UGetCTMScale(DCTM);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return scale multiplied by length */
+/*----------------------------------------------------------------------*/
+
+float UTopTransScale(float length)
+{
+ return (float)(length * UTopScale());
+}
+
+/*----------------------------------------------------------------------*/
+/* Return scale relative to the top-level schematic (not the window) */
+/*----------------------------------------------------------------------*/
+
+float UTopDrawingScale()
+{
+ Matrix lctm, wctm;
+ UCopyCTM(DCTM, &lctm);
+ UResetCTM(&wctm);
+ UMakeWCTM(&wctm);
+ InvertCTM(&wctm);
+ UPreMultCTMbyMat(&wctm, &lctm);
+ return UGetCTMScale(&wctm);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return position offset relative to a specific CTM */
+/*----------------------------------------------------------------------*/
+
+void UGetCTMOffset(Matrix *ctm, int *offx, int *offy)
+{
+ if (offx) *offx = (int)ctm->c;
+ if (offy) *offy = (int)ctm->f;
+}
+
+/*----------------------------------------------------------------------*/
+/* Return position offset relative to top-level */
+/*----------------------------------------------------------------------*/
+
+void UTopOffset(int *offx, int *offy)
+{
+ UGetCTMOffset(DCTM, offx, offy);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return postion relative to the top-level schematic (not the window) */
+/*----------------------------------------------------------------------*/
+
+void UTopDrawingOffset(int *offx, int *offy)
+{
+ Matrix lctm, wctm;
+ UCopyCTM(DCTM, &lctm);
+ UResetCTM(&wctm);
+ UMakeWCTM(&wctm);
+ InvertCTM(&wctm);
+ UPreMultCTMbyMat(&wctm, &lctm);
+ UGetCTMOffset(&wctm, offx, offy);
+}
+
+/*----------------------------------------------------------------------*/
+/* Get the cursor position */
+/*----------------------------------------------------------------------*/
+
+XPoint UGetCursor()
+{
+ Window nullwin;
+ int nullint, xpos, ypos;
+ u_int nullui;
+ XPoint newpos;
+
+#ifdef TCL_WRAPPER
+ /* Don't use areawin->window; if called from inside an object */
+ /* (e.g., "here" in a Tcl expression), areawin->window will be */
+ /* an off-screen pixmap, and cause a crash. */
+#ifndef _MSC_VER
+ XQueryPointer(dpy, Tk_WindowId(areawin->area), &nullwin, &nullwin,
+ &nullint, &nullint, &xpos, &ypos, &nullui);
+#else
+ XQueryPointer_TkW32(dpy, Tk_WindowId(areawin->area), &nullwin, &nullwin,
+ &nullint, &nullint, &xpos, &ypos, &nullui);
+#endif
+#else
+ XQueryPointer(dpy, areawin->window, &nullwin, &nullwin, &nullint,
+ &nullint, &xpos, &ypos, &nullui);
+#endif
+
+ newpos.x = xpos;
+ newpos.y = ypos;
+
+ return newpos;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get the cursor position and translate to user coordinates */
+/*----------------------------------------------------------------------*/
+
+XPoint UGetCursorPos()
+{
+ XPoint winpos, userpos;
+
+ winpos = UGetCursor();
+
+ window_to_user(winpos.x, winpos.y, &userpos);
+
+ return userpos;
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate a point to the nearest snap-to grid point */
+/*----------------------------------------------------------------------*/
+/* user coordinates to user coordinates version */
+
+void u2u_snap(XPoint *uvalue)
+{
+ float tmpx, tmpy;
+ float tmpix, tmpiy;
+
+ if (areawin->snapto) {
+ tmpx = (float)uvalue->x / xobjs.pagelist[areawin->page]->snapspace;
+ if (tmpx > 0)
+ tmpix = (float)((int)(tmpx + 0.5));
+ else
+ tmpix = (float)((int)(tmpx - 0.5));
+
+ tmpy = (float)uvalue->y / xobjs.pagelist[areawin->page]->snapspace;
+ if (tmpy > 0)
+ tmpiy = (float)((int)(tmpy + 0.5));
+ else
+ tmpiy = (float)((int)(tmpy - 0.5));
+
+ tmpix *= xobjs.pagelist[areawin->page]->snapspace;
+ tmpix += (tmpix > 0) ? 0.5 : -0.5;
+ tmpiy *= xobjs.pagelist[areawin->page]->snapspace;
+ tmpiy += (tmpiy > 0) ? 0.5 : -0.5;
+
+ uvalue->x = (int)tmpix;
+ uvalue->y = (int)tmpiy;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* window coordinates to user coordinates version */
+/*------------------------------------------------------------------------*/
+
+void snap(short valuex, short valuey, XPoint *returnpt)
+{
+ window_to_user(valuex, valuey, returnpt);
+ u2u_snap(returnpt);
+}
+
+/*------------------------------------------------------------------------*/
+/* Transform object coordinates through scale, translation, and rotation */
+/* This routine attempts to match the PostScript definition of trans- */
+/* formation matrices. */
+/*------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*/
+/* Current transformation matrix manipulation routines */
+/*------------------------------------------------------------------------*/
+
+void UResetCTM(Matrix *ctm)
+{
+ ctm->a = ctm->e = 1;
+ ctm->b = ctm->d = 0;
+ ctm->c = ctm->f = 0; /* 0.5 for nearest-int real->int conversion? */
+}
+
+/*------------------------------------------------------------------------*/
+
+void InvertCTM(Matrix *ctm)
+{
+ float det = ctm->a * ctm->e - ctm->b * ctm->d;
+ float tx = ctm->b * ctm->f - ctm->c * ctm->e;
+ float ty = ctm->d * ctm->c - ctm->a * ctm->f;
+
+ float tmpa = ctm->a;
+
+ ctm->b = -ctm->b / det;
+ ctm->d = -ctm->d / det;
+
+ ctm->a = ctm->e / det;
+ ctm->e = tmpa / det;
+ ctm->c = tx / det;
+ ctm->f = ty / det;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UCopyCTM(fctm, tctm)
+ Matrix *fctm, *tctm;
+{
+ tctm->a = fctm->a;
+ tctm->b = fctm->b;
+ tctm->c = fctm->c;
+ tctm->d = fctm->d;
+ tctm->e = fctm->e;
+ tctm->f = fctm->f;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Multiply CTM by current screen position and scale to get transformation */
+/* matrix from a user point to the X11 window */
+/*-------------------------------------------------------------------------*/
+
+void UMakeWCTM(Matrix *ctm)
+{
+ ctm->a *= areawin->vscale;
+ ctm->b *= areawin->vscale;
+ ctm->c = (ctm->c - (float)areawin->pcorner.x) * areawin->vscale;
+
+ ctm->d *= -areawin->vscale;
+ ctm->e *= -areawin->vscale;
+ ctm->f = (float)areawin->height + ((float)areawin->pcorner.y - ctm->f) *
+ areawin->vscale;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UMultCTM(Matrix *ctm, XPoint position, float scale, short rotate)
+{
+ float tmpa, tmpb, tmpd, tmpe, yscale;
+ float mata, matb, matc;
+ double drot = (double)rotate * RADFAC;
+
+ yscale = abs(scale); /* -scale implies flip in x direction only */
+
+ tmpa = scale * cos(drot);
+ tmpb = yscale * sin(drot);
+ tmpd = -scale * sin(drot);
+ tmpe = yscale * cos(drot);
+
+ mata = ctm->a * tmpa + ctm->d * tmpb;
+ matb = ctm->b * tmpa + ctm->e * tmpb;
+ matc = ctm->c * tmpa + ctm->f * tmpb + position.x;
+
+ ctm->d = ctm->d * tmpe + ctm->a * tmpd;
+ ctm->e = ctm->e * tmpe + ctm->b * tmpd;
+ ctm->f = ctm->f * tmpe + ctm->c * tmpd + position.y;
+
+ ctm->a = mata;
+ ctm->b = matb;
+ ctm->c = matc;
+}
+
+/*----------------------------------------------------------------------*/
+/* Slanting function x' = x + beta * y, y' = y */
+/*----------------------------------------------------------------------*/
+
+void USlantCTM(Matrix *ctm, float beta)
+{
+ ctm->b += ctm->a * beta;
+ ctm->e += ctm->d * beta;
+}
+
+#define EPS 1e-9
+/*----------------------------------------------------------------------*/
+/* Transform text to make it right-side up within 90 degrees of page */
+/* NOTE: This is not yet resolved, as xcircuit does not agree with */
+/* PostScript in a few cases! */
+/*----------------------------------------------------------------------*/
+
+void UPreScaleCTM(Matrix *ctm)
+{
+ /* negative X scale (-1, +1) */
+ if ((ctm->a < -EPS) || ((ctm->a < EPS) && (ctm->a > -EPS) &&
+ ((ctm->d * ctm->b) < 0))) {
+ ctm->a = -ctm->a;
+ ctm->d = -ctm->d;
+ }
+
+ /* negative Y scale (+1, -1) */
+ if (ctm->e > EPS) {
+ ctm->e = -ctm->e;
+ ctm->b = -ctm->b;
+ }
+
+ /* At 90, 270 degrees need special attention to avoid discrepencies */
+ /* with the PostScript output due to roundoff error. This code */
+ /* matches what PostScript produces. */
+
+}
+
+/*----------------------------------------------------------------------*/
+/* Adjust justification and CTM as necessary for flip invariance */
+/*----------------------------------------------------------------------*/
+
+short flipadjust(short justify)
+{
+ short tmpjust = justify & (~FLIPINV);
+
+ if (justify & FLIPINV) {
+ if (((DCTM)->a < -EPS) || (((DCTM)->a < EPS) && ((DCTM)->a > -EPS) &&
+ (((DCTM)->d * (DCTM)->b) < 0))) {
+ if ((tmpjust & (RIGHT | NOTLEFT)) != NOTLEFT)
+ tmpjust ^= (RIGHT | NOTLEFT);
+ }
+ if ((DCTM)->e > EPS) {
+ if ((tmpjust & (TOP | NOTBOTTOM)) != NOTBOTTOM)
+ tmpjust ^= (TOP | NOTBOTTOM);
+ }
+ UPreScaleCTM(DCTM);
+ }
+ return tmpjust;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UPreMultCTM(Matrix *ctm, XPoint position, float scale, short rotate)
+{
+ float tmpa, tmpb, tmpd, tmpe, yscale;
+ float mata, matd;
+ double drot = (double)rotate * RADFAC;
+
+ yscale = abs(scale); /* negative scale value implies flip in x only */
+
+ tmpa = scale * cos(drot);
+ tmpb = yscale * sin(drot);
+ tmpd = -scale * sin(drot);
+ tmpe = yscale * cos(drot);
+
+ ctm->c += ctm->a * position.x + ctm->b * position.y;
+ ctm->f += ctm->d * position.x + ctm->e * position.y;
+
+ mata = ctm->a * tmpa + ctm->b * tmpd;
+ ctm->b = ctm->a * tmpb + ctm->b * tmpe;
+
+ matd = ctm->d * tmpa + ctm->e * tmpd;
+ ctm->e = ctm->d * tmpb + ctm->e * tmpe;
+
+ ctm->a = mata;
+ ctm->d = matd;
+}
+
+/*----------------------------------------------------------------------*/
+/* Direct Matrix-Matrix multiplication */
+/*----------------------------------------------------------------------*/
+
+void UPreMultCTMbyMat(Matrix *ctm, Matrix *pre)
+{
+ float mata, matd;
+
+ mata = pre->a * ctm->a + pre->d * ctm->b;
+ ctm->c += pre->c * ctm->a + pre->f * ctm->b;
+ ctm->b = pre->b * ctm->a + pre->e * ctm->b;
+ ctm->a = mata;
+
+ matd = pre->a * ctm->d + pre->d * ctm->e;
+ ctm->f += pre->c * ctm->d + pre->f * ctm->e;
+ ctm->e = pre->b * ctm->d + pre->e * ctm->e;
+ ctm->d = matd;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UTransformbyCTM(Matrix *ctm, XPoint *ipoints, XPoint *points, short number)
+{
+ pointlist current, ptptr = points;
+ float fx, fy;
+ /* short tmpx; (jdk) */
+
+ for (current = ipoints; current < ipoints + number; current++, ptptr++) {
+ fx = ctm->a * (float)current->x + ctm->b * (float)current->y + ctm->c;
+ fy = ctm->d * (float)current->x + ctm->e * (float)current->y + ctm->f;
+
+ ptptr->x = (fx >= 0) ? (short)(fx + 0.5) : (short)(fx - 0.5);
+ ptptr->y = (fy >= 0) ? (short)(fy + 0.5) : (short)(fy - 0.5);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* (same as above routine but using type (float) for point values; this */
+/* is for calculation of Bezier curve internal points. */
+/*------------------------------------------------------------------------*/
+
+void UfTransformbyCTM(Matrix *ctm, XfPoint *fpoints, XPoint *points, short number)
+{
+ fpointlist current;
+ pointlist new = points;
+ float fx, fy;
+
+ for (current = fpoints; current < fpoints + number; current++, new++) {
+ fx = ctm->a * current->x + ctm->b * current->y + ctm->c;
+ fy = ctm->d * current->x + ctm->e * current->y + ctm->f;
+ new->x = (fx >= 0) ? (short)(fx + 0.5) : (short)(fx - 0.5);
+ new->y = (fy >= 0) ? (short)(fy + 0.5) : (short)(fy - 0.5);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void UPopCTM()
+{
+ Matrixptr lastmatrix;
+
+ if (areawin->MatStack == NULL) {
+ Wprintf("Matrix stack pop error");
+ return;
+ }
+ lastmatrix = areawin->MatStack->nextmatrix;
+ free(areawin->MatStack);
+ areawin->MatStack = lastmatrix;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UPushCTM()
+{
+ Matrixptr nmatrix;
+
+ nmatrix = (Matrixptr)malloc(sizeof(Matrix));
+ if (areawin->MatStack == NULL)
+ UResetCTM(nmatrix);
+ else
+ UCopyCTM(areawin->MatStack, nmatrix);
+ nmatrix->nextmatrix = areawin->MatStack;
+ areawin->MatStack = nmatrix;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UTransformPoints(XPoint *points, XPoint *newpoints, short number,
+ XPoint atpt, float scale, short rotate)
+{
+ Matrix LCTM;
+
+ UResetCTM(&LCTM);
+ UMultCTM(&LCTM, atpt, scale, rotate);
+ UTransformbyCTM(&LCTM, points, newpoints, number);
+}
+
+/*----------------------------------------------------*/
+/* Transform points inward to next hierarchical level */
+/*----------------------------------------------------*/
+
+void InvTransformPoints(XPoint *points, XPoint *newpoints, short number,
+ XPoint atpt, float scale, short rotate)
+{
+ Matrix LCTM;
+
+ UResetCTM(&LCTM);
+ UPreMultCTM(&LCTM, atpt, scale, rotate);
+ InvertCTM(&LCTM);
+ UTransformbyCTM(&LCTM, points, newpoints, number);
+}
+
+/*----------------------------------------------------------------------*/
+/* Adjust wire coords to force a wire to a horizontal or vertical */
+/* position. */
+/* "pospt" is the target position for the point of interest. */
+/* "cycle" is the point number in the polygon of the point of interest. */
+/* cycle == -1 is equivalent to the last point of the polygon. */
+/* If "strict" is TRUE then single-segment wires are forced manhattan */
+/* even if that means that the endpoint drifts from the target point. */
+/* If "strict" is FALSE then single-segment wires will become non- */
+/* manhattan so that the target point is reached. */
+/* NOTE: It might be preferable to add a segment to maintain a */
+/* manhattan layout, except that we want to avoid merging nets */
+/* together. . . */
+/*----------------------------------------------------------------------*/
+
+void manhattanize(XPoint *pospt, polyptr newpoly, short cycle, Boolean strict)
+{
+ XPoint *curpt, *bpt, *bbpt, *fpt, *ffpt;
+ int deltax, deltay;
+
+ if (newpoly->number == 1) return; /* sanity check */
+
+ if (cycle == -1 || cycle == newpoly->number - 1) {
+ curpt = newpoly->points + newpoly->number - 1;
+ bpt = newpoly->points + newpoly->number - 2;
+ fpt = NULL;
+ ffpt = NULL;
+ if (newpoly->number > 2)
+ bbpt = newpoly->points + newpoly->number - 3;
+ else
+ bbpt = NULL;
+ }
+ else if (cycle == 0) {
+ curpt = newpoly->points;
+ fpt = newpoly->points + 1;
+ bpt = NULL;
+ bbpt = NULL;
+ if (newpoly->number > 2)
+ ffpt = newpoly->points + 2;
+ else
+ ffpt = NULL;
+ }
+ else {
+ curpt = newpoly->points + cycle;
+ fpt = newpoly->points + cycle + 1;
+ bpt = newpoly->points + cycle - 1;
+ if (cycle > 1)
+ bbpt = newpoly->points + cycle - 2;
+ else
+ bbpt = NULL;
+
+ if (cycle < newpoly->number - 2)
+ ffpt = newpoly->points + cycle + 2;
+ else
+ ffpt = NULL;
+ }
+
+ /* enforce constraints on point behind cycle position */
+
+ if (bpt != NULL) {
+ if (bbpt != NULL) {
+ if (bpt->x == bbpt->x) bpt->y = pospt->y;
+ if (bpt->y == bbpt->y) bpt->x = pospt->x;
+ }
+ else if (strict) {
+ deltax = abs(bpt->x - pospt->x);
+ deltay = abs(bpt->y - pospt->y);
+
+ /* Only one segment---just make sure it's horizontal or vertical */
+ if (deltay > deltax) pospt->x = bpt->x;
+ else pospt->y = bpt->y;
+ }
+ }
+
+ /* enforce constraints on point forward of cycle position */
+
+ if (fpt != NULL) {
+ if (ffpt != NULL) {
+ if (fpt->x == ffpt->x) fpt->y = pospt->y;
+ if (fpt->y == ffpt->y) fpt->x = pospt->x;
+ }
+ else if (strict) {
+ deltax = abs(fpt->x - pospt->x);
+ deltay = abs(fpt->y - pospt->y);
+
+ /* Only one segment---just make sure it's horizontal or vertical */
+ if (deltay > deltax) pospt->x = fpt->x;
+ else pospt->y = fpt->y;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Bounding box calculation routines */
+/*----------------------------------------------------------------------*/
+
+void bboxcalc(short testval, short *lowerval, short *upperval)
+{
+ if (testval < *lowerval) *lowerval = testval;
+ if (testval > *upperval) *upperval = testval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Bounding box calculation for elements which can be part of a path */
+/*----------------------------------------------------------------------*/
+
+void calcextents(genericptr *bboxgen, short *llx, short *lly,
+ short *urx, short *ury)
+{
+ switch (ELEMENTTYPE(*bboxgen)) {
+ case(POLYGON): {
+ pointlist bboxpts;
+ for (bboxpts = TOPOLY(bboxgen)->points; bboxpts < TOPOLY(bboxgen)->points
+ + TOPOLY(bboxgen)->number; bboxpts++) {
+ bboxcalc(bboxpts->x, llx, urx);
+ bboxcalc(bboxpts->y, lly, ury);
+ }
+ } break;
+
+ case(SPLINE): {
+ fpointlist bboxpts;
+ bboxcalc(TOSPLINE(bboxgen)->ctrl[0].x, llx, urx);
+ bboxcalc(TOSPLINE(bboxgen)->ctrl[0].y, lly, ury);
+ bboxcalc(TOSPLINE(bboxgen)->ctrl[3].x, llx, urx);
+ bboxcalc(TOSPLINE(bboxgen)->ctrl[3].y, lly, ury);
+ for (bboxpts = TOSPLINE(bboxgen)->points; bboxpts <
+ TOSPLINE(bboxgen)->points + INTSEGS; bboxpts++) {
+ bboxcalc((short)(bboxpts->x), llx, urx);
+ bboxcalc((short)(bboxpts->y), lly, ury);
+ }
+ } break;
+
+ case (ARC): {
+ fpointlist bboxpts;
+ for (bboxpts = TOARC(bboxgen)->points; bboxpts < TOARC(bboxgen)->points +
+ TOARC(bboxgen)->number; bboxpts++) {
+ bboxcalc((short)(bboxpts->x), llx, urx);
+ bboxcalc((short)(bboxpts->y), lly, ury);
+ }
+ } break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Calculate the bounding box of an object instance */
+/*----------------------------------------------------------------------*/
+
+void objinstbbox(objinstptr obbox, XPoint *npoints, int extend)
+{
+ XPoint points[4];
+
+ points[0].x = points[1].x = obbox->bbox.lowerleft.x - extend;
+ points[1].y = points[2].y = obbox->bbox.lowerleft.y + obbox->bbox.height
+ + extend;
+ points[2].x = points[3].x = obbox->bbox.lowerleft.x + obbox->bbox.width
+ + extend;
+ points[0].y = points[3].y = obbox->bbox.lowerleft.y - extend;
+
+ UTransformPoints(points, npoints, 4, obbox->position,
+ obbox->scale, obbox->rotation);
+}
+
+/*----------------------------------------------------------------------*/
+/* Calculate the bounding box of a label */
+/*----------------------------------------------------------------------*/
+
+void labelbbox(labelptr labox, XPoint *npoints, objinstptr callinst)
+{
+ XPoint points[4];
+ TextExtents tmpext;
+ short j;
+
+ tmpext = ULength(labox, callinst, 0, NULL);
+ points[0].x = points[1].x = (labox->justify & NOTLEFT ?
+ (labox->justify & RIGHT ? -tmpext.maxwidth :
+ -tmpext.maxwidth / 2) : 0);
+ points[2].x = points[3].x = points[0].x + tmpext.maxwidth;
+ points[0].y = points[3].y = (labox->justify & NOTBOTTOM ?
+ (labox->justify & TOP ? -tmpext.ascent :
+ -(tmpext.ascent + tmpext.base) / 2) : -tmpext.base)
+ + tmpext.descent;
+ points[1].y = points[2].y = points[0].y + tmpext.ascent - tmpext.descent;
+
+ /* separate bounding box for pinlabels and infolabels */
+
+ if (labox->pin)
+ for (j = 0; j < 4; j++)
+ pinadjust(labox->justify, &points[j].x, &points[j].y, 1);
+
+ UTransformPoints(points, npoints, 4, labox->position,
+ labox->scale, labox->rotation);
+}
+
+/*----------------------------------------------------------------------*/
+/* Calculate the bounding box of a graphic image */
+/*----------------------------------------------------------------------*/
+
+void graphicbbox(graphicptr gp, XPoint *npoints)
+{
+ XPoint points[4];
+ int hw = gp->source->width >> 1;
+ int hh = gp->source->height >> 1;
+
+ points[1].x = points[2].x = hw;
+ points[0].x = points[3].x = -hw;
+
+ points[0].y = points[1].y = -hh;
+ points[2].y = points[3].y = hh;
+
+ UTransformPoints(points, npoints, 4, gp->position,
+ gp->scale, gp->rotation);
+}
+
+/*--------------------------------------------------------------*/
+/* Wrapper for single call to calcbboxsingle() in the netlister */
+/*--------------------------------------------------------------*/
+
+void calcinstbbox(genericptr *bboxgen, short *llx, short *lly, short *urx,
+ short *ury)
+{
+ *llx = *lly = 32767;
+ *urx = *ury = -32768;
+
+ calcbboxsingle(bboxgen, areawin->topinstance, llx, lly, urx, ury);
+}
+
+/*----------------------------------------------------------------------*/
+/* Bounding box calculation for a single generic element */
+/*----------------------------------------------------------------------*/
+
+void calcbboxsingle(genericptr *bboxgen, objinstptr thisinst,
+ short *llx, short *lly, short *urx, short *ury)
+{
+ XPoint npoints[4];
+ short j;
+
+ /* For each screen element, compute the extents and revise bounding */
+ /* box points, if necessary. */
+
+ switch(ELEMENTTYPE(*bboxgen)) {
+
+ case(OBJINST):
+ objinstbbox(TOOBJINST(bboxgen), npoints, 0);
+
+ for (j = 0; j < 4; j++) {
+ bboxcalc(npoints[j].x, llx, urx);
+ bboxcalc(npoints[j].y, lly, ury);
+ }
+ break;
+
+ case(LABEL):
+ /* because a pin is offset from its position point, include */
+ /* that point in the bounding box. */
+
+ if (TOLABEL(bboxgen)->pin) {
+ bboxcalc(TOLABEL(bboxgen)->position.x, llx, urx);
+ bboxcalc(TOLABEL(bboxgen)->position.y, lly, ury);
+ }
+ labelbbox(TOLABEL(bboxgen), npoints, thisinst);
+
+ for (j = 0; j < 4; j++) {
+ bboxcalc(npoints[j].x, llx, urx);
+ bboxcalc(npoints[j].y, lly, ury);
+ }
+ break;
+
+ case(GRAPHIC):
+ graphicbbox(TOGRAPHIC(bboxgen), npoints);
+ for (j = 0; j < 4; j++) {
+ bboxcalc(npoints[j].x, llx, urx);
+ bboxcalc(npoints[j].y, lly, ury);
+ }
+ break;
+
+ case(PATH): {
+ genericptr *pathc;
+ for (pathc = TOPATH(bboxgen)->plist; pathc < TOPATH(bboxgen)->plist
+ + TOPATH(bboxgen)->parts; pathc++)
+ calcextents(pathc, llx, lly, urx, ury);
+ } break;
+
+ default:
+ calcextents(bboxgen, llx, lly, urx, ury);
+ }
+}
+
+/*------------------------------------------------------*/
+/* Find if an object is in the specified library */
+/*------------------------------------------------------*/
+
+Boolean object_in_library(short libnum, objectptr thisobject)
+{
+ short i;
+
+ for (i = 0; i < xobjs.userlibs[libnum].number; i++) {
+ if (*(xobjs.userlibs[libnum].library + i) == thisobject)
+ return True;
+ }
+ return False;
+}
+
+/*-----------------------------------------------------------*/
+/* Find if an object is in the hierarchy of the given object */
+/* Returns the number (position in plist) or -1 if not found */
+/*-----------------------------------------------------------*/
+
+short find_object(objectptr pageobj, objectptr thisobject)
+{
+ short i, j;
+ genericptr *pelem;
+
+ for (i = 0; i < pageobj->parts; i++) {
+ pelem = pageobj->plist + i;
+ if (IS_OBJINST(*pelem)) {
+ if ((TOOBJINST(pelem))->thisobject == thisobject)
+ return i;
+ else if ((j = find_object((TOOBJINST(pelem))->thisobject, thisobject)) >= 0)
+ return i; /* was j---is this the right fix? */
+ }
+ }
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* Find all pages and libraries containing this object */
+/* and update accordingly. If this object is a page, */
+/* just update the page directory. */
+/*------------------------------------------------------*/
+
+void updatepagebounds(objectptr thisobject)
+{
+ short i, j;
+ objectptr pageobj;
+
+ if ((i = is_page(thisobject)) >= 0) {
+ if (xobjs.pagelist[i]->background.name != (char *)NULL)
+ backgroundbbox(i);
+ updatepagelib(PAGELIB, i);
+ }
+ else {
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst != NULL) {
+ pageobj = xobjs.pagelist[i]->pageinst->thisobject;
+ if ((j = find_object(pageobj, thisobject)) >= 0) {
+ calcbboxvalues(xobjs.pagelist[i]->pageinst,
+ (genericptr *)(pageobj->plist + j));
+ updatepagelib(PAGELIB, i);
+ }
+ }
+ }
+ for (i = 0; i < xobjs.numlibs; i++)
+ if (object_in_library(i, thisobject))
+ composelib(i + LIBRARY);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Free memory for the schematic bounding box */
+/*--------------------------------------------------------------*/
+
+void invalidateschembbox(objinstptr thisinst)
+{
+ if (thisinst->schembbox != NULL) {
+ free(thisinst->schembbox);
+ thisinst->schembbox = NULL;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Calculate the bounding box for an object instance. Use the */
+/* existing bbox and finish calculation on all the elements */
+/* which have parameters not taking default values. */
+/* This finishes the calculation partially done by */
+/* calcbboxvalues(). */
+/*--------------------------------------------------------------*/
+
+void calcbboxinst(objinstptr thisinst)
+{
+ objectptr thisobj;
+ genericptr *gelem;
+ short llx, lly, urx, ury;
+
+ short pllx, plly, purx, pury;
+ Boolean hasschembbox = FALSE;
+ Boolean didparamsubs = FALSE;
+
+ if (thisinst == NULL) return;
+
+ thisobj = thisinst->thisobject;
+
+ llx = thisobj->bbox.lowerleft.x;
+ lly = thisobj->bbox.lowerleft.y;
+ urx = llx + thisobj->bbox.width;
+ ury = lly + thisobj->bbox.height;
+
+ pllx = plly = 32767;
+ purx = pury = -32768;
+
+ for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts;
+ gelem++) {
+ /* pins which do not appear outside of the object */
+ /* contribute to the objects "schembbox". */
+
+ if (IS_LABEL(*gelem)) {
+ labelptr btext = TOLABEL(gelem);
+ if (btext->pin && !(btext->justify & PINVISIBLE)) {
+ hasschembbox = TRUE;
+ calcbboxsingle(gelem, thisinst, &pllx, &plly, &purx, &pury);
+ continue;
+ }
+ }
+
+ if (has_param(*gelem)) {
+ if (didparamsubs == FALSE) {
+ psubstitute(thisinst);
+ didparamsubs = TRUE;
+ }
+ calcbboxsingle(gelem, thisinst, &llx, &lly, &urx, &ury);
+ }
+
+ /* If we have a clipmask, the clipmask is used to calculate the */
+ /* bounding box, not the element it is masking. */
+
+ switch(ELEMENTTYPE(*gelem)) {
+ case POLYGON: case SPLINE: case ARC: case PATH:
+ if (TOPOLY(gelem)->style & CLIPMASK) gelem++;
+ break;
+ }
+ }
+
+ thisinst->bbox.lowerleft.x = llx;
+ thisinst->bbox.lowerleft.y = lly;
+ thisinst->bbox.width = urx - llx;
+ thisinst->bbox.height = ury - lly;
+
+ if (hasschembbox) {
+ if (thisinst->schembbox == NULL)
+ thisinst->schembbox = (BBox *)malloc(sizeof(BBox));
+
+ thisinst->schembbox->lowerleft.x = pllx;
+ thisinst->schembbox->lowerleft.y = plly;
+ thisinst->schembbox->width = purx - pllx;
+ thisinst->schembbox->height = pury - plly;
+ }
+ else
+ invalidateschembbox(thisinst);
+}
+
+/*--------------------------------------------------------------*/
+/* Update things based on a changed instance bounding box. */
+/* If the parameter was a single-instance */
+/* substitution, only the page should be updated. If the */
+/* parameter was a default value, the library should be updated */
+/* and any pages containing the object where the parameter */
+/* takes the default value. */
+/*--------------------------------------------------------------*/
+
+void updateinstparam(objectptr bobj)
+{
+ short i, j;
+ objectptr pageobj;
+
+ /* change bounds on pagelib and all pages */
+ /* containing this *object* if and only if the object */
+ /* instance takes the default value. Also update the */
+ /* library page. */
+
+ for (i = 0; i < xobjs.pages; i++)
+ if (xobjs.pagelist[i]->pageinst != NULL) {
+ pageobj = xobjs.pagelist[i]->pageinst->thisobject;
+ if ((j = find_object(pageobj, topobject)) >= 0) {
+
+ /* Really, we'd like to recalculate the bounding box only if the */
+ /* parameter value is the default value which was just changed. */
+ /* However, then any non-default values may contain the wrong */
+ /* substitutions. */
+
+ objinstptr cinst = TOOBJINST(pageobj->plist + j);
+ if (cinst->thisobject->params == NULL) {
+ calcbboxvalues(xobjs.pagelist[i]->pageinst, pageobj->plist + j);
+ updatepagelib(PAGELIB, i);
+ }
+ }
+ }
+
+ for (i = 0; i < xobjs.numlibs; i++)
+ if (object_in_library(i, topobject))
+ composelib(i + LIBRARY);
+}
+
+/*--------------------------------------------------------------*/
+/* Calculate bbox on all elements of the given object */
+/*--------------------------------------------------------------*/
+
+void calcbbox(objinstptr binst)
+{
+ calcbboxvalues(binst, (genericptr *)NULL);
+ if (binst == areawin->topinstance) {
+ updatepagebounds(topobject);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Calculate bbox on the given element of the specified object. */
+/* This is a wrapper for calcbboxvalues() assuming that we're */
+/* on the top-level, and that page bounds need to be updated. */
+/*--------------------------------------------------------------*/
+
+void singlebbox(genericptr *gelem)
+{
+ calcbboxvalues(areawin->topinstance, (genericptr *)gelem);
+ updatepagebounds(topobject);
+}
+
+/*----------------------------------------------------------------------*/
+/* Extend bounding box based on selected elements only */
+/*----------------------------------------------------------------------*/
+
+void calcbboxselect()
+{
+ short *bsel;
+ for (bsel = areawin->selectlist; bsel < areawin->selectlist +
+ areawin->selects; bsel++)
+ calcbboxvalues(areawin->topinstance, topobject->plist + *bsel);
+
+ updatepagebounds(topobject);
+}
+
+/*--------------------------------------------------------------*/
+/* Update Bounding box for an object. */
+/* If newelement == NULL, calculate bounding box from scratch. */
+/* Otherwise, expand bounding box to enclose newelement. */
+/*--------------------------------------------------------------*/
+
+void calcbboxvalues(objinstptr thisinst, genericptr *newelement)
+{
+ genericptr *bboxgen;
+ short llx, lly, urx, ury;
+ objectptr thisobj = thisinst->thisobject;
+
+ /* no action if there are no elements */
+ if (thisobj->parts == 0) return;
+
+ /* If this object has parameters, then we will do a separate */
+ /* bounding box calculation on parameterized parts. This */
+ /* calculation ignores them, and the result is a base that the */
+ /* instance bounding-box computation can use as a starting point. */
+
+ /* set starting bounds as maximum bounds of screen */
+ llx = lly = 32767;
+ urx = ury = -32768;
+
+ for (bboxgen = thisobj->plist; bboxgen < thisobj->plist +
+ thisobj->parts; bboxgen++) {
+
+ /* override the "for" loop if we're doing a single element */
+ if (newelement != NULL) bboxgen = newelement;
+
+ if ((thisobj->params == NULL) || (!has_param(*bboxgen))) {
+ /* pins which do not appear outside of the object */
+ /* are ignored now---will be computed per instance. */
+
+ if (IS_LABEL(*bboxgen)) {
+ labelptr btext = TOLABEL(bboxgen);
+ if (btext->pin && !(btext->justify & PINVISIBLE)) {
+ goto nextgen;
+ }
+ }
+ calcbboxsingle(bboxgen, thisinst, &llx, &lly, &urx, &ury);
+
+ if (newelement == NULL)
+ switch(ELEMENTTYPE(*bboxgen)) {
+ case POLYGON: case SPLINE: case ARC: case PATH:
+ if (TOPOLY(bboxgen)->style & CLIPMASK)
+ bboxgen++;
+ break;
+ }
+ }
+nextgen:
+ if (newelement != NULL) break;
+ }
+
+ /* if this is a single-element calculation and its bounding box */
+ /* turned out to be smaller than the object's, then we need to */
+ /* recompute the entire object's bounding box in case it got */
+ /* smaller. This is not recursive, in spite of looks. */
+
+ if (newelement != NULL) {
+ if (llx > thisobj->bbox.lowerleft.x &&
+ lly > thisobj->bbox.lowerleft.y &&
+ urx < (thisobj->bbox.lowerleft.x + thisobj->bbox.width) &&
+ ury < (thisobj->bbox.lowerleft.y + thisobj->bbox.height)) {
+ calcbboxvalues(thisinst, NULL);
+ return;
+ }
+ else {
+ bboxcalc(thisobj->bbox.lowerleft.x, &llx, &urx);
+ bboxcalc(thisobj->bbox.lowerleft.y, &lly, &ury);
+ bboxcalc(thisobj->bbox.lowerleft.x + thisobj->bbox.width, &llx, &urx);
+ bboxcalc(thisobj->bbox.lowerleft.y + thisobj->bbox.height, &lly, &ury);
+ }
+ }
+
+ /* Set the new bounding box. In pathological cases, such as a page */
+ /* with only pin labels, the bounds may not have been changed from */
+ /* their initial values. If so, then don't touch the bounding box. */
+
+ if ((llx <= urx) && (lly <= ury)) {
+ thisobj->bbox.lowerleft.x = llx;
+ thisobj->bbox.lowerleft.y = lly;
+ thisobj->bbox.width = urx - llx;
+ thisobj->bbox.height = ury - lly;
+ }
+
+ /* calculate instance-specific values */
+ calcbboxinst(thisinst);
+}
+
+/*------------------------------------------------------*/
+/* Center an object in the viewing window */
+/*------------------------------------------------------*/
+
+void centerview(objinstptr tinst)
+{
+ XPoint origin, corner;
+ Dimension width, height;
+ float fitwidth, fitheight;
+ objectptr tobj = tinst->thisobject;
+
+ origin = tinst->bbox.lowerleft;
+ corner.x = origin.x + tinst->bbox.width;
+ corner.y = origin.y + tinst->bbox.height;
+
+ extendschembbox(tinst, &origin, &corner);
+
+ width = corner.x - origin.x;
+ height = corner.y - origin.y;
+
+ fitwidth = (float)areawin->width / ((float)width + 2 * DEFAULTGRIDSPACE);
+ fitheight = (float)areawin->height / ((float)height + 2 * DEFAULTGRIDSPACE);
+
+ tobj->viewscale = (fitwidth < fitheight) ?
+ min(MINAUTOSCALE, fitwidth) : min(MINAUTOSCALE, fitheight);
+
+ tobj->pcorner.x = origin.x - (areawin->width
+ / tobj->viewscale - width) / 2;
+ tobj->pcorner.y = origin.y - (areawin->height
+ / tobj->viewscale - height) / 2;
+
+ /* Copy new position values to the current window */
+
+ if (tobj == topobject) {
+ areawin->pcorner = tobj->pcorner;
+ areawin->vscale = tobj->viewscale;
+ }
+}
+
+/*-----------------------------------------------------------*/
+/* Refresh the window and scrollbars and write the page name */
+/*-----------------------------------------------------------*/
+
+void refresh(xcWidget bw, caddr_t clientdata, caddr_t calldata)
+{
+ drawarea(NULL, NULL, NULL);
+ if (areawin->scrollbarh)
+ drawhbar(areawin->scrollbarh, NULL, NULL);
+ if (areawin->scrollbarv)
+ drawvbar(areawin->scrollbarv, NULL, NULL);
+ printname(topobject);
+}
+
+/*------------------------------------------------------*/
+/* Center the current page in the viewing window */
+/*------------------------------------------------------*/
+
+void zoomview(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ if (eventmode == NORMAL_MODE || eventmode == COPY_MODE ||
+ eventmode == MOVE_MODE || eventmode == CATALOG_MODE ||
+ eventmode == FONTCAT_MODE || eventmode == EFONTCAT_MODE ||
+ eventmode == CATMOVE_MODE) {
+
+ centerview(areawin->topinstance);
+ areawin->lastbackground = NULL;
+ renderbackground();
+ refresh(NULL, NULL, NULL);
+ }
+}
+
+/*---------------------------------------------------------*/
+/* Basic X Graphics Routines in the User coordinate system */
+/*---------------------------------------------------------*/
+
+void UDrawSimpleLine(XPoint *pt1, XPoint *pt2)
+{
+ XPoint newpt1, newpt2;
+
+ UTransformbyCTM(DCTM, pt1, &newpt1, 1);
+ UTransformbyCTM(DCTM, pt2, &newpt2, 1);
+
+ DrawLine(dpy, areawin->window, areawin->gc,
+ newpt1.x, newpt1.y, newpt2.x, newpt2.y);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawLine(XPoint *pt1, XPoint *pt2)
+{
+ float tmpwidth = UTopTransScale(xobjs.pagelist[areawin->page]->wirewidth);
+
+ SetLineAttributes(dpy, areawin->gc, tmpwidth, LineSolid, CapRound, JoinBevel);
+ UDrawSimpleLine(pt1, pt2);
+}
+
+/*----------------------------------------------------------------------*/
+/* Add circle at given point to indicate that the point is a parameter. */
+/* The circle is divided into quarters. For parameterized y-coordinate */
+/* the top and bottom quarters are drawn. For parameterized x- */
+/* coordinate, the left and right quarters are drawn. A full circle */
+/* indicates either both x- and y-coordinates are parameterized, or */
+/* else any other kind of parameterization (presently, not used). */
+/* */
+/* (note that the two angles in XDrawArc() are 1) the start angle, */
+/* measured in absolute 64th degrees from 0 (3 o'clock), and 2) the */
+/* path length, in relative 64th degrees (positive = counterclockwise, */
+/* negative = clockwise)). */
+/*----------------------------------------------------------------------*/
+
+void UDrawCircle(XPoint *upt, u_char which)
+{
+ XPoint wpt;
+
+ user_to_window(*upt, &wpt);
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapButt, JoinMiter);
+
+ switch(which) {
+ case P_POSITION_X:
+ XDrawArc(dpy, areawin->window, areawin->gc, wpt.x - 4,
+ wpt.y - 4, 8, 8, -(45 * 64), (90 * 64));
+ XDrawArc(dpy, areawin->window, areawin->gc, wpt.x - 4,
+ wpt.y - 4, 8, 8, (135 * 64), (90 * 64));
+ break;
+ case P_POSITION_Y:
+ XDrawArc(dpy, areawin->window, areawin->gc, wpt.x - 4,
+ wpt.y - 4, 8, 8, (45 * 64), (90 * 64));
+ XDrawArc(dpy, areawin->window, areawin->gc, wpt.x - 4,
+ wpt.y - 4, 8, 8, (225 * 64), (90 * 64));
+ break;
+ default:
+ XDrawArc(dpy, areawin->window, areawin->gc, wpt.x - 4,
+ wpt.y - 4, 8, 8, 0, (360 * 64));
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Add "X" at string origin */
+/*----------------------------------------------------------------------*/
+
+void UDrawXAt(XPoint *wpt)
+{
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapButt, JoinMiter);
+ DrawLine(dpy, areawin->window, areawin->gc, wpt->x - 3,
+ wpt->y - 3, wpt->x + 3, wpt->y + 3);
+ DrawLine(dpy, areawin->window, areawin->gc, wpt->x + 3,
+ wpt->y - 3, wpt->x - 3, wpt->y + 3);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw "X" on current level */
+/*----------------------------------------------------------------------*/
+
+void UDrawX(labelptr curlabel)
+{
+ XPoint wpt;
+
+ user_to_window(curlabel->position, &wpt);
+ UDrawXAt(&wpt);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw "X" on top level (only for LOCAL and GLOBAL pin labels) */
+/*----------------------------------------------------------------------*/
+
+void UDrawXDown(labelptr curlabel)
+{
+ XPoint wpt;
+
+ UTransformbyCTM(DCTM, &curlabel->position, &wpt, 1);
+ UDrawXAt(&wpt);
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the "real" width, height, and origin of an object including pin */
+/* labels and so forth that only show up on a schematic when it is the */
+/* top-level object. */
+/*----------------------------------------------------------------------*/
+
+int toplevelwidth(objinstptr bbinst, short *rllx)
+{
+ short llx, urx;
+ short origin, corner;
+
+ if (bbinst->schembbox == NULL) {
+ if (rllx) *rllx = bbinst->bbox.lowerleft.x;
+ return bbinst->bbox.width;
+ }
+
+ origin = bbinst->bbox.lowerleft.x;
+ corner = origin + bbinst->bbox.width;
+
+ llx = bbinst->schembbox->lowerleft.x;
+ urx = llx + bbinst->schembbox->width;
+
+ bboxcalc(llx, &origin, &corner);
+ bboxcalc(urx, &origin, &corner);
+
+ if (rllx) *rllx = origin;
+ return(corner - origin);
+}
+
+/*----------------------------------------------------------------------*/
+
+int toplevelheight(objinstptr bbinst, short *rlly)
+{
+ short lly, ury;
+ short origin, corner;
+
+ if (bbinst->schembbox == NULL) {
+ if (rlly) *rlly = bbinst->bbox.lowerleft.y;
+ return bbinst->bbox.height;
+ }
+
+ origin = bbinst->bbox.lowerleft.y;
+ corner = origin + bbinst->bbox.height;
+
+ lly = bbinst->schembbox->lowerleft.y;
+ ury = lly + bbinst->schembbox->height;
+
+ bboxcalc(lly, &origin, &corner);
+ bboxcalc(ury, &origin, &corner);
+
+ if (rlly) *rlly = origin;
+ return(corner - origin);
+}
+
+/*----------------------------------------------------------------------*/
+/* Add dimensions of schematic pins to an object's bounding box */
+/*----------------------------------------------------------------------*/
+
+void extendschembbox(objinstptr bbinst, XPoint *origin, XPoint *corner)
+{
+ short llx, lly, urx, ury;
+
+ if ((bbinst == NULL) || (bbinst->schembbox == NULL)) return;
+
+ llx = bbinst->schembbox->lowerleft.x;
+ lly = bbinst->schembbox->lowerleft.y;
+ urx = llx + bbinst->schembbox->width;
+ ury = lly + bbinst->schembbox->height;
+
+ bboxcalc(llx, &(origin->x), &(corner->x));
+ bboxcalc(lly, &(origin->y), &(corner->y));
+ bboxcalc(urx, &(origin->x), &(corner->x));
+ bboxcalc(ury, &(origin->y), &(corner->y));
+}
+
+/*----------------------------------------------------------------------*/
+/* Adjust a pinlabel position to account for pad spacing */
+/*----------------------------------------------------------------------*/
+
+void pinadjust (short justify, short *xpoint, short *ypoint, short dir)
+{
+ int delx, dely;
+
+ dely = (justify & NOTBOTTOM) ?
+ ((justify & TOP) ? -PADSPACE : 0) : PADSPACE;
+ delx = (justify & NOTLEFT) ?
+ ((justify & RIGHT) ? -PADSPACE : 0) : PADSPACE;
+
+ if (xpoint != NULL) *xpoint += (dir > 0) ? delx : -delx;
+ if (ypoint != NULL) *ypoint += (dir > 0) ? dely : -dely;
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw line for editing text (position of cursor in string is given by */
+/* tpos (2nd parameter) */
+/*----------------------------------------------------------------------*/
+
+void UDrawTextLine(labelptr curlabel, short tpos)
+{
+ XPoint points[2]; /* top and bottom of text cursor line */
+ short xdist, xbase, tmpjust;
+ TextExtents tmpext;
+
+ /* correct for position, rotation, scale, and flip invariance of text */
+
+ UPushCTM();
+ UPreMultCTM(DCTM, curlabel->position, curlabel->scale, curlabel->rotation);
+ tmpjust = flipadjust(curlabel->justify);
+
+ SetFunction(dpy, areawin->gc, GXxor);
+ SetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+
+ tmpext = ULength(curlabel, areawin->topinstance, tpos, NULL);
+ xdist = tmpext.width;
+ xbase = tmpext.base;
+ tmpext = ULength(curlabel, areawin->topinstance, 0, NULL);
+
+ points[0].x = (tmpjust & NOTLEFT ?
+ (tmpjust & RIGHT ? -tmpext.maxwidth : -tmpext.maxwidth >> 1) : 0)
+ + xdist;
+ points[0].y = (tmpjust & NOTBOTTOM ?
+ (tmpjust & TOP ? -tmpext.ascent : -(tmpext.ascent + tmpext.base) / 2)
+ : -tmpext.base) + xbase - 3;
+ points[1].x = points[0].x;
+ points[1].y = points[0].y + TEXTHEIGHT + 6;
+
+ if (curlabel->pin) {
+ pinadjust(tmpjust, &(points[0].x), &(points[0].y), 1);
+ pinadjust(tmpjust, &(points[1].x), &(points[1].y), 1);
+ }
+
+ /* draw the line */
+
+ UDrawLine(&points[0], &points[1]);
+ UPopCTM();
+
+ UDrawX(curlabel);
+}
+
+/*-----------------------------------------------------------------*/
+/* Draw lines for editing text when multiple characters are chosen */
+/*-----------------------------------------------------------------*/
+
+void UDrawTLine(labelptr curlabel)
+{
+ UDrawTextLine(curlabel, areawin->textpos);
+ if ((areawin->textend > 0) && (areawin->textend < areawin->textpos)) {
+ UDrawTextLine(curlabel, areawin->textend);
+ }
+}
+
+/*----------------------*/
+/* Draw an X */
+/*----------------------*/
+
+void UDrawXLine(XPoint opt, XPoint cpt)
+{
+ XPoint upt, vpt;
+
+ SetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+ SetFunction(dpy, areawin->gc, GXxor);
+
+ user_to_window(cpt, &upt);
+ user_to_window(opt, &vpt);
+
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineOnOffDash, CapButt, JoinMiter);
+ DrawLine(dpy, areawin->window, areawin->gc, vpt.x, vpt.y, upt.x, upt.y);
+
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapButt, JoinMiter);
+ DrawLine(dpy, areawin->window, areawin->gc, upt.x - 3, upt.y - 3,
+ upt.x + 3, upt.y + 3);
+ DrawLine(dpy, areawin->window, areawin->gc, upt.x + 3, upt.y - 3,
+ upt.x - 3, upt.y + 3);
+
+ SetFunction(dpy, areawin->gc, areawin->gctype);
+ SetForeground(dpy, areawin->gc, areawin->gccolor);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawBox(XPoint origin, XPoint corner)
+{
+ XPoint worig, wcorn;
+
+ user_to_window(origin, &worig);
+ user_to_window(corner, &wcorn);
+
+ SetFunction(dpy, areawin->gc, GXxor);
+ SetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapRound, JoinBevel);
+
+ DrawLine(dpy, areawin->window, areawin->gc, worig.x, worig.y,
+ worig.x, wcorn.y);
+ DrawLine(dpy, areawin->window, areawin->gc, worig.x, wcorn.y,
+ wcorn.x, wcorn.y);
+ DrawLine(dpy, areawin->window, areawin->gc, wcorn.x, wcorn.y,
+ wcorn.x, worig.y);
+ DrawLine(dpy, areawin->window, areawin->gc, wcorn.x, worig.y,
+ worig.x, worig.y);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw a box indicating the dimensions of the edit element that most */
+/* closely reach the position "corner". */
+/*----------------------------------------------------------------------*/
+
+float UDrawRescaleBox(XPoint *corner)
+{
+ XPoint origpoints[5], newpoints[5];
+ genericptr rgen;
+ float savescale, newscale;
+ long mindist, testdist, refdist;
+ labelptr rlab;
+ graphicptr rgraph;
+ objinstptr rinst;
+ int i;
+
+ if (areawin->selects == 0) return 0.0;
+
+ SetFunction(dpy, areawin->gc, GXxor);
+ SetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+ SetThinLineAttributes(dpy, areawin->gc, 0, LineSolid, CapRound, JoinBevel);
+
+ /* Use only the 1st selection as a reference to set the scale */
+
+ rgen = SELTOGENERIC(areawin->selectlist);
+
+ switch(ELEMENTTYPE(rgen)) {
+ case LABEL:
+ rlab = (labelptr)rgen;
+ labelbbox(rlab, newpoints, areawin->topinstance);
+ newpoints[4] = newpoints[0];
+ mindist = LONG_MAX;
+ for (i = 0; i < 4; i++) {
+ testdist = finddist(&newpoints[i], &newpoints[i+1], corner);
+ if (testdist < mindist)
+ mindist = testdist;
+ }
+ refdist = wirelength(corner, &(rlab->position));
+ mindist = (int)sqrt(abs((double)mindist));
+ savescale = rlab->scale;
+ if (!test_insideness((int)corner->x, (int)corner->y, newpoints))
+ mindist = -mindist;
+ if (refdist == mindist) refdist = 1 - mindist;
+ if (rlab->scale < 0) rlab->scale = -rlab->scale;
+ newscale = fabs(rlab->scale * (float)refdist / (float)(refdist + mindist));
+ if (newscale > 10 * rlab->scale) newscale = 10 * rlab->scale;
+ if (areawin->snapto) {
+ float snapstep = 2 * (float)xobjs.pagelist[areawin->page]->gridspace
+ / (float)xobjs.pagelist[areawin->page]->snapspace;
+ newscale = (float)((int)(newscale * snapstep)) / snapstep;
+ if (newscale < (1.0 / snapstep)) newscale = (1.0 / snapstep);
+ }
+ else if (newscale < 0.1 * rlab->scale) newscale = 0.1 * rlab->scale;
+ rlab->scale = (savescale < 0) ? -newscale : newscale;
+ labelbbox(rlab, newpoints, areawin->topinstance);
+ rlab->scale = savescale;
+ if (savescale < 0) newscale = -newscale;
+ break;
+
+ case GRAPHIC:
+ rgraph = (graphicptr)rgen;
+ graphicbbox(rgraph, newpoints);
+ newpoints[4] = newpoints[0];
+ mindist = LONG_MAX;
+ for (i = 0; i < 4; i++) {
+ testdist = finddist(&newpoints[i], &newpoints[i+1], corner);
+ if (testdist < mindist)
+ mindist = testdist;
+ }
+ refdist = wirelength(corner, &(rgraph->position));
+ mindist = (int)sqrt(abs((double)mindist));
+ savescale = rgraph->scale;
+ if (!test_insideness((int)corner->x, (int)corner->y, newpoints))
+ mindist = -mindist;
+ if (refdist == mindist) refdist = 1 - mindist; /* avoid inf result */
+ if (rgraph->scale < 0) rgraph->scale = -rgraph->scale;
+ newscale = fabs(rgraph->scale * (float)refdist / (float)(refdist + mindist));
+ if (newscale > 10 * rgraph->scale) newscale = 10 * rgraph->scale;
+ if (areawin->snapto) {
+ float snapstep = 2 * (float)xobjs.pagelist[areawin->page]->gridspace
+ / (float)xobjs.pagelist[areawin->page]->snapspace;
+ newscale = (float)((int)(newscale * snapstep)) / snapstep;
+ if (newscale < (1.0 / snapstep)) newscale = (1.0 / snapstep);
+ }
+ else if (newscale < 0.1 * rgraph->scale) newscale = 0.1 * rgraph->scale;
+ rgraph->scale = (savescale < 0) ? -newscale : newscale;
+ graphicbbox(rgraph, newpoints);
+ rgraph->scale = savescale;
+ if (savescale < 0) newscale = -newscale;
+ break;
+
+ case OBJINST:
+ rinst = (objinstptr)rgen;
+ objinstbbox(rinst, newpoints, 0);
+ newpoints[4] = newpoints[0];
+ mindist = LONG_MAX;
+ for (i = 0; i < 4; i++) {
+ testdist = finddist(&newpoints[i], &newpoints[i+1], corner);
+ if (testdist < mindist)
+ mindist = testdist;
+ }
+ refdist = wirelength(corner, &(rinst->position));
+ mindist = (int)sqrt(abs((double)mindist));
+ savescale = rinst->scale;
+ if (!test_insideness((int)corner->x, (int)corner->y, newpoints))
+ mindist = -mindist;
+ if (refdist == mindist) refdist = 1 - mindist; /* avoid inf result */
+ if (rinst->scale < 0) rinst->scale = -rinst->scale;
+ newscale = fabs(rinst->scale * (float)refdist / (float)(refdist + mindist));
+ if (newscale > 10 * rinst->scale) newscale = 10 * rinst->scale;
+ if (areawin->snapto) {
+ float snapstep = 2 * (float)xobjs.pagelist[areawin->page]->gridspace
+ / (float)xobjs.pagelist[areawin->page]->snapspace;
+ newscale = (float)((int)(newscale * snapstep)) / snapstep;
+ if (newscale < (1.0 / snapstep)) newscale = (1.0 / snapstep);
+ }
+ else if (newscale < 0.1 * rinst->scale) newscale = 0.1 * rinst->scale;
+ rinst->scale = (savescale < 0) ? -newscale : newscale;
+ objinstbbox(rinst, newpoints, 0);
+ rinst->scale = savescale;
+ if (savescale < 0) newscale = -newscale;
+ break;
+ }
+
+ UTransformbyCTM(DCTM, newpoints, origpoints, 4);
+ strokepath(origpoints, 4, 0, 1);
+ return newscale;
+}
+
+/*-------------------------------------------------------------------------*/
+void UDrawBBox()
+{
+ XPoint origin;
+ XPoint worig, wcorn, corner;
+ objinstptr bbinst = areawin->topinstance;
+
+ if ((!areawin->bboxon) || (checkforbbox(topobject) != NULL)) return;
+
+ origin = bbinst->bbox.lowerleft;
+ corner.x = origin.x + bbinst->bbox.width;
+ corner.y = origin.y + bbinst->bbox.height;
+
+ /* Include any schematic labels in the bounding box. */
+ extendschembbox(bbinst, &origin, &corner);
+
+ user_to_window(origin, &worig);
+ user_to_window(corner, &wcorn);
+
+ SetForeground(dpy, areawin->gc, BBOXCOLOR);
+ DrawLine(dpy, areawin->window, areawin->gc, worig.x, worig.y,
+ worig.x, wcorn.y);
+ DrawLine(dpy, areawin->window, areawin->gc, worig.x, wcorn.y,
+ wcorn.x, wcorn.y);
+ DrawLine(dpy, areawin->window, areawin->gc, wcorn.x, wcorn.y,
+ wcorn.x, worig.y);
+ DrawLine(dpy, areawin->window, areawin->gc, wcorn.x, worig.y,
+ worig.x, worig.y);
+}
+
+/*----------------------------------------------------------------------*/
+/* Fill and/or draw a border around the stroking path */
+/*----------------------------------------------------------------------*/
+
+void strokepath(XPoint *pathlist, short number, short style, float width)
+{
+ float tmpwidth;
+
+ tmpwidth = UTopTransScale(width);
+
+ if (!(style & CLIPMASK) || (areawin->showclipmasks == TRUE) ||
+ (areawin->clipped < 0)) {
+ if (style & FILLED || (!(style & FILLED) && style & OPAQUE)) {
+ if ((style & FILLSOLID) == FILLSOLID)
+ SetFillStyle(dpy, areawin->gc, FillSolid);
+ else if (!(style & FILLED)) {
+ SetFillStyle(dpy, areawin->gc, FillOpaqueStippled);
+ SetStipple(dpy, areawin->gc, 7);
+ }
+ else {
+ if (style & OPAQUE)
+ SetFillStyle(dpy, areawin->gc, FillOpaqueStippled);
+ else
+ SetFillStyle(dpy, areawin->gc, FillStippled);
+ SetStipple(dpy, areawin->gc, ((style & FILLSOLID) >> 5));
+ }
+ FillPolygon(dpy, areawin->window, areawin->gc, pathlist, number, Nonconvex,
+ CoordModeOrigin);
+ /* return to original state */
+ SetFillStyle(dpy, areawin->gc, FillSolid);
+ }
+ if (!(style & NOBORDER)) {
+ if (style & (DASHED | DOTTED)) {
+ /* Set up dots or dashes */
+ char dashstring[2];
+ /* prevent values greater than 255 from folding back into */
+ /* type char. Limit to 63 (=255/4) to keep at least the */
+ /* dot/gap ratio to scale when 'gap' is at its maximum */
+ /* value. */
+ unsigned char dotsize = min(63, max(1, (short)tmpwidth));
+ if (style & DASHED)
+ dashstring[0] = 4 * dotsize;
+ else if (style & DOTTED)
+ dashstring[0] = dotsize;
+ dashstring[1] = 4 * dotsize;
+ SetDashes(dpy, areawin->gc, 0, dashstring, 2);
+ SetLineAttributes(dpy, areawin->gc, tmpwidth, LineOnOffDash,
+ CapButt, (style & SQUARECAP) ? JoinMiter : JoinBevel);
+ }
+ else
+ SetLineAttributes(dpy, areawin->gc, tmpwidth, LineSolid,
+ (style & SQUARECAP) ? CapProjecting : CapRound,
+ (style & SQUARECAP) ? JoinMiter : JoinBevel);
+
+ /* draw the spline and close off if so specified */
+ DrawLines(dpy, areawin->window, areawin->gc, pathlist,
+ number, CoordModeOrigin);
+ if (!(style & UNCLOSED))
+ DrawLine(dpy, areawin->window, areawin->gc, pathlist[0].x,
+ pathlist[0].y, pathlist[number - 1].x, pathlist[number - 1].y);
+ }
+ }
+
+ if (style & CLIPMASK) {
+ if (areawin->clipped == 0) {
+ XSetForeground(dpy, areawin->cmgc, 0);
+ XFillRectangle(dpy, areawin->clipmask, areawin->cmgc, 0, 0,
+ areawin->width, areawin->height);
+ XSetForeground(dpy, areawin->cmgc, 1);
+ FillPolygon(dpy, areawin->clipmask, areawin->cmgc, pathlist,
+ number, Nonconvex, CoordModeOrigin);
+ XSetClipMask(dpy, areawin->gc, areawin->clipmask);
+ // printf("level 0: Clip to clipmask\n"); // Diagnostic
+ areawin->clipped++;
+ }
+ else if ((areawin->clipped > 0) && (areawin->clipped & 1) == 0) {
+ if (areawin->pbuf == (Pixmap)NULL) {
+ areawin->pbuf = XCreatePixmap (dpy, areawin->window,
+ areawin->width, areawin->height, 1);
+ }
+ XCopyArea(dpy, areawin->clipmask, areawin->pbuf, areawin->cmgc,
+ 0, 0, areawin->width, areawin->height, 0, 0);
+ XSetForeground(dpy, areawin->cmgc, 0);
+ XFillRectangle(dpy, areawin->clipmask, areawin->cmgc, 0, 0,
+ areawin->width, areawin->height);
+ XSetForeground(dpy, areawin->cmgc, 1);
+ FillPolygon(dpy, areawin->clipmask, areawin->cmgc, pathlist,
+ number, Nonconvex, CoordModeOrigin);
+ XSetFunction(dpy, areawin->cmgc, GXand);
+ XCopyArea(dpy, areawin->pbuf, areawin->clipmask, areawin->cmgc,
+ 0, 0, areawin->width, areawin->height, 0, 0);
+ XSetFunction(dpy, areawin->cmgc, GXcopy);
+ XSetClipMask(dpy, areawin->gc, areawin->clipmask);
+ // printf("level X: Clip to clipmask\n"); // Diagnostic
+ areawin->clipped++;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+void makesplinepath(splineptr thespline, XPoint *pathlist)
+{
+ XPoint *tmpptr = pathlist;
+
+ UTransformbyCTM(DCTM, &(thespline->ctrl[0]), tmpptr, 1);
+ UfTransformbyCTM(DCTM, thespline->points, ++tmpptr, INTSEGS);
+ UTransformbyCTM(DCTM, &(thespline->ctrl[3]), tmpptr + INTSEGS, 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawSpline(splineptr thespline, float passwidth)
+{
+ XPoint tmppoints[SPLINESEGS];
+ float scaledwidth;
+
+ scaledwidth = thespline->width * passwidth;
+
+ makesplinepath(thespline, tmppoints);
+ strokepath(tmppoints, SPLINESEGS, thespline->style, scaledwidth);
+ if (thespline->cycle != NULL) {
+ UDrawXLine(thespline->ctrl[0], thespline->ctrl[1]);
+ UDrawXLine(thespline->ctrl[3], thespline->ctrl[2]);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawPolygon(polyptr thepoly, float passwidth)
+{
+ XPoint *tmppoints = (pointlist) malloc(thepoly->number * sizeof(XPoint));
+ float scaledwidth;
+
+ scaledwidth = thepoly->width * passwidth;
+
+ UTransformbyCTM(DCTM, thepoly->points, tmppoints, thepoly->number);
+ strokepath(tmppoints, thepoly->number, thepoly->style, scaledwidth);
+ free(tmppoints);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawArc(arcptr thearc, float passwidth)
+{
+ XPoint tmppoints[RSTEPS + 2];
+ float scaledwidth;
+
+ scaledwidth = thearc->width * passwidth;
+
+ UfTransformbyCTM(DCTM, thearc->points, tmppoints, thearc->number);
+ strokepath(tmppoints, thearc->number, thearc->style, scaledwidth);
+ if (thearc->cycle != NULL) {
+ UDrawXLine(thearc->position, areawin->save);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+void UDrawPath(pathptr thepath, float passwidth)
+{
+ XPoint *tmppoints = (pointlist) malloc(sizeof(XPoint));
+ genericptr *genpath;
+ polyptr thepoly;
+ splineptr thespline;
+ int pathsegs = 0, curseg = 0;
+ float scaledwidth;
+ Boolean draweditlines = FALSE;
+
+ /* First pass---check for any splines that are being edited. If */
+ /* any one is, then draw all control points for all splines in the */
+ /* path. */
+
+ for (genpath = thepath->plist; genpath < thepath->plist + thepath->parts;
+ genpath++) {
+ switch(ELEMENTTYPE(*genpath)) {
+ case SPLINE:
+ thespline = TOSPLINE(genpath);
+ if (thespline->cycle != NULL)
+ draweditlines = TRUE;
+ break;
+ }
+ if (draweditlines) break;
+ }
+
+ for (genpath = thepath->plist; genpath < thepath->plist + thepath->parts;
+ genpath++) {
+ switch(ELEMENTTYPE(*genpath)) {
+ case POLYGON:
+ thepoly = TOPOLY(genpath);
+ pathsegs += thepoly->number;
+ tmppoints = (pointlist) realloc(tmppoints, pathsegs * sizeof(XPoint));
+ UTransformbyCTM(DCTM, thepoly->points, tmppoints + curseg, thepoly->number);
+ curseg = pathsegs;
+ break;
+ case SPLINE:
+ thespline = TOSPLINE(genpath);
+ pathsegs += SPLINESEGS;
+ tmppoints = (pointlist) realloc(tmppoints, pathsegs * sizeof(XPoint));
+ makesplinepath(thespline, tmppoints + curseg);
+ curseg = pathsegs;
+
+ if (draweditlines) {
+ UDrawXLine(thespline->ctrl[0], thespline->ctrl[1]);
+ UDrawXLine(thespline->ctrl[3], thespline->ctrl[2]);
+ }
+ break;
+ }
+ }
+ scaledwidth = thepath->width * passwidth;
+
+ strokepath(tmppoints, pathsegs, thepath->style, scaledwidth);
+ free(tmppoints);
+}
+
+/*----------------------------------------------------------------------*/
+/* Main recursive object instance drawing routine. */
+/* context is the instance information passed down from above */
+/* theinstance is the object instance to be drawn */
+/* level is the level of recursion */
+/* passcolor is the inherited color value passed to object */
+/* passwidth is the inherited linewidth value passed to the object */
+/* stack contains graphics context information */
+/*----------------------------------------------------------------------*/
+
+void UDrawObject(objinstptr theinstance, short level, int passcolor,
+ float passwidth, pushlistptr *stack)
+{
+ genericptr *areagen;
+ float tmpwidth;
+ int defaultcolor = passcolor;
+ int curcolor = passcolor;
+ int thispart;
+ short savesel;
+ XPoint bboxin[2], bboxout[2];
+ u_char xm, ym;
+ objectptr theobject = theinstance->thisobject;
+
+ /* Save the number of selections and set it to zero while we do the */
+ /* object drawing. */
+
+ savesel = areawin->selects;
+ areawin->selects = 0;
+
+ /* All parts are given in the coordinate system of the object, unless */
+ /* this is the top-level object, in which they will be interpreted as */
+ /* relative to the screen. */
+
+ UPushCTM();
+
+ if (stack) {
+ /* Save the current clipping mask and push it on the stack */
+ if (areawin->clipped > 0) {
+ push_stack((pushlistptr *)stack, theinstance, (char *)areawin->clipmask);
+ areawin->clipmask = XCreatePixmap(dpy, areawin->window, areawin->width,
+ areawin->height, 1);
+ XCopyArea(dpy, (Pixmap)(*stack)->clientdata, areawin->clipmask, areawin->cmgc,
+ 0, 0, areawin->width, areawin->height, 0, 0);
+ }
+ else
+ push_stack((pushlistptr *)stack, theinstance, (char *)NULL);
+ }
+ if (level != 0)
+ UPreMultCTM(DCTM, theinstance->position, theinstance->scale,
+ theinstance->rotation);
+
+ if (theinstance->style & LINE_INVARIANT)
+ passwidth /= fabs(theinstance->scale);
+
+ /* do a quick test for intersection with the display window */
+
+ bboxin[0].x = theobject->bbox.lowerleft.x;
+ bboxin[0].y = theobject->bbox.lowerleft.y;
+ bboxin[1].x = theobject->bbox.lowerleft.x + theobject->bbox.width;
+ bboxin[1].y = theobject->bbox.lowerleft.y + theobject->bbox.height;
+ if (level == 0)
+ extendschembbox(theinstance, &(bboxin[0]), &(bboxin[1]));
+ UTransformbyCTM(DCTM, bboxin, bboxout, 2);
+
+ xm = (bboxout[0].x < bboxout[1].x) ? 0 : 1;
+ ym = (bboxout[0].y < bboxout[1].y) ? 0 : 1;
+
+ if (bboxout[xm].x < areawin->width && bboxout[ym].y < areawin->height &&
+ bboxout[1 - xm].x > 0 && bboxout[1 - ym].y > 0) {
+
+ /* make parameter substitutions */
+ psubstitute(theinstance);
+
+ /* draw all of the elements */
+
+ tmpwidth = UTopTransScale(passwidth);
+ SetLineAttributes(dpy, areawin->gc, tmpwidth, LineSolid, CapRound,
+ JoinBevel);
+
+ /* guard against plist being regenerated during a redraw by the */
+ /* expression parameter mechanism (should that be prohibited?) */
+
+ for (thispart = 0; thispart < theobject->parts; thispart++) {
+ areagen = theobject->plist + thispart;
+ if ((*areagen)->type & DRAW_HIDE) continue;
+
+ if (defaultcolor != DOFORALL) {
+ Boolean clipcolor = FALSE;
+ switch(ELEMENTTYPE(*areagen)) {
+ case(POLYGON): case(SPLINE): case(ARC): case(PATH):
+ if (TOPOLY(areagen)->style & CLIPMASK)
+ clipcolor = TRUE;
+ break;
+ }
+ if (((*areagen)->color != curcolor) || (clipcolor == TRUE)) {
+ if (clipcolor)
+ curcolor = CLIPMASKCOLOR;
+ else if ((*areagen)->color == DEFAULTCOLOR)
+ curcolor = defaultcolor;
+ else
+ curcolor = (*areagen)->color;
+
+ XcTopSetForeground(curcolor);
+ }
+ }
+
+ switch(ELEMENTTYPE(*areagen)) {
+ case(POLYGON):
+ if (level == 0 || !((TOPOLY(areagen))->style & BBOX))
+ UDrawPolygon(TOPOLY(areagen), passwidth);
+ break;
+
+ case(SPLINE):
+ UDrawSpline(TOSPLINE(areagen), passwidth);
+ break;
+
+ case(ARC):
+ UDrawArc(TOARC(areagen), passwidth);
+ break;
+
+ case(PATH):
+ UDrawPath(TOPATH(areagen), passwidth);
+ break;
+
+ case(GRAPHIC):
+ UDrawGraphic(TOGRAPHIC(areagen));
+ break;
+
+ case(OBJINST):
+ if (areawin->editinplace && stack && (TOOBJINST(areagen)
+ == areawin->topinstance)) {
+ /* If stack matches areawin->stack, then don't draw */
+ /* because it would be redundant. */
+ pushlistptr alist = *stack, blist = areawin->stack;
+ while (alist && blist) {
+ if (alist->thisinst != blist->thisinst) break;
+ alist = alist->next;
+ blist = blist->next;
+ }
+ if ((!alist) || (!blist)) break;
+ }
+ if (areawin->clipped > 0) areawin->clipped += 2;
+ UDrawObject(TOOBJINST(areagen), level + 1, curcolor, passwidth, stack);
+ if (areawin->clipped > 0) areawin->clipped -= 2;
+ break;
+
+ case(LABEL):
+ if (level == 0 || TOLABEL(areagen)->pin == False)
+ UDrawString(TOLABEL(areagen), curcolor, theinstance);
+ else if ((TOLABEL(areagen)->justify & PINVISIBLE) && areawin->pinpointon)
+ UDrawString(TOLABEL(areagen), curcolor, theinstance);
+ else if (TOLABEL(areagen)->justify & PINVISIBLE)
+ UDrawStringNoX(TOLABEL(areagen), curcolor, theinstance);
+ else if (level == 1 && TOLABEL(areagen)->pin &&
+ TOLABEL(areagen)->pin != INFO && areawin->pinpointon)
+ UDrawXDown(TOLABEL(areagen));
+ break;
+ }
+ if (areawin->clipped > 0) {
+ if ((areawin->clipped & 3) == 1) {
+ areawin->clipped++;
+ }
+ else if ((areawin->clipped & 3) == 2) {
+ areawin->clipped -= 2;
+ if ((!stack) || ((*stack)->clientdata == (char *)NULL)) {
+ XSetClipMask(dpy, areawin->gc, None);
+ // printf("1: Clear clipmask\n"); // Diagnostic
+ }
+ else {
+ XSetClipMask(dpy, areawin->gc, (Pixmap)((*stack)->clientdata));
+ // printf("1: Set to pushed clipmask\n"); // Diagnostic
+ }
+ }
+ }
+ }
+
+ /* restore the color passed to the object, if different from current color */
+
+ if ((defaultcolor != DOFORALL) && (passcolor != curcolor)) {
+ XTopSetForeground(passcolor);
+ }
+ if (areawin->clipped > 0) {
+ if ((areawin->clipped & 3) != 3) {
+ if ((!stack) || ((*stack)->clientdata == (char *)NULL)) {
+ XSetClipMask(dpy, areawin->gc, None);
+ // printf("2: Clear clipmask\n"); // Diagnostic
+ }
+ else {
+ XSetClipMask(dpy, areawin->gc, (Pixmap)((*stack)->clientdata));
+ // printf("2: Set to pushed clipmask\n"); // Diagnostic
+ }
+ }
+ areawin->clipped &= ~3;
+ }
+ }
+
+ /* restore the selection list (if any) */
+ areawin->selects = savesel;
+ UPopCTM();
+ if (stack) {
+ if ((*stack) != NULL) {
+ if ((*stack)->clientdata != (char *)NULL) {
+ XFreePixmap(dpy, areawin->clipmask);
+ areawin->clipmask = (Pixmap)(*stack)->clientdata;
+ // printf("3: Restore clipmask\n"); // Diagnostic
+ }
+ }
+ pop_stack(stack);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursively run through the current page and find any labels which */
+/* are declared to be style LATEX. If "checkonly" is present, we set */
+/* it to TRUE or FALSE depending on whether or not LATEX labels have */
+/* been encountered. If NULL, then we write LATEX output appropriately */
+/* to a file named with the page filename + suffix ".tex". */
+/*----------------------------------------------------------------------*/
+
+void UDoLatex(objinstptr theinstance, short level, FILE *f,
+ float scale, float scale2, int tx, int ty, Boolean *checkonly)
+{
+ XPoint lpos, xlpos;
+ XfPoint xfpos;
+ labelptr thislabel;
+ genericptr *areagen;
+ objectptr theobject = theinstance->thisobject;
+ char *ltext;
+ int lrjust, tbjust;
+
+ UPushCTM();
+ if (level != 0)
+ UPreMultCTM(DCTM, theinstance->position, theinstance->scale,
+ theinstance->rotation);
+
+ /* make parameter substitutions */
+ psubstitute(theinstance);
+
+ /* find all of the elements */
+
+ for (areagen = theobject->plist; areagen < theobject->plist +
+ theobject->parts; areagen++) {
+
+ switch(ELEMENTTYPE(*areagen)) {
+ case(OBJINST):
+ UDoLatex(TOOBJINST(areagen), level + 1, f, scale, scale2, tx, ty, checkonly);
+ break;
+
+ case(LABEL):
+ thislabel = TOLABEL(areagen);
+ if (level == 0 || thislabel->pin == False ||
+ (thislabel->justify & PINVISIBLE))
+ if (thislabel->justify & LATEXLABEL) {
+ if (checkonly) {
+ *checkonly = TRUE;
+ return;
+ }
+ else {
+ lpos.x = thislabel->position.x;
+ lpos.y = thislabel->position.y;
+ UTransformbyCTM(DCTM, &lpos, &xlpos, 1);
+ xlpos.x += tx;
+ xlpos.y += ty;
+ xfpos.x = (float)xlpos.x * scale;
+ xfpos.y = (float)xlpos.y * scale;
+ xfpos.x /= 72.0;
+ xfpos.y /= 72.0;
+ xfpos.x -= 1.0;
+ xfpos.y -= 1.0;
+ xfpos.x += 0.056;
+ xfpos.y += 0.056;
+ xfpos.x /= scale2;
+ xfpos.y /= scale2;
+ ltext = textprinttex(thislabel->string, theinstance);
+ tbjust = thislabel->justify & (NOTBOTTOM | TOP);
+ lrjust = thislabel->justify & (NOTLEFT | RIGHT);
+
+ /* The 1.2 factor accounts for the difference between */
+ /* Xcircuit's label scale of "1" and LaTeX's "normalsize" */
+
+ fprintf(f, " \\putbox{%3.2fin}{%3.2fin}{%3.2f}{",
+ xfpos.x, xfpos.y, 1.2 * thislabel->scale);
+ if (thislabel->rotation != 0)
+ fprintf(f, "\\rotatebox{-%d}{", thislabel->rotation);
+ if (lrjust == (NOTLEFT | RIGHT)) fprintf(f, "\\rightbox{");
+ else if (lrjust == NOTLEFT) fprintf(f, "\\centbox{");
+ if (tbjust == (NOTBOTTOM | TOP)) fprintf(f, "\\topbox{");
+ else if (tbjust == NOTBOTTOM) fprintf(f, "\\midbox{");
+ fprintf(f, "%s", ltext);
+ if (lrjust != NORMAL) fprintf(f, "}");
+ if (tbjust != NORMAL) fprintf(f, "}");
+ if (thislabel->rotation != 0) fprintf(f, "}");
+ fprintf(f, "}%%\n");
+ free(ltext);
+ }
+ }
+ break;
+ }
+ }
+ UPopCTM();
+}
+
+/*----------------------------------------------------------------------*/
+/* Top level routine for writing LATEX output. */
+/*----------------------------------------------------------------------*/
+
+void TopDoLatex()
+{
+ FILE *f;
+ float psscale, outscale;
+ int tx, ty, width, height;
+ polyptr framebox;
+ XPoint origin;
+ Boolean checklatex = FALSE;
+ char filename[100], extend[10], *dotptr;
+
+ UDoLatex(areawin->topinstance, 0, NULL, 1.0, 1.0, 0, 0, &checklatex);
+
+ if (checklatex == FALSE) return; /* No LaTeX labels to write */
+
+ /* Handle cases where the file might have a ".eps" extension. */
+ /* Thanks to Graham Sheward for pointing this out. */
+
+ if (xobjs.pagelist[areawin->page]->filename)
+ sprintf(filename, "%s", xobjs.pagelist[areawin->page]->filename);
+ else
+ sprintf(filename, "%s",
+ xobjs.pagelist[areawin->page]->pageinst->thisobject->name);
+
+ if ((dotptr = strchr(filename + strlen(filename) - 4, '.')) == NULL) {
+ dotptr = filename + strlen(filename);
+ sprintf(dotptr, ".ps");
+ }
+ strcpy(extend, dotptr);
+ strcpy(dotptr, ".tex");
+
+ f = fopen(filename, "w");
+
+ *dotptr = '\0';
+
+ fprintf(f, "%% XCircuit output \"%s.tex\" for LaTeX input from %s%s\n",
+ filename, filename, extend);
+ fprintf(f, "\\def\\putbox#1#2#3#4{\\makebox[0in][l]{\\makebox[#1][l]{}"
+ "\\raisebox{\\baselineskip}[0in][0in]"
+ "{\\raisebox{#2}[0in][0in]{\\scalebox{#3}{#4}}}}}\n");
+ fprintf(f, "\\def\\rightbox#1{\\makebox[0in][r]{#1}}\n");
+ fprintf(f, "\\def\\centbox#1{\\makebox[0in]{#1}}\n");
+ fprintf(f, "\\def\\topbox#1{\\raisebox{-0.60\\baselineskip}[0in][0in]{#1}}\n");
+ fprintf(f, "\\def\\midbox#1{\\raisebox{-0.20\\baselineskip}[0in][0in]{#1}}\n");
+
+ /* Modified to use \scalebox and \parbox by Alex Tercete, June 2008 */
+
+ // fprintf(f, "\\begin{center}\n");
+
+ outscale = xobjs.pagelist[areawin->page]->outscale;
+ psscale = getpsscale(outscale, areawin->page);
+
+ width = toplevelwidth(areawin->topinstance, &origin.x);
+ height = toplevelheight(areawin->topinstance, &origin.y);
+
+ /* Added 10/19/10: If there is a specified bounding box, let it */
+ /* determine the figure origin; otherwise, the labels will be */
+ /* mismatched to the bounding box. */
+
+ if ((framebox = checkforbbox(topobject)) != NULL) {
+ int i, maxx, maxy;
+
+ origin.x = maxx = framebox->points[0].x;
+ origin.y = maxy = framebox->points[0].y;
+ for (i = 1; i < framebox->number; i++) {
+ if (framebox->points[i].x < origin.x) origin.x = framebox->points[i].x;
+ if (framebox->points[i].x > maxx) maxx = framebox->points[i].x;
+ if (framebox->points[i].y < origin.y) origin.y = framebox->points[i].y;
+ if (framebox->points[i].y > maxy) maxy = framebox->points[i].y;
+ }
+ origin.x -= ((width - maxx + origin.x) / 2);
+ origin.y -= ((height - maxy + origin.y) / 2);
+ }
+
+ tx = (int)(72 / psscale) - origin.x,
+ ty = (int)(72 / psscale) - origin.y;
+
+ fprintf(f, " \\scalebox{%g}{\n", outscale);
+ fprintf(f, " \\normalsize\n");
+ fprintf(f, " \\parbox{%gin}{\n", (((float)width * psscale) / 72.0) / outscale);
+ fprintf(f, " \\includegraphics[scale=%g]{%s}\\\\\n", 1.0 / outscale,
+ filename);
+ fprintf(f, " %% translate x=%d y=%d scale %3.2f\n", tx, ty, psscale);
+
+ UPushCTM(); /* Save current state */
+ UResetCTM(DCTM); /* Set to identity matrix */
+ UDoLatex(areawin->topinstance, 0, f, psscale, outscale, tx, ty, NULL);
+ UPopCTM(); /* Restore state */
+
+ fprintf(f, " } %% close \'parbox\'\n");
+ fprintf(f, " } %% close \'scalebox\'\n");
+ fprintf(f, " \\vspace{-\\baselineskip} %% this is not"
+ " necessary, but looks better\n");
+ // fprintf(f, "\\end{center}\n");
+ fclose(f);
+
+ Wprintf("Wrote auxiliary file %s.tex", filename);
+}
+
diff --git a/graphic.c b/graphic.c
new file mode 100644
index 0000000..38c54a3
--- /dev/null
+++ b/graphic.c
@@ -0,0 +1,580 @@
+/*----------------------------------------------------------------------*/
+/* graphic.c --- xcircuit routines handling rendered graphic elements */
+/* Copyright (c) 2005 Tim Edwards, MultiGiG, Inc. */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 7/11/05 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef OPENGL
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif /* OPENGL */
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern colorindex *colorlist;
+extern int number_colors;
+
+/*----------------------------------------------------------------------*/
+/* Recursive search for graphic images in an object. */
+/* Updates list "glist" when any image is found in an object or its */
+/* descendents. */
+/*----------------------------------------------------------------------*/
+
+void count_graphics(objectptr thisobj, short *glist)
+{
+ genericptr *ge;
+ graphicptr gp;
+ Imagedata *iptr;
+ int i;
+
+ for (ge = thisobj->plist; ge < thisobj->plist + thisobj->parts; ge++) {
+ if (IS_GRAPHIC(*ge)) {
+ gp = TOGRAPHIC(ge);
+ for (i = 0; i < xobjs.images; i++) {
+ iptr = xobjs.imagelist + i;
+ if (iptr->image == gp->source) {
+ glist[i]++;
+ }
+ }
+ }
+ else if (IS_OBJINST(*ge)) {
+ count_graphics(TOOBJINST(ge)->thisobject, glist);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Given a list of pages, return a list of indices into the graphics */
+/* buffer area of each graphic used on any of the indicated pages. */
+/* The returned list is allocated and it is the responsibility of the */
+/* calling routine to free it. */
+/*----------------------------------------------------------------------*/
+
+short *collect_graphics(short *pagelist)
+{
+ short *glist;
+ int i;
+
+ glist = (short *)malloc(xobjs.images * sizeof(short));
+
+ for (i = 0; i < xobjs.images; i++) glist[i] = 0;
+
+ for (i = 0; i < xobjs.pages; i++)
+ if (pagelist[i] > 0)
+ count_graphics(xobjs.pagelist[i]->pageinst->thisobject, glist);
+
+ return glist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate the target view of the indicated graphic image, combining */
+/* the image's scale and rotation and the zoom factor of the current */
+/* view. */
+/* */
+/* If the graphic is at the wrong scale or rotation but is not redrawn */
+/* because it is outside the screen viewing area, return FALSE. */
+/* Otherwise, return TRUE. */
+/*----------------------------------------------------------------------*/
+
+Boolean transform_graphic(graphicptr gp)
+{
+ int width, height, twidth, theight, rotation;
+ float scale, tscale;
+ double cosr, sinr;
+ int x, y, c, s, hw, hh, thw, thh, xorig, yorig, crot, xc, yc;
+ int screen = DefaultScreen(dpy);
+ static GC cmgc = (GC)NULL;
+
+ tscale = UTopScale();
+ scale = gp->scale * tscale;
+ rotation = gp->rotation + UTopRotation();
+
+ if (rotation >= 360) rotation -= 360;
+ else if (rotation < 0) rotation += 360;
+
+ /* Check if the top-level rotation and scale match the */
+ /* saved target image. If so, then we're done. */
+ if ((rotation == gp->trot) && (scale == gp->tscale)) return TRUE;
+
+ cosr = cos(RADFAC * rotation);
+ sinr = sin(RADFAC * rotation);
+ c = (int)(8192 * cosr / scale);
+ s = (int)(8192 * sinr / scale);
+
+ /* Determine the necessary width and height of the pixmap */
+ /* that fits the rotated and scaled image. */
+
+ crot = rotation;
+ if (crot > 90 && crot < 180) crot = 180 - crot;
+ if (crot > 270 && crot < 360) crot = 360 - crot;
+ cosr = cos(RADFAC * crot);
+ sinr = sin(RADFAC * crot);
+ width = gp->source->width * scale;
+ height = gp->source->height * scale;
+
+ twidth = (int)(fabs(width * cosr + height * sinr));
+ theight = (int)(fabs(width * sinr + height * cosr));
+ if (twidth & 1) twidth++;
+ if (theight & 1) theight++;
+
+ /* Check whether this instance is going to be off-screen, */
+ /* to avoid excessive computation. */
+
+ UTopOffset(&xc, &yc);
+ xc += (int)((float)gp->position.x * tscale);
+ yc = areawin->height - yc;
+ yc += (int)((float)gp->position.y * tscale);
+
+ if (xc - (twidth >> 1) > areawin->width) return FALSE;
+ if (xc + (twidth >> 1) < 0) return FALSE;
+ if (yc - (theight >> 1) > areawin->height) return FALSE;
+ if (yc + (theight >> 1) < 0) return FALSE;
+
+ /* Generate the new target image */
+ if (gp->target != NULL) {
+ if (gp->target->data != NULL) {
+ /* Free data first, because we used our own malloc() */
+ free(gp->target->data);
+ gp->target->data = NULL;
+ }
+ XDestroyImage(gp->target);
+ }
+ if (gp->clipmask != (Pixmap)NULL) XFreePixmap(dpy, gp->clipmask);
+
+ gp->target = XCreateImage(dpy, DefaultVisual(dpy, screen),
+ DefaultDepth(dpy, screen), ZPixmap,
+ 0, 0, twidth, theight, 8, 0);
+ gp->target->data = (char *)malloc(theight * gp->target->bytes_per_line);
+
+ if (gp->target->data == (char *)NULL) {
+ XDestroyImage(gp->target);
+ gp->target = (XImage *)NULL;
+ gp->clipmask = (Pixmap)NULL;
+ return FALSE;
+ }
+
+ if (rotation != 0) {
+ gp->clipmask = XCreatePixmap(dpy, areawin->window, twidth, theight, 1);
+ if (cmgc == (GC)NULL) {
+ XGCValues values;
+ values.foreground = 0;
+ values.background = 0;
+ cmgc = XCreateGC(dpy, gp->clipmask, GCForeground | GCBackground, &values);
+ }
+ XSetForeground(dpy, cmgc, 1);
+ XFillRectangle(dpy, gp->clipmask, cmgc, 0, 0, twidth, theight);
+ XSetForeground(dpy, cmgc, 0);
+ }
+ else
+ gp->clipmask = (Pixmap)NULL;
+
+ hh = gp->source->height >> 1;
+ hw = gp->source->width >> 1;
+ thh = theight >> 1;
+ thw = twidth >> 1;
+ for (y = -thh; y < thh; y++) {
+ for (x = -thw; x < thw; x++) {
+ xorig = ((x * c + y * s) >> 13) + hw;
+ yorig = ((-x * s + y * c) >> 13) + hh;
+
+ if ((xorig >= 0) && (yorig >= 0) &&
+ (xorig < gp->source->width) && (yorig < gp->source->height))
+ XPutPixel(gp->target, x + thw, y + thh,
+ XGetPixel(gp->source, xorig, yorig));
+ else if (gp->clipmask)
+ XDrawPoint(dpy, gp->clipmask, cmgc, x + thw, y + thh);
+ }
+ }
+ gp->tscale = scale;
+ gp->trot = rotation;
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw a graphic image by copying from the image to the window. */
+/* Image is centered on the center point of the graphic image. */
+/*----------------------------------------------------------------------*/
+
+void UDrawGraphic(graphicptr gp)
+{
+ XPoint ppt;
+
+ /* transform to current scale and rotation, if necessary */
+ if (transform_graphic(gp) == FALSE) return; /* Graphic off-screen */
+
+ /* transform to current position */
+ UTransformbyCTM(DCTM, &(gp->position), &ppt, 1);
+
+ /* user_to_window(gp->position, &ppt); */
+
+ ppt.x -= (gp->target->width >> 1);
+ ppt.y -= (gp->target->height >> 1);
+
+ if (gp->clipmask != (Pixmap)NULL) {
+ if (areawin->clipped > 0) {
+ /* Clipmask areawin->clipmask already applied to window. */
+ /* Modify existing clipmask with the graphic's. */
+ XSetFunction(dpy, areawin->cmgc, GXand);
+ XCopyArea(dpy, gp->clipmask, areawin->clipmask, areawin->cmgc,
+ 0, 0, gp->target->width, gp->target->height, ppt.x, ppt.y);
+ XSetClipMask(dpy, areawin->gc, areawin->clipmask);
+ XSetFunction(dpy, areawin->cmgc, GXcopy);
+ }
+ else {
+ XSetClipOrigin(dpy, areawin->gc, ppt.x, ppt.y);
+ XSetClipMask(dpy, areawin->gc, gp->clipmask);
+ }
+ }
+
+ XPutImage(dpy, areawin->window, areawin->gc,
+ gp->target, 0, 0, ppt.x, ppt.y, gp->target->width,
+ gp->target->height);
+
+ if (gp->clipmask != (Pixmap)NULL) {
+ if (areawin->clipped <= 0) {
+ XSetClipMask(dpy, areawin->gc, None);
+ XSetClipOrigin(dpy, areawin->gc, 0, 0);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Allocate space for a new graphic source image of size width x height */
+/*----------------------------------------------------------------------*/
+
+Imagedata *addnewimage(char *name, int width, int height)
+{
+ Imagedata *iptr;
+ int screen = DefaultScreen(dpy);
+
+ /* Create the image and store in the global list of images */
+
+ xobjs.images++;
+ if (xobjs.imagelist)
+ xobjs.imagelist = (Imagedata *)realloc(xobjs.imagelist,
+ xobjs.images * sizeof(Imagedata));
+ else
+ xobjs.imagelist = (Imagedata *)malloc(sizeof(Imagedata));
+
+ /* Save the image source in a file */
+ iptr = xobjs.imagelist + xobjs.images - 1;
+ if (name)
+ iptr->filename = strdup(name);
+ else
+ iptr->filename = NULL; /* must be filled in later! */
+ iptr->refcount = 0; /* no calls yet */
+ iptr->image = XCreateImage(dpy, DefaultVisual(dpy, screen),
+ DefaultDepth(dpy, screen), ZPixmap, 0, NULL,
+ width, height, 8, 0);
+ iptr->image->data = (char *)malloc(height * iptr->image->bytes_per_line);
+
+ return iptr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a new graphic image from a PPM file, and position it at the */
+/* indicated (px, py) coordinate in user space. */
+/* */
+/* This should be expanded to incorporate more PPM formats. Also, it */
+/* needs to be combined with the render.c routines to transform */
+/* PostScript graphics into an internal XImage for faster rendering. */
+/*----------------------------------------------------------------------*/
+
+graphicptr new_graphic(objinstptr destinst, char *filename, int px, int py)
+{
+ graphicptr *gp;
+ objectptr destobject;
+ objinstptr locdestinst;
+ Imagedata *iptr;
+ FILE *fg;
+ int nr, width, height, imax, x, y, i; /* nf, (jdk) */
+ char id[5], c, buf[128];
+ union {
+ u_char b[4];
+ u_long i;
+ } pixel;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ /* Check the existing list of images. If there is a match, */
+ /* re-use the source; don't load the file again. */
+
+ for (i = 0; i < xobjs.images; i++) {
+ iptr = xobjs.imagelist + i;
+ if (!strcmp(iptr->filename, filename)) {
+ break;
+ }
+ }
+ if (i == xobjs.images) {
+
+ fg = fopen(filename, "r");
+ if (fg == NULL) return NULL;
+
+ /* This ONLY handles binary ppm files with max data = 255 */
+
+ while (1) {
+ nr = fscanf(fg, " %s", buf);
+ if (nr <= 0) return NULL;
+ if (buf[0] != '#') {
+ if (sscanf(buf, "%s", id) <= 0)
+ return NULL;
+ break;
+ }
+ else fgets(buf, 127, fg);
+ }
+ if ((nr <= 0) || strncmp(id, "P6", 2)) return NULL;
+
+ while (1) {
+ nr = fscanf(fg, " %s", buf);
+ if (nr <= 0) return NULL;
+ if (buf[0] != '#') {
+ if (sscanf(buf, "%d", &width) <= 0)
+ return NULL;
+ break;
+ }
+ else fgets(buf, 127, fg);
+ }
+ if (width <= 0) return NULL;
+
+ while (1) {
+ nr = fscanf(fg, " %s", buf);
+ if (nr <= 0) return NULL;
+ if (buf[0] != '#') {
+ if (sscanf(buf, "%d", &height) <= 0)
+ return NULL;
+ break;
+ }
+ else fgets(buf, 127, fg);
+ }
+ if (height <= 0) return NULL;
+
+ while (1) {
+ nr = fscanf(fg, " %s", buf);
+ if (nr <= 0) return NULL;
+ if (buf[0] != '#') {
+ if (sscanf(buf, "%d", &imax) <= 0)
+ return NULL;
+ break;
+ }
+ else fgets(buf, 127, fg);
+ }
+ if (imax != 255) return NULL;
+
+ while (1) {
+ fread(&c, 1, 1, fg);
+ if (c == '\n') break;
+ else if (c == '\0') return NULL;
+ }
+
+ iptr = addnewimage(filename, width, height);
+
+ /* Read the image data from the PPM file */
+
+ pixel.b[3] = 0;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++) {
+ fread(&pixel.b[2], 1, 1, fg);
+ fread(&pixel.b[1], 1, 1, fg);
+ fread(&pixel.b[0], 1, 1, fg);
+ XPutPixel(iptr->image, x, y, pixel.i);
+ }
+ }
+
+ iptr->refcount++;
+ NEW_GRAPHIC(gp, destobject);
+
+ (*gp)->scale = 1.0;
+ (*gp)->position.x = px;
+ (*gp)->position.y = py;
+ (*gp)->rotation = 0;
+ (*gp)->color = DEFAULTCOLOR;
+ (*gp)->passed = NULL;
+ (*gp)->clipmask = (Pixmap)NULL;
+ (*gp)->source = iptr->image;
+ (*gp)->target = NULL;
+ (*gp)->trot = 0;
+ (*gp)->tscale = 0;
+
+ calcbboxvalues(locdestinst, (genericptr *)gp);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+
+ register_for_undo(XCF_Graphic, UNDO_DONE, areawin->topinstance, *gp);
+
+ return *gp;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a gradient field graphic */
+/* For now, gradient field is linear white-to-black size 100x100. */
+/*----------------------------------------------------------------------*/
+
+graphicptr gradient_field(objinstptr destinst, int px, int py, int c1, int c2)
+{
+ graphicptr *gp;
+ objectptr destobject;
+ objinstptr locdestinst;
+ Imagedata *iptr;
+ int width, height, imax, x, y, i;
+ int r, g, b, rd, gd, bd;
+ char id[11];
+ union {
+ u_char b[4];
+ u_long i;
+ } pixel;
+
+ locdestinst = (destinst == NULL) ? areawin->topinstance : destinst;
+ destobject = locdestinst->thisobject;
+
+ if (c1 < 0) c1 = 0;
+ if (c1 >= number_colors) c1 = 1;
+ if (c2 < 0) c2 = 0;
+ if (c2 >= number_colors) c2 = 1;
+
+ /* Create name "gradientXX" */
+
+ y = 0;
+ for (i = 0; i < xobjs.images; i++) {
+ iptr = xobjs.imagelist + i;
+ if (!strncmp(iptr->filename, "gradient", 8)) {
+ if (sscanf(iptr->filename + 8, "%2d", &x) == 1)
+ if (x >= y)
+ y = x + 1;
+ }
+ }
+ sprintf(id, "gradient%02d", y);
+
+ width = height = 100; /* Fixed size, at least for now */
+
+ iptr = addnewimage(id, width, height);
+
+ r = (colorlist[c1].color.red >> 8);
+ g = (colorlist[c1].color.green >> 8);
+ b = (colorlist[c1].color.blue >> 8);
+
+ rd = (colorlist[c2].color.red >> 8) - r;
+ gd = (colorlist[c2].color.green >> 8) - g;
+ bd = (colorlist[c2].color.blue >> 8) - b;
+
+ pixel.b[3] = 0;
+ for (y = 0; y < height; y++) {
+ pixel.b[2] = r + ((y * rd) / (height - 1));
+ pixel.b[1] = g + ((y * gd) / (height - 1));
+ pixel.b[0] = b + ((y * bd) / (height - 1));
+ for (x = 0; x < width; x++) {
+ XPutPixel(iptr->image, x, y, pixel.i);
+ }
+ }
+
+ iptr->refcount++;
+ NEW_GRAPHIC(gp, destobject);
+
+ (*gp)->scale = 1.0;
+ (*gp)->position.x = px;
+ (*gp)->position.y = py;
+ (*gp)->rotation = 0;
+ (*gp)->color = DEFAULTCOLOR;
+ (*gp)->passed = NULL;
+ (*gp)->clipmask = (Pixmap)NULL;
+ (*gp)->source = iptr->image;
+ (*gp)->target = NULL;
+ (*gp)->trot = 0;
+ (*gp)->tscale = 0;
+
+ calcbboxvalues(locdestinst, (genericptr *)gp);
+ updatepagebounds(destobject);
+ incr_changes(destobject);
+
+ register_for_undo(XCF_Graphic, UNDO_DONE, areawin->topinstance, *gp);
+
+ return *gp;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* Free memory associated with the XImage structure for a graphic. */
+/*----------------------------------------------------------------------*/
+
+void freeimage(XImage *source)
+{
+ int i, j;
+ Imagedata *iptr;
+
+ for (i = 0; i < xobjs.images; i++) {
+ iptr = xobjs.imagelist + i;
+ if (iptr->image == source) {
+ iptr->refcount--;
+ if (iptr->refcount <= 0) {
+ if (iptr->image->data != NULL) {
+ /* Free data first, because we used our own malloc() */
+ free(iptr->image->data);
+ iptr->image->data = NULL;
+ }
+ XDestroyImage(iptr->image);
+ free(iptr->filename);
+
+ /* Remove this from the list of images */
+
+ for (j = i; j < xobjs.images - 1; j++)
+ *(xobjs.imagelist + j) = *(xobjs.imagelist + j + 1);
+ xobjs.images--;
+ }
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated by a graphicptr structure. */
+/*----------------------------------------------------------------------*/
+
+void freegraphic(graphicptr gp)
+{
+ if (gp->target != NULL) {
+ if (gp->target->data != NULL) {
+ /* Free data first, because we used our own malloc() */
+ free(gp->target->data);
+ gp->target->data = NULL;
+ }
+ XDestroyImage(gp->target);
+ }
+ if (gp->clipmask != (Pixmap)NULL) XFreePixmap(dpy, gp->clipmask);
+ freeimage(gp->source);
+}
+
+/*----------------------------------------------------------------------*/
diff --git a/help.c b/help.c
new file mode 100644
index 0000000..f392a79
--- /dev/null
+++ b/help.c
@@ -0,0 +1,514 @@
+/*----------------------------------------------------------------------*/
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Spun off from xcircuit.c 10/4/98 */
+/* Functionality will not be expanded in the Xt version. All new */
+/* capabilities will be developed in the TCL version of help. */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#include "Xw/Form.h"
+#include "Xw/WorkSpace.h"
+#include "Xw/MenuBtn.h"
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+#ifndef TCL_WRAPPER
+
+extern Display *dpy;
+extern GC hgc;
+extern XCWindowData *areawin;
+extern ApplicationData appdata;
+extern int *appcolors;
+extern xcWidget top;
+extern short popups;
+extern xcWidget menuwidgets[];
+extern char *function_names[NUM_FUNCTIONS];
+
+Pixmap helppix = (Pixmap)NULL; /* For help window */
+Dimension helpwidth, helpheight, hheight;
+int helptop;
+short help_up;
+
+/*-----------------------------------------*/
+/* Print help list into a pixmap */
+/* Return width and height of map through */
+/* global variables helpwidth, helpheight. */
+/*-----------------------------------------*/
+
+typedef struct {
+ int function;
+ char *text;
+} helpstruct;
+
+void printhelppix()
+{
+ static char *helptitle = "Macro Key Binding Summary:";
+ static helpstruct helptext[] = {
+ { XCF_Finish, "Finish"},
+ { XCF_Cancel, "Cancel"},
+ { XCF_Zoom_In, "Zoom in 3/2"},
+ { XCF_Zoom_Out, "Zoom out 3/2"},
+ { XCF_Pan, "Pan (various modes)"},
+ { XCF_Double_Snap, "Double snap-to spacing"},
+ { XCF_Halve_Snap, "Halve snap-to spacing"},
+ { XCF_Next_Library, "Go To Next Library"},
+ { XCF_Library_Pop, "Return from Library"},
+ { XCF_Push, "Push object"},
+ { XCF_Pop, "Pop object"},
+ { XCF_Redraw, "Refresh screen"},
+ { XCF_Page, "Go To Page"},
+ { XCF_Write, "Popup Output dialog"},
+#ifdef HAVE_PYTHON
+ { XCF_Prompt, "Python Command entry"},
+#else
+ { XCF_Prompt, "Command entry"},
+#endif
+ { XCF_Exit, "Quit XCircuit"},
+ { XCF_SPACER, NULL},
+ { XCF_Wire, "Begin Polygon"},
+ { XCF_Box, "Begin Box"},
+ { XCF_Arc, "Begin Arc"},
+ { XCF_Text, "Begin Text"},
+ { XCF_Spline, "Begin Spline"},
+ { XCF_Select_Save, "Make object"},
+ { XCF_Virtual, "Make library instance"},
+ { XCF_Join, "Join elements (make path)"},
+ { XCF_Unjoin, "Un-join elements"},
+ { XCF_Dot, "Place a dot"},
+ { XCF_SPACER, NULL},
+ { XCF_Delete, "Delete"},
+ { XCF_Undo, "Undo"},
+ { XCF_Redo, "Redo"},
+ { XCF_Select, "Select"},
+ { XCF_Unselect, "Deselect"},
+ { XCF_Copy, "Copy"},
+ { XCF_Edit, "Edit"},
+ { XCF_SPACER, NULL},
+ { XCF_Rotate, "Rotate"},
+ { XCF_Flip_X, "Flip horizontally"},
+ { XCF_Flip_Y, "Flip vertically"},
+ { XCF_Snap, "Snap to grid"},
+ { XCF_Attach, "Attach to"},
+ { XCF_Dashed, "Dashed line style"},
+ { XCF_Dotted, "Dotted line style"},
+ { XCF_Solid, "Solid line style"},
+ { XCF_SPACER, NULL},
+ { XCF_Justify, "Text Justification"},
+ { XCF_Superscript, "Text Superscript"},
+ { XCF_Subscript, "Text Subscript"},
+ { XCF_Font, "Toggle text font"},
+ { XCF_Boldfont, "Begin Bold text"},
+ { XCF_Italicfont, "Begin Italic text"},
+ { XCF_Normalfont, "Resume normal text"},
+ { XCF_ISO_Encoding, "Begin Latin-1 encoding"},
+ { XCF_Overline, "Begin text overline"},
+ { XCF_Underline, "Begin text underline"},
+ { XCF_Parameter, "Insert parameter"},
+ { XCF_Halfspace, "Insert half-space"},
+ { XCF_Quarterspace, "Insert quarter-space"},
+ { XCF_Linebreak, "Insert return character"},
+ { XCF_Special, "Insert special character"},
+ { XCF_TabStop, "Set tab stop"},
+ { XCF_TabForward, "Forward tab"},
+ { XCF_TabBackward, "Backward tab"},
+ { XCF_Text_Home, "Go to label beginning"},
+ { XCF_Text_End, "Go to label end"},
+ { XCF_Text_Left, "Move left one position"},
+ { XCF_Text_Right, "Move right one position"},
+ { XCF_Text_Up, "Move up one line"},
+ { XCF_Text_Down, "Move down one line"},
+ { XCF_Text_Delete, "Delete character(s)"},
+ { XCF_Text_Return, "End text edit"},
+ { XCF_Text_Split, "Split label at cursor"},
+ { XCF_SPACER, NULL},
+ { XCF_Edit_Next, "Edit: next position"},
+ { XCF_Edit_Delete, "Edit: delete point"},
+ { XCF_Edit_Insert, "Edit: insert point"},
+ { XCF_Edit_Param, "Edit: insert parameter"},
+ { XCF_SPACER, NULL},
+ { XCF_Library_Edit, "Library: name edit"},
+ { XCF_Library_Move, "Library: move object/page"},
+ { XCF_Library_Delete, "Library: object delete"},
+ { XCF_Library_Hide, "Library: hide object"},
+ { XCF_Library_Duplicate, "Library: copy object"},
+ { XCF_Library_Virtual, "Library: copy instance"},
+ { XCF_SPACER, NULL},
+ { XCF_Pin_Label, "Make Pin Label"},
+ { XCF_Pin_Global, "Make Global Pin"},
+ { XCF_Info_Label, "Make Info Label"},
+ { XCF_Swap, "Go to Symbol or Schematic"},
+ { XCF_Connectivity, "See net connectivity"},
+ { XCF_Sim, "Generate Sim netlist"},
+ { XCF_SPICE, "Generate SPICE netlist"},
+ { XCF_SPICEflat, "Generate flattened SPICE"},
+ { XCF_PCB, "Generate PCB netlist"},
+ { XCF_ENDDATA, NULL},
+ };
+
+ XGCValues values;
+ Window hwin = DefaultRootWindow(dpy);
+ Dimension htmp, vtmp, lineheight, mwidth;
+ int i, j, t1, t2, dum, numlines;
+ XCharStruct csdum;
+ char *bindings, *bptr, *cptr;
+
+ if (hwin == 0) return;
+
+ /* Set up the GC for drawing to the help window pixmap */
+
+ if (hgc == NULL) {
+ values.foreground = FOREGROUND;
+ values.background = BACKGROUND;
+ values.graphics_exposures = False;
+ values.font = appdata.helpfont->fid;
+ hgc = XCreateGC(dpy, hwin, GCForeground | GCBackground | GCFont
+ | GCGraphicsExposures, &values);
+ }
+
+ /* Determine the dimensions of the help text */
+
+ mwidth = helpwidth = lineheight = numlines = 0;
+
+ for (i = 0; helptext[i].function != XCF_ENDDATA; i++) {
+ if (helptext[i].function == XCF_SPACER) {
+ numlines++;
+ continue;
+ }
+
+ htmp = XTextWidth(appdata.helpfont, helptext[i].text, strlen(helptext[i].text));
+ if (htmp > mwidth) mwidth = htmp;
+
+ XTextExtents(appdata.helpfont, helptext[i].text, strlen(helptext[i].text),
+ &dum, &t1, &t2, &csdum);
+ vtmp = t1 + t2 + 5;
+ if (vtmp > lineheight) lineheight = vtmp;
+
+ bindings = function_binding_to_string(0, helptext[i].function);
+
+ /* Limit list to three key bindings per line */
+ bptr = bindings;
+ while (bptr != NULL) {
+ cptr = bptr;
+ for (j = 0; j < 3; j++) {
+ cptr = strchr(cptr + 1, ',');
+ if (cptr == NULL) break;
+ }
+ if (cptr != NULL) *(++cptr) = '\0';
+
+ htmp = XTextWidth(appdata.helpfont, bptr, strlen(bptr));
+ if (htmp > helpwidth) helpwidth = htmp;
+
+ XTextExtents(appdata.helpfont, bptr, strlen(bptr),
+ &dum, &t1, &t2, &csdum);
+ vtmp = t1 + t2 + 5;
+ if (vtmp > lineheight) lineheight = vtmp;
+ numlines++;
+
+ if (cptr == NULL) break;
+ bptr = cptr + 1;
+ }
+ free(bindings);
+ }
+ XTextExtents(appdata.helpfont, helptitle, strlen(helptitle), &dum, &t1,
+ &t2, &csdum);
+ t1 += t2;
+ helpwidth += mwidth + 15;
+
+ helpheight = lineheight * numlines + 15 + t1; /* full height of help text */
+ if (helppix != (Pixmap)NULL) {
+ Wprintf("Error: Help window not cancelled?");
+ return;
+ }
+ helppix = XCreatePixmap(dpy, hwin, helpwidth, helpheight,
+ DefaultDepthOfScreen(DefaultScreenOfDisplay(dpy)));
+
+ XSetForeground(dpy, hgc, FOREGROUND);
+ XFillRectangle(dpy, helppix, hgc, 0, 0, helpwidth, helpheight);
+
+ XSetForeground(dpy, hgc, BACKGROUND);
+ XDrawString(dpy, helppix, hgc, (helpwidth - XTextWidth(appdata.helpfont,
+ helptitle, strlen(helptitle))) >> 1, t1 + 2, helptitle, strlen(helptitle));
+ vtmp = lineheight + 15;
+ for (i = 0; helptext[i].function != XCF_ENDDATA; i++) {
+ if (helptext[i].function == XCF_SPACER) {
+ vtmp += lineheight;
+ continue;
+ }
+ XDrawString(dpy, helppix, hgc, 7, vtmp, helptext[i].text,
+ strlen(helptext[i].text));
+ bindings = function_binding_to_string(0, helptext[i].function);
+ bptr = bindings;
+ while (bptr != NULL) {
+ cptr = bptr;
+ for (j = 0; j < 3; j++) {
+ cptr = strchr(cptr + 1, ',');
+ if (cptr == NULL) break;
+ }
+ if (cptr != NULL) *(++cptr) = '\0';
+ XDrawString(dpy, helppix, hgc, 7 + mwidth, vtmp, bptr, strlen(bptr));
+ vtmp += lineheight;
+ if (cptr == NULL) break;
+ bptr = cptr + 1;
+ }
+ free(bindings);
+ }
+ XSetForeground(dpy, hgc, AUXCOLOR);
+ XDrawLine(dpy, helppix, hgc, 0, t1 + 7, helpwidth, t1 + 7);
+}
+
+/*----------------------------------------------*/
+/* Create the help popup window (Xt version) */
+/*----------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void starthelp(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ Arg wargs[11];
+ xcWidget popup, cancelbutton, hspace, help2, hsb;
+ short n = 0;
+ popupstruct *okaystruct;
+ buttonsave *savebutton;
+ Dimension areawidth, bwidth, pheight;
+ Position xpos, ypos;
+ u_int xmax, ymax;
+
+ if (help_up) return; /* no multiple help windows */
+
+ /* for positioning the help window outside of the xcircuit */
+ /* window, get information about the display width and height */
+ /* and the xcircuit window. */
+
+ /* The "- 50" leaves space for the Windows-95-type title bar that */
+ /* runs across the bottom of the screen in some window managers */
+ /* (specifically, fvwm95 which is the default for RedHat Linux) */
+
+ xmax = DisplayWidth(dpy, DefaultScreen(dpy)) - 100;
+ ymax = DisplayHeight(dpy, DefaultScreen(dpy)) - 50;
+
+ XtnSetArg(XtNwidth, &areawidth);
+ XtGetValues(areawin->area, wargs, n); n = 0;
+ XtTranslateCoords(areawin->area, (Position) (areawidth + 10), -50,
+ &xpos, &ypos);
+
+ /* Always direct the call to the main menu button. */
+ button = OptionsHelpButton;
+
+ savebutton = getgeneric(button, starthelp, NULL);
+
+ /* Generate the pixmap and write the help text to it */
+
+ if (helppix == (Pixmap)NULL) printhelppix();
+
+ /* Use the pixmap size to size the help window */
+
+ if (xpos + helpwidth + SBARSIZE > xmax) xpos = xmax - helpwidth - SBARSIZE - 4;
+ if (ypos + helpheight > ymax) ypos = ymax - helpheight - 4;
+ if (ypos < 4) ypos = 4;
+
+ XtnSetArg(XtNx, xpos);
+ XtnSetArg(XtNy, ypos);
+ popup = XtCreatePopupShell("help", transientShellWidgetClass,
+ button, wargs, n); n = 0;
+ popups++;
+ help_up = True;
+ helptop = 0;
+
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNxResizable, False);
+ help2 = XtCreateManagedWidget("help2", XwformWidgetClass,
+ popup, wargs, n); n = 0;
+
+ XtnSetArg(XtNfont, appdata.xcfont);
+ cancelbutton = XtCreateManagedWidget("Dismiss", XwmenuButtonWidgetClass,
+ help2, wargs, n); n = 0;
+
+ XtnSetArg(XtNwidth, helpwidth);
+ XtnSetArg(XtNheight, areawin->height);
+ XtnSetArg(XtNyRefWidget, cancelbutton);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyAttachBottom, True);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNxAttachRight, False);
+ hspace = XtCreateManagedWidget("HSpace", XwworkSpaceWidgetClass,
+ help2, wargs, n); n = 0;
+
+ /* Create scrollbar */
+ XtnSetArg(XtNwidth, SBARSIZE);
+ XtnSetArg(XtNxRefWidget, hspace);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNyRefWidget, cancelbutton);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNyAttachBottom, True);
+ XtnSetArg(XtNborderWidth, 1);
+ hsb = XtCreateManagedWidget("HSB", XwworkSpaceWidgetClass,
+ help2, wargs, n); n = 0;
+
+ okaystruct = (popupstruct *) malloc(sizeof(popupstruct));
+ okaystruct->buttonptr = savebutton;
+ okaystruct->popup = popup;
+ okaystruct->filter = NULL;
+
+ XtPopup(popup, XtGrabNone);
+
+ /* reposition the "Dismiss" button to center */
+
+ XtSetArg(wargs[0], XtNwidth, &bwidth);
+ XtGetValues(cancelbutton, wargs, 1);
+ XtnSetArg(XtNx, ((helpwidth - bwidth) >> 1));
+ XtSetValues(cancelbutton, wargs, n); n = 0;
+
+ XtSetArg(wargs[0], XtNheight, &pheight);
+ XtGetValues(help2, wargs, 1);
+
+ if (pheight > (ymax - 8)) {
+ XtnSetArg(XtNheight, ymax - 8);
+ XtSetValues(help2, wargs, n); n = 0;
+ }
+
+ XtAddEventHandler(hsb, ButtonMotionMask | ButtonPressMask, False,
+ (XtEventHandler)simplescroll, hspace);
+
+ /* Expose and End callbacks */
+
+ XtAddCallback(cancelbutton, XtNselect, (XtCallbackProc)destroypopup, okaystruct);
+ XtAddCallback(hspace, XtNexpose, (XtCallbackProc)exposehelp, NULL);
+ XtAddCallback(hsb, XtNexpose, (XtCallbackProc)showhsb, NULL);
+}
+
+/*----------------------------------------------*/
+/* Very simple scroll mechanism (grab-and-pan) */
+/*----------------------------------------------*/
+
+void simplescroll(xcWidget hsb, xcWidget hspace, XMotionEvent *event)
+{
+ Dimension oldtop = helptop;
+
+ helptop = (((int)(event->y) * helpheight) / hheight) - (hheight / 2);
+
+ if (helptop < 0) helptop = 0;
+ else if (helptop > helpheight - hheight) helptop = helpheight - hheight;
+
+ if (helptop != oldtop) {
+ showhsb(hsb, NULL, NULL);
+ printhelp(hspace);
+ }
+}
+
+/*----------------------------------------------*/
+/* Expose callback for the help scrollbar */
+/*----------------------------------------------*/
+
+void showhsb(xcWidget hsb, caddr_t clientdata, caddr_t calldata)
+{
+ Window hwin = xcWindow(hsb);
+ Dimension sheight;
+ int pstart, pheight;
+ short n = 0;
+
+ if (helppix == (Pixmap)NULL) printhelppix();
+ if (helpheight == 0) helpheight = 1;
+
+ pstart = (helptop * hheight) / helpheight;
+ pheight = (hheight * hheight) / helpheight;
+
+ if (pheight < 3) pheight = 3;
+
+ XClearArea(dpy, hwin, 0, 0, SBARSIZE, pstart, False);
+ XClearArea(dpy, hwin, 0, pstart + pheight, SBARSIZE,
+ hheight - (pstart + pheight), False);
+
+ XSetForeground(dpy, hgc, BARCOLOR);
+ XFillRectangle(dpy, hwin, hgc, 0, pstart, SBARSIZE, pheight);
+}
+
+/*----------------------------------------------*/
+/* Expose callback for the help window */
+/*----------------------------------------------*/
+
+void exposehelp(xcWidget hspace, caddr_t clientdata, caddr_t calldata)
+{
+ Arg wargs[1];
+
+ XtSetArg(wargs[0], XtNheight, &hheight);
+ XtGetValues(hspace, wargs, 1);
+
+ if (helppix == (Pixmap)NULL) printhelppix();
+ if (hheight < 1) hheight = 1;
+
+ printhelp(hspace);
+}
+
+/*----------------------------------------------*/
+/* Expose callback for the help window */
+/*----------------------------------------------*/
+
+void printhelp(xcWidget hspace)
+{
+ Window hwin = xcWindow(hspace);
+ XEvent discard;
+
+ /* Draw the pixmap to the window */
+
+ XCopyArea(dpy, helppix, hwin, hgc, 0, helptop - 5, helpwidth, helpheight,
+ 0, 0);
+
+ /* flush out multiple expose events */
+
+ while (XCheckWindowEvent(dpy, hwin, ExposureMask, &discard) == True);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* The TCL version assumes the existence of command "helpwindow". */
+/*----------------------------------------------------------------------*/
+
+#else
+
+void starthelp(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ Tcl_Eval(xcinterp, "catch xcircuit::helpwindow");
+}
+
+#endif /* !TCL_WRAPPER */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/keybindings.c b/keybindings.c
new file mode 100644
index 0000000..b77d703
--- /dev/null
+++ b/keybindings.c
@@ -0,0 +1,864 @@
+/*--------------------------------------------------------------*/
+/* keybindings.c: List of key bindings */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*--------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 2/27/01 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h> /* for tolower(), toupper() */
+#include <math.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#if !defined(XC_WIN32) || defined(TCL_WRAPPER)
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define XK_XKB_KEYS
+#include <X11/keysymdef.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototypes */
+/*----------------------------------------------------------------------*/
+
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------*/
+
+keybinding *keylist = NULL;
+
+extern Display *dpy;
+extern char _STR[150], _STR2[250];
+extern int pressmode;
+extern XCWindowData *areawin;
+
+/*----------------------------------------------------------------------*/
+/* Key modifiers (convenience definitions) */
+/* Use Mod5Mask for a "hold" ("press") definition. */
+/* Why Mod5Mask? Mod2Mask is used by fvwm2 for some obscure purpose, */
+/* so I went to the other end (Mod5Mask is just below Button1Mask). */
+/* Thanks to John Heil for reporting the problem and confirming the */
+/* Mod5Mask solution. */
+/*----------------------------------------------------------------------*/
+
+#define ALT (Mod1Mask << 16)
+#define CTRL (ControlMask << 16)
+#define CAPSLOCK (LockMask << 16)
+#define SHIFT (ShiftMask << 16)
+#define BUTTON1 (Button1Mask << 16)
+#define BUTTON2 (Button2Mask << 16)
+#define BUTTON3 (Button3Mask << 16)
+#define BUTTON4 (Button4Mask << 16)
+#define BUTTON5 (Button5Mask << 16)
+#define HOLD (Mod4Mask << 16)
+
+#define ALL_WINDOWS (xcWidget)NULL
+
+/*--------------------------------------------------------------*/
+/* This list declares all the functions which can be bound to */
+/* keys. It must match the order of the enumeration listed in */
+/* xcircuit.h! */
+/*--------------------------------------------------------------*/
+
+static char *function_names[NUM_FUNCTIONS + 1] = {
+ "Page", "Justify", "Superscript", "Subscript", "Normalscript",
+ "Nextfont", "Boldfont", "Italicfont", "Normalfont", "Underline",
+ "Overline", "ISO Encoding", "Halfspace", "Quarterspace",
+ "Special", "Tab Stop", "Tab Forward", "Tab Backward",
+ "Text Return", "Text Delete", "Text Right", "Text Left",
+ "Text Up", "Text Down", "Text Split",
+ "Text Home", "Text End", "Linebreak", "Parameter",
+ "Parameterize Point", "Change Style", "Delete Point", "Insert Point",
+ "Append Point", "Next Point", "Attach", "Next Library", "Library Directory",
+ "Library Move", "Library Copy", "Library Edit", "Library Delete",
+ "Library Duplicate", "Library Hide", "Library Virtual Copy",
+ "Page Directory", "Library Pop", "Virtual Copy",
+ "Help", "Redraw", "View", "Zoom In", "Zoom Out", "Pan",
+ "Double Snap", "Halve Snap", "Write", "Rotate", "Flip X",
+ "Flip Y", "Snap", "Snap To",
+ "Pop", "Push", "Delete", "Select", "Box", "Arc", "Text",
+ "Exchange", "Copy", "Move", "Join", "Unjoin", "Spline", "Edit",
+ "Undo", "Redo", "Select Save", "Unselect", "Dashed", "Dotted",
+ "Solid", "Prompt", "Dot", "Wire", "Cancel", "Nothing", "Exit",
+ "Netlist", "Swap", "Pin Label", "Pin Global", "Info Label", "Graphic",
+ "Select Box", "Connectivity", "Continue Element", "Finish Element",
+ "Continue Copy", "Finish Copy", "Finish", "Cancel Last", "Sim",
+ "SPICE", "PCB", "SPICE Flat", "Rescale", "Reorder", "Color",
+ "Margin Stop", "Text Delete Param",
+ NULL /* sentinel */
+};
+
+/*--------------------------------------------------------------*/
+/* Return TRUE if the indicated key (keysym + bit-shifted state)*/
+/* is bound to some function. */
+/*--------------------------------------------------------------*/
+
+Boolean ismacro(xcWidget window, int keywstate)
+{
+ keybinding *ksearch;
+
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding)
+ if (ksearch->window == ALL_WINDOWS || ksearch->window == window)
+ if (keywstate == ksearch->keywstate)
+ return True;
+
+ return False;
+}
+
+/*--------------------------------------------------------------*/
+/* Return the first key binding for the indicated function */
+/*--------------------------------------------------------------*/
+
+int firstbinding(xcWidget window, int function)
+{
+ keybinding *ksearch;
+ int keywstate = -1;
+
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ if (ksearch->function == function) {
+ if (ksearch->window == window)
+ return ksearch->keywstate;
+ else if (ksearch->window == ALL_WINDOWS)
+ keywstate = ksearch->keywstate;
+ }
+ }
+ return keywstate;
+}
+
+/*--------------------------------------------------------------*/
+/* Find the first function bound to the indicated key that is */
+/* compatible with the current state (eventmode). Window- */
+/* specific bindings shadow ALL_WINDOWS bindings. Return the */
+/* function number if found, or -1 if no compatible functions */
+/* are bound to the key state. */
+/*--------------------------------------------------------------*/
+
+int boundfunction(xcWidget window, int keywstate, short *retnum)
+{
+ keybinding *ksearch;
+ int tempfunc = -1;
+
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ if (keywstate == ksearch->keywstate) {
+ if (compatible_function(ksearch->function)) {
+ if (ksearch->window == window) {
+ if (retnum != NULL) *retnum = (ksearch->value);
+ return ksearch->function;
+ }
+ else if (ksearch->window == ALL_WINDOWS) {
+ if (retnum != NULL) *retnum = (ksearch->value);
+ tempfunc = ksearch->function;
+ }
+ }
+ }
+ }
+ return tempfunc;
+}
+
+/*--------------------------------------------------------------*/
+/* Check if an entry exists for a given key-function pair */
+/*--------------------------------------------------------------*/
+
+int isbound(xcWidget window, int keywstate, int function, short value)
+{
+ keybinding *ksearch;
+
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding)
+ if (keywstate == ksearch->keywstate && function == ksearch->function)
+ if (window == ALL_WINDOWS || window == ksearch->window ||
+ ksearch->window == ALL_WINDOWS)
+ if (value == -1 || value == ksearch->value || ksearch->value == -1)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*--------------------------------------------------------------*/
+/* Return the string associated with a function, or NULL if the */
+/* function value is out-of-bounds. */
+/*--------------------------------------------------------------*/
+
+char *func_to_string(int function)
+{
+ if ((function < 0) || (function >= NUM_FUNCTIONS)) return NULL;
+ return function_names[function];
+}
+
+/*--------------------------------------------------------------*/
+/* Identify a function with the string version of its name */
+/*--------------------------------------------------------------*/
+
+int string_to_func(const char *funcstring, short *value)
+{
+ int i;
+
+ for (i = 0; i < NUM_FUNCTIONS; i++)
+ {
+ if (function_names[i] == NULL) {
+ Fprintf(stderr, "Error: resolve bindings and function strings!\n");
+ return -1; /* should not happen? */
+ }
+ if (!strcmp(funcstring, function_names[i]))
+ return i;
+ }
+
+ /* Check if this string might have a value attached */
+
+ if (value != NULL)
+ for (i = 0; i < NUM_FUNCTIONS; i++)
+ if (!strncmp(funcstring, function_names[i], strlen(function_names[i]))) {
+ sscanf(funcstring + strlen(function_names[i]), "%hd", value);
+ return i;
+ }
+
+ return -1;
+}
+
+/*--------------------------------------------------------------*/
+/* Make a key sym from a string representing the key state */
+/*--------------------------------------------------------------*/
+
+int string_to_key(const char *keystring)
+{
+ int ct, keywstate = 0;
+ const char *kptr = keystring;
+
+ while(1) {
+ if (*kptr == '\0') return -1;
+ if (!strncmp(kptr, "XK_", 3))
+ kptr += 3;
+ else if (!strncmp(kptr, "Shift_", 6)) {
+ keywstate |= SHIFT;
+ kptr += 6;
+ }
+ else if (!strncmp(kptr, "Capslock_", 9)) {
+ keywstate |= CAPSLOCK;
+ kptr += 9;
+ }
+ else if (!strncmp(kptr, "Control_", 8)) {
+ keywstate |= CTRL;
+ kptr += 8;
+ }
+ else if (!strncmp(kptr, "Alt_", 4)) {
+ keywstate |= ALT;
+ kptr += 4;
+ }
+ else if (!strncmp(kptr, "Meta_", 5)) {
+ keywstate |= ALT;
+ kptr += 5;
+ }
+ else if (!strncmp(kptr, "Hold_", 5)) {
+ keywstate |= HOLD;
+ kptr += 5;
+ }
+ else if (*kptr == '^') {
+ kptr++;
+ ct = (int)tolower(*kptr);
+ keywstate |= CTRL | ct;
+ break;
+ }
+ else if (*(kptr + 1) == '\0') {
+ if ((*kptr) < 32)
+ keywstate |= CTRL | (int)('A' + (*kptr) - 1);
+ else
+ keywstate |= (int)(*kptr);
+ break;
+ }
+ else {
+ if (!strncmp(kptr, "Button", 6)) {
+ switch (*(kptr + 6)) {
+ case '1': keywstate = (Button1Mask << 16); break;
+ case '2': keywstate = (Button2Mask << 16); break;
+ case '3': keywstate = (Button3Mask << 16); break;
+ case '4': keywstate = (Button4Mask << 16); break;
+ case '5': keywstate = (Button5Mask << 16); break;
+ }
+ }
+ else {
+ /* When any modifier keys are used, presence of SHIFT */
+ /* requires that the corresponding key be uppercase, */
+ /* and lack of SHIFT requires lowercase. Enforce it */
+ /* here so that it is not necessary for the user to */
+ /* do so. */
+ if (*(kptr + 1) == '\0') {
+ if (keywstate & SHIFT)
+ ct = (int)toupper(*kptr);
+ else
+ ct = (int)tolower(*kptr);
+ keywstate |= ct;
+ }
+ else
+ keywstate |= XStringToKeysym(kptr);
+ }
+ break;
+ }
+ }
+ return keywstate;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a function into a string representing all of its */
+/* key bindings. */
+/*--------------------------------------------------------------*/
+
+char *function_binding_to_string(xcWidget window, int function)
+{
+ keybinding *ksearch;
+ char *retstr, *tmpstr;
+ Bool first = True;
+
+ retstr = (char *)malloc(1);
+ retstr[0] = '\0';
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ if (function == ksearch->function) {
+ if (ksearch->window == ALL_WINDOWS || ksearch->window == window) {
+ tmpstr = key_to_string(ksearch->keywstate);
+ if (tmpstr != NULL) {
+ retstr = (char *)realloc(retstr, strlen(retstr) + strlen(tmpstr) +
+ ((first) ? 1 : 3));
+ if (!first) strcat(retstr, ", ");
+ strcat(retstr, tmpstr);
+ free(tmpstr);
+ }
+ first = False;
+ }
+ }
+ }
+ if (retstr[0] == '\0') {
+ retstr = (char *)realloc(retstr, 10);
+ strcat(retstr, "<unbound>");
+ }
+ return(retstr);
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a key into a string representing all of its function */
+/* bindings. */
+/*--------------------------------------------------------------*/
+
+char *key_binding_to_string(xcWidget window, int keywstate)
+{
+ keybinding *ksearch;
+ char *retstr, *tmpstr;
+ Bool first = True;
+
+ retstr = (char *)malloc(1);
+ retstr[0] = '\0';
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ if (keywstate == ksearch->keywstate) {
+ if (ksearch->window == ALL_WINDOWS || ksearch->window == window) {
+ tmpstr = function_names[ksearch->function];
+ if (tmpstr != NULL) {
+ retstr = (char *)realloc(retstr, strlen(retstr) + strlen(tmpstr) +
+ ((first) ? 1 : 3));
+ if (!first) strcat(retstr, ", ");
+ strcat(retstr, tmpstr);
+ }
+ first = False;
+ }
+ }
+ }
+ if (retstr[0] == '\0') {
+ retstr = (char *)realloc(retstr, 10);
+ strcat(retstr, "<unbound>");
+ }
+ return(retstr);
+}
+
+/*--------------------------------------------------------------*/
+/* Return an allocated string name of the function that */
+/* is bound to the indicated key state for the indicated */
+/* window and compattible with the current event mode. */
+/*--------------------------------------------------------------*/
+
+char *compat_key_to_string(xcWidget window, int keywstate)
+{
+ char *retstr, *tmpstr;
+ int function;
+
+ function = boundfunction(window, keywstate, NULL);
+ tmpstr = func_to_string(function);
+
+ /* Pass back "Nothing" for unbound key states, since a */
+ /* wrapper script may want to use the result as an action. */
+
+ if (tmpstr == NULL) {
+ retstr = (char *)malloc(8);
+ strcpy(retstr, "Nothing");
+ }
+ else
+ retstr = strdup(tmpstr);
+
+ return(retstr);
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a key sym into a string */
+/*--------------------------------------------------------------*/
+
+char *key_to_string(int keywstate)
+{
+ static char hex[17] = "0123456789ABCDEF";
+ char *kptr, *str = NULL;
+ KeySym ks;
+ int kmod;
+
+ ks = keywstate & 0xffff;
+ kmod = keywstate >> 16;
+#if defined(XC_WIN32) && defined(TCL_WRAPPER)
+ if (ks != NoSymbol) str = XKeysymToString_TkW32(ks);
+#else
+ if (ks != NoSymbol) str = XKeysymToString(ks);
+#endif
+
+ kptr = (char *)malloc(32);
+ kptr[0] = '\0';
+ if (kmod & Mod1Mask) strcat(kptr, "Alt_");
+ if (kmod & Mod4Mask) strcat(kptr, "Hold_");
+ if (kmod & ControlMask) strcat(kptr, "Control_");
+ if (kmod & LockMask) strcat(kptr, "Capslock_");
+ if (kmod & ShiftMask) strcat(kptr, "Shift_");
+
+ if (str != NULL) {
+ /* 33 is length of all modifiers concatenated + 1 */
+ kptr = (char *)realloc(kptr, strlen(str) + 33);
+ strcat(kptr, str);
+ }
+ else {
+ kptr = (char *)realloc(kptr, 40);
+ if (kmod & Button1Mask) strcat(kptr, "Button1");
+ else if (kmod & Button2Mask) strcat(kptr, "Button2");
+ else if (kmod & Button3Mask) strcat(kptr, "Button3");
+ else if (kmod & Button4Mask) strcat(kptr, "Button4");
+ else if (kmod & Button5Mask) strcat(kptr, "Button5");
+ else {
+ kptr[0] = '0';
+ kptr[1] = 'x';
+ kptr[2] = hex[(kmod & 0xf)];
+ kptr[3] = hex[(keywstate & 0xf000) >> 12];
+ kptr[4] = hex[(keywstate & 0x0f00) >> 8];
+ kptr[5] = hex[(keywstate & 0x00f0) >> 4];
+ kptr[6] = hex[(keywstate & 0x000f) ];
+ kptr[7] = '\0';
+ }
+ }
+ return kptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Print the bindings for the (polygon) edit functions */
+/*--------------------------------------------------------------*/
+
+void printeditbindings()
+{
+ char *tstr;
+
+ _STR2[0] = '\0';
+
+ tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Delete));
+ strcat(_STR2, tstr);
+ strcat(_STR2, "=");
+ strcat(_STR2, func_to_string(XCF_Edit_Delete));
+ strcat(_STR2, ", ");
+ free(tstr);
+
+ tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Insert));
+ strcat(_STR2, tstr);
+ strcat(_STR2, "=");
+ strcat(_STR2, func_to_string(XCF_Edit_Insert));
+ strcat(_STR2, ", ");
+ free(tstr);
+
+ tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Param));
+ strcat(_STR2, tstr);
+ strcat(_STR2, "=");
+ strcat(_STR2, func_to_string(XCF_Edit_Param));
+ strcat(_STR2, ", ");
+ free(tstr);
+
+ tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Next));
+ strcat(_STR2, tstr);
+ strcat(_STR2, "=");
+ strcat(_STR2, func_to_string(XCF_Edit_Next));
+ free(tstr);
+
+ /* Use W3printf(). In the Tcl version, this prints to the */
+ /* message window but does not duplicate the output to */
+ /* stdout, where it would be just an annoyance. */
+
+ W3printf("%s", _STR2);
+}
+
+/*--------------------------------------------------------------*/
+/* Remove a key binding from the list */
+/* */
+/* Note: This routine needs to correctly handle ALL_WINDOWS */
+/* bindings that shadow specific window bindings. */
+/*--------------------------------------------------------------*/
+
+int remove_binding(xcWidget window, int keywstate, int function)
+{
+ keybinding *ksearch, *klast = NULL;
+
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ if (window == ALL_WINDOWS || window == ksearch->window) {
+ if ((function == ksearch->function)
+ && (keywstate == ksearch->keywstate)) {
+ if (klast == NULL)
+ keylist = ksearch->nextbinding;
+ else
+ klast->nextbinding = ksearch->nextbinding;
+ free(ksearch);
+ return 0;
+ }
+ }
+ klast = ksearch;
+ }
+ return -1;
+}
+
+/*--------------------------------------------------------------*/
+/* Wrapper for remove_binding */
+/*--------------------------------------------------------------*/
+
+void remove_keybinding(xcWidget window, const char *keystring, const char *fstring)
+{
+ int function = string_to_func(fstring, NULL);
+ int keywstate = string_to_key(keystring);
+
+ if ((function < 0) || (remove_binding(window, keywstate, function) < 0)) {
+ Wprintf("Key binding \'%s\' to \'%s\' does not exist in list.",
+ keystring, fstring);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Add a key binding to the list */
+/*--------------------------------------------------------------*/
+
+int add_vbinding(xcWidget window, int keywstate, int function, short value)
+{
+ keybinding *newbinding;
+
+ /* If key is already bound to the function, ignore it */
+
+ if (isbound(window, keywstate, function, value)) return 1;
+
+ /* Add the new key binding */
+
+ newbinding = (keybinding *)malloc(sizeof(keybinding));
+ newbinding->window = window;
+ newbinding->keywstate = keywstate;
+ newbinding->function = function;
+ newbinding->value = value;
+ newbinding->nextbinding = keylist;
+ keylist = newbinding;
+ return 0;
+}
+
+/*--------------------------------------------------------------*/
+/* Wrapper function for key binding without any values */
+/*--------------------------------------------------------------*/
+
+int add_binding(xcWidget window, int keywstate, int function)
+{
+ return add_vbinding(window, keywstate, function, (short)-1);
+}
+
+/*--------------------------------------------------------------*/
+/* Wrapper function for key binding with function as string */
+/*--------------------------------------------------------------*/
+
+int add_keybinding(xcWidget window, const char *keystring, const char *fstring)
+{
+ short value = -1;
+ int function = string_to_func(fstring, &value);
+ int keywstate = string_to_key(keystring);
+
+ if (function < 0)
+ return -1;
+ else
+ return add_vbinding(window, keywstate, function, value);
+}
+
+/*--------------------------------------------------------------*/
+/* Create list of default key bindings. */
+/* These are conditional upon any bindings set in the startup */
+/* file .xcircuitrc. */
+/*--------------------------------------------------------------*/
+
+void default_keybindings()
+{
+ add_vbinding(ALL_WINDOWS, XK_1, XCF_Page, 1);
+ add_vbinding(ALL_WINDOWS, XK_2, XCF_Page, 2);
+ add_vbinding(ALL_WINDOWS, XK_3, XCF_Page, 3);
+ add_vbinding(ALL_WINDOWS, XK_4, XCF_Page, 4);
+ add_vbinding(ALL_WINDOWS, XK_5, XCF_Page, 5);
+ add_vbinding(ALL_WINDOWS, XK_6, XCF_Page, 6);
+ add_vbinding(ALL_WINDOWS, XK_7, XCF_Page, 7);
+ add_vbinding(ALL_WINDOWS, XK_8, XCF_Page, 8);
+ add_vbinding(ALL_WINDOWS, XK_9, XCF_Page, 9);
+ add_vbinding(ALL_WINDOWS, XK_0, XCF_Page, 10);
+
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_1, XCF_Justify, 0);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_2, XCF_Justify, 1);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_3, XCF_Justify, 2);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_4, XCF_Justify, 3);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_5, XCF_Justify, 4);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_6, XCF_Justify, 5);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_7, XCF_Justify, 6);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_8, XCF_Justify, 7);
+ add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_9, XCF_Justify, 8);
+
+ add_vbinding(ALL_WINDOWS, XK_KP_End, XCF_Justify, 0);
+ add_vbinding(ALL_WINDOWS, XK_KP_Down, XCF_Justify, 1);
+ add_vbinding(ALL_WINDOWS, XK_KP_Next, XCF_Justify, 2);
+ add_vbinding(ALL_WINDOWS, XK_KP_Left, XCF_Justify, 3);
+ add_vbinding(ALL_WINDOWS, XK_KP_Begin, XCF_Justify, 4);
+ add_vbinding(ALL_WINDOWS, XK_KP_Right, XCF_Justify, 5);
+ add_vbinding(ALL_WINDOWS, XK_KP_Home, XCF_Justify, 6);
+ add_vbinding(ALL_WINDOWS, XK_KP_Up, XCF_Justify, 7);
+ add_vbinding(ALL_WINDOWS, XK_KP_Prior, XCF_Justify, 8);
+
+ add_binding(ALL_WINDOWS, XK_Delete, XCF_Text_Delete);
+ add_binding(ALL_WINDOWS, XK_Return, XCF_Text_Return);
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Text_Return);
+ add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Text_Delete);
+ add_binding(ALL_WINDOWS, XK_Left, XCF_Text_Left);
+ add_binding(ALL_WINDOWS, XK_Right, XCF_Text_Right);
+ add_binding(ALL_WINDOWS, XK_Up, XCF_Text_Up);
+ add_binding(ALL_WINDOWS, XK_Down, XCF_Text_Down);
+ add_binding(ALL_WINDOWS, ALT | XK_x, XCF_Text_Split);
+ add_binding(ALL_WINDOWS, XK_Home, XCF_Text_Home);
+ add_binding(ALL_WINDOWS, XK_End, XCF_Text_End);
+ add_binding(ALL_WINDOWS, XK_Tab, XCF_TabForward);
+ add_binding(ALL_WINDOWS, SHIFT | XK_Tab, XCF_TabBackward);
+#ifdef XK_ISO_Left_Tab
+ add_binding(ALL_WINDOWS, SHIFT | XK_ISO_Left_Tab, XCF_TabBackward);
+#endif
+ add_binding(ALL_WINDOWS, ALT | XK_Tab, XCF_TabStop);
+ add_binding(ALL_WINDOWS, XK_KP_Add, XCF_Superscript);
+ add_binding(ALL_WINDOWS, XK_KP_Subtract, XCF_Subscript);
+ add_binding(ALL_WINDOWS, XK_KP_Enter, XCF_Normalscript);
+ add_vbinding(ALL_WINDOWS, ALT | XK_f, XCF_Font, 1000);
+ add_binding(ALL_WINDOWS, ALT | XK_b, XCF_Boldfont);
+ add_binding(ALL_WINDOWS, ALT | XK_i, XCF_Italicfont);
+ add_binding(ALL_WINDOWS, ALT | XK_n, XCF_Normalfont);
+ add_binding(ALL_WINDOWS, ALT | XK_u, XCF_Underline);
+ add_binding(ALL_WINDOWS, ALT | XK_o, XCF_Overline);
+ add_binding(ALL_WINDOWS, ALT | XK_e, XCF_ISO_Encoding);
+ add_binding(ALL_WINDOWS, ALT | XK_Return, XCF_Linebreak);
+ add_binding(ALL_WINDOWS, ALT | XK_h, XCF_Halfspace);
+ add_binding(ALL_WINDOWS, ALT | XK_q, XCF_Quarterspace);
+#ifndef TCL_WRAPPER
+ add_binding(ALL_WINDOWS, ALT | XK_p, XCF_Parameter);
+#endif
+ add_binding(ALL_WINDOWS, XK_backslash, XCF_Special);
+ add_binding(ALL_WINDOWS, ALT | XK_c, XCF_Special);
+ add_binding(ALL_WINDOWS, XK_p, XCF_Edit_Param);
+ add_binding(ALL_WINDOWS, XK_d, XCF_Edit_Delete);
+ add_binding(ALL_WINDOWS, XK_Delete, XCF_Edit_Delete);
+ add_binding(ALL_WINDOWS, XK_i, XCF_Edit_Insert);
+ add_binding(ALL_WINDOWS, XK_Insert, XCF_Edit_Insert);
+ add_binding(ALL_WINDOWS, XK_e, XCF_Edit_Next);
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Edit_Next);
+ add_binding(ALL_WINDOWS, XK_A, XCF_Attach);
+ add_binding(ALL_WINDOWS, XK_V, XCF_Virtual);
+ add_binding(ALL_WINDOWS, XK_l, XCF_Next_Library);
+ add_binding(ALL_WINDOWS, XK_L, XCF_Library_Directory);
+ add_binding(ALL_WINDOWS, XK_c, XCF_Library_Copy);
+ add_binding(ALL_WINDOWS, XK_E, XCF_Library_Edit);
+ add_binding(ALL_WINDOWS, XK_e, XCF_Library_Edit);
+ add_binding(ALL_WINDOWS, XK_D, XCF_Library_Delete);
+ add_binding(ALL_WINDOWS, XK_C, XCF_Library_Duplicate);
+ add_binding(ALL_WINDOWS, XK_H, XCF_Library_Hide);
+ add_binding(ALL_WINDOWS, XK_V, XCF_Library_Virtual);
+ add_binding(ALL_WINDOWS, XK_M, XCF_Library_Move);
+ add_binding(ALL_WINDOWS, XK_m, XCF_Library_Move);
+ add_binding(ALL_WINDOWS, XK_P, XCF_Page_Directory);
+ add_binding(ALL_WINDOWS, XK_less, XCF_Library_Pop);
+ add_binding(ALL_WINDOWS, HOLD | BUTTON1, XCF_Library_Pop);
+ add_binding(ALL_WINDOWS, XK_h, XCF_Help);
+ add_binding(ALL_WINDOWS, XK_question, XCF_Help);
+ add_binding(ALL_WINDOWS, XK_space, XCF_Redraw);
+ add_binding(ALL_WINDOWS, XK_Redo, XCF_Redraw);
+ add_binding(ALL_WINDOWS, XK_Undo, XCF_Redraw);
+ add_binding(ALL_WINDOWS, XK_Home, XCF_View);
+ add_binding(ALL_WINDOWS, XK_v, XCF_View);
+ add_binding(ALL_WINDOWS, XK_Z, XCF_Zoom_In);
+ add_binding(ALL_WINDOWS, XK_z, XCF_Zoom_Out);
+ add_vbinding(ALL_WINDOWS, XK_p, XCF_Pan, 0);
+ add_binding(ALL_WINDOWS, XK_plus, XCF_Double_Snap);
+ add_binding(ALL_WINDOWS, XK_minus, XCF_Halve_Snap);
+ add_vbinding(ALL_WINDOWS, XK_Left, XCF_Pan, 1);
+ add_vbinding(ALL_WINDOWS, XK_Right, XCF_Pan, 2);
+ add_vbinding(ALL_WINDOWS, XK_Up, XCF_Pan, 3);
+ add_vbinding(ALL_WINDOWS, XK_Down, XCF_Pan, 4);
+ add_binding(ALL_WINDOWS, XK_W, XCF_Write);
+ add_vbinding(ALL_WINDOWS, XK_O, XCF_Rotate, -5);
+ add_vbinding(ALL_WINDOWS, XK_o, XCF_Rotate, 5);
+ add_vbinding(ALL_WINDOWS, XK_R, XCF_Rotate, -15);
+ add_vbinding(ALL_WINDOWS, XK_r, XCF_Rotate, 15);
+ add_binding(ALL_WINDOWS, XK_f, XCF_Flip_X);
+ add_binding(ALL_WINDOWS, XK_F, XCF_Flip_Y);
+ add_binding(ALL_WINDOWS, XK_S, XCF_Snap);
+ add_binding(ALL_WINDOWS, XK_less, XCF_Pop);
+ add_binding(ALL_WINDOWS, XK_greater, XCF_Push);
+ add_binding(ALL_WINDOWS, XK_Delete, XCF_Delete);
+ add_binding(ALL_WINDOWS, XK_d, XCF_Delete);
+ add_binding(ALL_WINDOWS, XK_F19, XCF_Select);
+ add_binding(ALL_WINDOWS, XK_b, XCF_Box);
+ add_binding(ALL_WINDOWS, XK_a, XCF_Arc);
+ add_binding(ALL_WINDOWS, XK_t, XCF_Text);
+ add_binding(ALL_WINDOWS, XK_X, XCF_Exchange);
+ add_binding(ALL_WINDOWS, XK_c, XCF_Copy);
+ add_binding(ALL_WINDOWS, XK_j, XCF_Join);
+ add_binding(ALL_WINDOWS, XK_J, XCF_Unjoin);
+ add_binding(ALL_WINDOWS, XK_s, XCF_Spline);
+ add_binding(ALL_WINDOWS, XK_e, XCF_Edit);
+ add_binding(ALL_WINDOWS, XK_u, XCF_Undo);
+ add_binding(ALL_WINDOWS, XK_U, XCF_Redo);
+ add_binding(ALL_WINDOWS, XK_M, XCF_Select_Save);
+ add_binding(ALL_WINDOWS, XK_m, XCF_Select_Save);
+ add_binding(ALL_WINDOWS, XK_x, XCF_Unselect);
+ add_binding(ALL_WINDOWS, XK_bar, XCF_Dashed);
+ add_binding(ALL_WINDOWS, XK_colon, XCF_Dotted);
+ add_binding(ALL_WINDOWS, XK_underscore, XCF_Solid);
+ add_binding(ALL_WINDOWS, XK_percent, XCF_Prompt);
+ add_binding(ALL_WINDOWS, XK_period, XCF_Dot);
+#ifndef TCL_WRAPPER
+ /* TCL_WRAPPER version req's binding to specific windows */
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Wire);
+#endif
+ add_binding(ALL_WINDOWS, XK_w, XCF_Wire);
+ add_binding(ALL_WINDOWS, CTRL | ALT | XK_q, XCF_Exit);
+ add_binding(ALL_WINDOWS, HOLD | BUTTON1, XCF_Move);
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Continue_Element);
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Continue_Copy);
+ add_binding(ALL_WINDOWS, BUTTON1, XCF_Finish);
+ add_binding(ALL_WINDOWS, XK_Escape, XCF_Cancel);
+ add_binding(ALL_WINDOWS, ALT | XK_r, XCF_Rescale);
+ add_binding(ALL_WINDOWS, ALT | XK_s, XCF_SnapTo);
+ add_binding(ALL_WINDOWS, ALT | XK_q, XCF_Netlist);
+ add_binding(ALL_WINDOWS, XK_slash, XCF_Swap);
+ add_binding(ALL_WINDOWS, XK_T, XCF_Pin_Label);
+ add_binding(ALL_WINDOWS, XK_G, XCF_Pin_Global);
+ add_binding(ALL_WINDOWS, XK_I, XCF_Info_Label);
+ add_binding(ALL_WINDOWS, ALT | XK_w, XCF_Connectivity);
+
+/* These are for test purposes only. Menu selection is */
+/* preferred. */
+
+/* add_binding(ALL_WINDOWS, ALT | XK_d, XCF_Sim); */
+/* add_binding(ALL_WINDOWS, ALT | XK_a, XCF_SPICE); */
+/* add_binding(ALL_WINDOWS, ALT | XK_f, XCF_SPICEflat); */
+/* add_binding(ALL_WINDOWS, ALT | XK_p, XCF_PCB); */
+
+ /* Avoid spurious Num_Lock messages */
+ add_binding(ALL_WINDOWS, XK_Num_Lock, XCF_Nothing);
+
+ /* 2-button vs. 3-button mouse bindings (set with -2 */
+ /* commandline option; 3-button bindings default) */
+
+ if (pressmode == 1) {
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Text_Return);
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Select);
+ add_binding(ALL_WINDOWS, HOLD | BUTTON3, XCF_SelectBox);
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Finish_Element);
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Finish_Copy);
+
+ add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Cancel_Last);
+ add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Cancel);
+ }
+ else {
+ add_binding(ALL_WINDOWS, BUTTON2, XCF_Text_Return);
+ add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Text_Return);
+ add_binding(ALL_WINDOWS, BUTTON2, XCF_Select);
+ add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Select);
+ add_binding(ALL_WINDOWS, HOLD | BUTTON2, XCF_SelectBox);
+ add_binding(ALL_WINDOWS, SHIFT | HOLD | BUTTON1, XCF_Select);
+ add_binding(ALL_WINDOWS, BUTTON2, XCF_Finish_Element);
+ add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Finish_Element);
+ add_binding(ALL_WINDOWS, BUTTON2, XCF_Finish_Copy);
+ add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Finish_Copy);
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Cancel_Last);
+ add_binding(ALL_WINDOWS, BUTTON3, XCF_Cancel);
+ }
+}
+
+#ifndef TCL_WRAPPER
+/*----------------------------------------------*/
+/* Mode-setting rebindings (non-Tcl version) */
+/*----------------------------------------------*/
+
+static int button1mode = XCF_Wire;
+
+/*--------------------------------------------------------------*/
+/* Re-bind BUTTON1 to the indicated function and optional value */
+/*--------------------------------------------------------------*/
+
+void mode_rebinding(int newmode, int newvalue)
+{
+ xcWidget window = areawin->area;
+
+ remove_binding(window, BUTTON1, button1mode);
+ add_vbinding(window, BUTTON1, newmode, (short)newvalue);
+ button1mode = newmode;
+ toolcursor(newmode);
+}
+
+/*--------------------------------------------------------------*/
+/* Execute the function associated with the indicated BUTTON1 */
+/* mode, but return the keybinding to its previous state. */
+/*--------------------------------------------------------------*/
+
+void mode_tempbinding(int newmode, int newvalue)
+{
+ short saveval;
+ XPoint cpos;
+ xcWidget window = areawin->area;
+
+ if (boundfunction(window, BUTTON1, &saveval) == button1mode) {
+ remove_binding(window, BUTTON1, button1mode);
+ add_vbinding(window, BUTTON1, newmode, (short)newvalue);
+ cpos = UGetCursor();
+ eventdispatch(BUTTON1, (int)cpos.x, (int)cpos.y);
+ remove_binding(window, BUTTON1, newmode);
+ add_vbinding(window, BUTTON1, button1mode, saveval);
+ }
+ else
+ fprintf(stderr, "Error: No such button1 binding %s\n",
+ func_to_string(button1mode));
+}
+
+#endif /* TCL_WRAPPER */
+
+#undef ALT
+#undef CTRL
+#undef CAPSLOCK
+#undef SHIFT
+#undef BUTTON1
+#undef BUTTON2
+#undef BUTTON3
+
+/*--------------------------------------------------------------*/
diff --git a/lib/XCircuit.ad b/lib/XCircuit.ad
new file mode 100644
index 0000000..384fb58
--- /dev/null
+++ b/lib/XCircuit.ad
@@ -0,0 +1,35 @@
+!
+! Normal X defaults for xcircuit, black-on-white version
+!
+xcircuit*foreground : Brown4
+xcircuit*background : Beige
+xcircuit.foreground : Black
+xcircuit.background : White
+xcircuit*gridcolor : Gray95
+xcircuit*snapcolor : Red
+xcircuit*selectcolor : Gold3
+xcircuit*querycolor : Turquoise
+xcircuit*axescolor : Antique White
+xcircuit*offbuttoncolor : Gray85
+xcircuit*auxiliarycolor : Green3
+xcircuit*barcolor : Tan
+xcircuit*ratsnestcolor : Tan4
+!
+xcircuit*borderWidth : 2
+xcircuit*borderColor : Red
+!
+xcircuit.width : 950
+xcircuit.height : 760
+!
+! Inverse color scheme (white-on-black)
+!
+xcircuit*foreground2 : White
+xcircuit*background2 : DarkSlateGray
+xcircuit*gridcolor2 : Gray40
+xcircuit*snapcolor2 : Red
+xcircuit*selectcolor2 : Gold
+xcircuit*querycolor2 : Turquoise
+xcircuit*axescolor2 : NavajoWhite4
+xcircuit*offbuttoncolor2 : Gray50
+xcircuit*auxiliarycolor2 : Green
+xcircuit*barcolor2 : Tan
diff --git a/lib/analog.lps b/lib/analog.lps
new file mode 100644
index 0000000..bf0271d
--- /dev/null
+++ b/lib/analog.lps
@@ -0,0 +1,312 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.6
+% Library name is: analog
+% Author: R. Timothy Edwards <tim@khachaturian.tim.linglan.net>
+%
+
+% Depend analog::vsource analog::source
+% Depend analog::isource analog::source generic::arrowhead
+% Depend analog::acsource analog::source
+% Depend analog::nmos2 analog::nmos generic::arrowhead
+% Depend analog::pmos2 analog::nmos generic::arrowhead
+% Depend analog::npn generic::arrowhead
+% Depend analog::pnp generic::arrowhead
+% Depend analog::switch generic::circle generic::arrowhead
+
+% XCircuitLib library objects
+/analog::capacitor {
+begingate
+1 1.000 0 -64 0 -6 2 polygon
+1 1.000 0 64 0 6 2 polygon
+1 1.000 -32 6 32 6 2 polygon
+1 1.000 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(c.1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(c.2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:C%i %pc.1 %pc.2 1.0P) {/Times-Roman cf} 2 0 0 1.000 -208 -160 infolabel
+(sim:c %pc.1 %pc.2) {/Times-Roman cf} 2 0 0 1.000 -208 -208 infolabel
+endgate
+} def
+
+/analog::polarized {
+begingate
+1 1.000 0 -64 0 -6 2 polygon
+1 1.000 0 64 0 6 2 polygon
+1 1.000 -32 6 32 6 2 polygon
+1 1.000 0 -80 74 66.000 114.000 xcarc
+1.000 0.000 0.000 scb
+(t) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(b) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:C%i %pt %pb 1.0P) {/Times-Roman cf} 2 0 0 1.000 -208 -160 infolabel
+(sim:e %pt %pb %pb) {/Times-Roman cf} 2 0 0 1.000 -208 -208 infolabel
+endgate
+} def
+
+/analog::resistor {
+begingate
+1 1.000 0 64 0 36 2 polygon
+1 1.000 0 -64 0 -36 2 polygon
+1 1.000 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(r.2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:R%i %pr.1 %pr.2 1.0K) {/Times-Roman cf} 2 0 0 1.000 -208 -160 infolabel
+(sim:r %pr.1 %pr.2) {/Times-Roman cf} 2 0 0 1.000 -208 -208 infolabel
+endgate
+} def
+
+/analog::inductor {
+begingate
+1 1.000 20 -22 20 -38 0 -42 0 -18 spline
+1 1.000 -20 -14 -20 -26 0 -22 0 -18 spline
+1 1.000 20 38 20 22 0 18 0 42 spline
+1 1.000 20 18 20 2 0 -2 0 22 spline
+1 1.000 20 -2 20 -18 0 -22 0 2 spline
+1 1.000 -20 26 -20 14 0 18 0 22 spline
+1 1.000 -20 6 -20 -6 0 -2 0 2 spline
+1 1.000 0 -42 0 -64 2 polygon
+1 1.000 0 42 0 64 2 polygon
+1.000 0.000 0.000 scb
+(l.1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(l.2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:L%i %pl.1 %pl.2 1.0U) {/Times-Roman cf} 2 0 0 1.000 -208 -160 infolabel
+(sim:l %pl.1 %pl.2) {/Times-Roman cf} 2 0 0 1.000 -208 -208 infolabel
+endgate
+} def
+
+/analog::opamp {
+begingate
+0 1.000 -80 -80 -80 80 80 0 3 polygon
+(-) {/Symbol cf} 2 5 0 1.000 -61 42 label
+(+) {/Symbol cf} 2 5 0 1.000 -61 -50 label
+1.000 0.000 0.000 scb
+(in.m) {/Times-Roman cf} 2 7 0 1.000 -80 48 pinlabel
+(in.p) {/Times-Roman cf} 2 7 0 1.000 -80 -48 pinlabel
+(out) {/Times-Roman cf} 2 4 0 1.000 80 0 pinlabel
+endgate
+} def
+
+/analog::vdd {
+% trivial
+begingate
+1 1.000 0 0 0 32 2 polygon
+1 1.000 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.900 0 38 label
+0.933 0.604 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.000 0 0 pinglobal
+endgate
+} def
+
+/analog::gnd {
+% trivial
+begingate
+1 1.000 0 0 0 -32 2 polygon
+1 1.000 -32 -32 32 -32 2 polygon
+1 1.000 -18 -46 18 -46 2 polygon
+1 1.000 -4 -60 4 -60 2 polygon
+0.933 0.604 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.000 0 0 pinglobal
+endgate
+} def
+
+/analog::source {
+% hidden
+begingate
+1 1.000 0 0 32 0.000 360.000 xcarc
+1 1.000 0 32 0 64 2 polygon
+1 1.000 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/analog::vsource {
+begingate
+1.000 0 0 0 analog::source
+(+) {/Symbol cf} 2 5 0 1.000 0 14 label
+(-) {/Symbol cf} 2 5 0 1.000 0 -22 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(v.m) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+endgate
+} def
+
+/generic::arrowhead {
+% nonetwork
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249
+1.000 endpath
+endgate
+} def
+
+/analog::isource {
+begingate
+1.000 0 0 0 analog::source
+1 0.750 0 20 0 -8 2 polygon
+0.800 180 0 -20 generic::arrowhead
+1.000 0.000 0.000 scb
+(i.p) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(i.m) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+endgate
+} def
+
+/analog::acsource {
+begingate
+1.000 0 0 0 analog::source
+1 0.800 0 -48 0 48 -16 0 16 0 spline
+1.000 0.000 0.000 scb
+(s.p) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(s.m) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+endgate
+} def
+
+/analog::nmos {
+begingate
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS GND nmos) {/Times-Roman cf} 2 4 0 1.000 -244 -139
+infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.000 -244 -187 infolabel
+endgate
+} def
+
+/analog::pmos {
+begingate
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -60 0 -64 0 2 polygon
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -52 0 8 0.000 360.000 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS Vdd pmos) {/Times-Roman cf} 2 4 0 1.000 -196 -139
+infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.000 -196 -187 infolabel
+endgate
+} def
+
+/analog::nmos2 {
+begingate
+1.000 0 0 0 analog::nmos
+1.000 90 0 -28 generic::arrowhead
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+endgate
+} def
+
+/analog::pmos2 {
+begingate
+1.000 0 0 0 analog::nmos
+1.000 270 -32 28 generic::arrowhead
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+endgate
+} def
+
+/analog::diode {
+begingate
+248 1.000 -18 -16 0 16 18 -16 3 polygon
+1 1.000 0 -48 0 -16 2 polygon
+1 1.000 0 48 0 16 2 polygon
+1 1.000 -18 16 18 16 2 polygon
+1.000 0.000 0.000 scb
+(d.m) {/Times-Roman cf} 2 9 0 1.000 0 48 pinlabel
+(d.p) {/Times-Roman cf} 2 13 0 1.000 0 -48 pinlabel
+endgate
+} def
+
+/analog::npn {
+begingate
+1 1.000 -48 0 -64 0 2 polygon
+1 1.000 -48 48 -48 -48 2 polygon
+1 1.000 0 48 -48 22 2 polygon
+1 1.000 0 48 0 64 2 polygon
+1 1.000 0 -48 -48 -22 2 polygon
+1 1.000 0 -48 0 -64 2 polygon
+1.000 120 0 -48 generic::arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:Q%i %pC %pB %pE npn) {/Times-Roman cf} 2 4 0 1.000 -244 -139 infolabel
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.000 -244 -187 infolabel
+endgate
+} def
+
+/analog::pnp {
+begingate
+1 1.000 -48 0 -64 0 2 polygon
+1 1.000 -48 48 -48 -48 2 polygon
+1 1.000 0 48 -48 22 2 polygon
+1 1.000 0 48 0 64 2 polygon
+1 1.000 0 -48 -48 -22 2 polygon
+1 1.000 0 -48 0 -64 2 polygon
+1.000 240 -48 22 generic::arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:Q%i %pC %pB %pE pnp) {/Times-Roman cf} 2 4 0 1.000 -244 -139 infolabel
+endgate
+} def
+
+/analog::crystal {
+begingate
+0 1.000 -24 -12 -24 12 24 12 24 -12 4 polygon
+1 1.000 0 48 0 24 2 polygon
+1 1.000 0 -48 0 -24 2 polygon
+1 1.000 -20 24 20 24 2 polygon
+1 1.000 -20 -24 20 -24 2 polygon
+1.000 0.000 0.000 scb
+(x.1) {/Times-Roman cf} 2 9 0 1.000 0 48 pinlabel
+(x.2) {/Times-Roman cf} 2 13 0 1.000 0 -48 pinlabel
+endgate
+} def
+
+/generic::circle {
+% trivial
+begingate
+1 1.000 16 0 6 0.000 360.000 xcarc
+1 1.000 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.000 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.000 0 0 pinlabel
+endgate
+} def
+
+/analog::switch {
+% trivial
+begingate
+1 1.300 32 32 2 -43 2 polygon
+1 0.600 0 -48 57 49.000 90.000 xcarc
+-1.000 90 0 -64 generic::circle
+0.600 270 -12 8 generic::arrowhead
+1.000 90 0 48 generic::circle
+1.000 0.000 0.000 scb
+(sw.1) {/Times-Roman cf} 2 9 0 1.000 0 48 pinlabel
+(sw.2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/analoglib2.lps b/lib/analoglib2.lps
new file mode 100644
index 0000000..b2c8f7f
--- /dev/null
+++ b/lib/analoglib2.lps
@@ -0,0 +1,372 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: analoglib2
+% Author: R. Timothy Edwards <tim@khachaturian>
+%
+
+% Depend analoglib2::Transformer analog::inductor
+% Depend analoglib2::Vsource analog::source
+% Depend analoglib2::Isource generic::arrowhead analog::source
+% Depend analoglib2::ACsource analoglib2::sinusoid analog::source
+% Depend analoglib2::NPN generic::arrowhead
+% Depend analoglib2::PNP generic::arrowhead
+
+% XCircuitLib library objects
+/analoglib2::Capacitor {
+<< /value (1.0) /units (p) /@index (?) /p_jst 20 /p_rot 0 /pkg (AXIAL_400) >> begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:C) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:c %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (F) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:C) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Capacitor libinst
+
+/analoglib2::Polarized {
+<< /value (1.0) /units (p) /@index (?) /p_jst 20 /p_rot 0 /pkg (AXIAL_400) >> begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:C) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:e %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (F) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:C) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Polarized libinst
+
+/analoglib2::Resistor {
+<< /value (1.0) /units (k) /@index (?) /p_jst 20 /p_rot 0 /pkg (AXIAL_400) >> begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:R) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:r %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (W) {/Symbol cf} units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 32 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:R) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Resistor libinst
+
+/analoglib2::Inductor {
+<< /value (1.0) /units (m) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 20 -28 20 -44 0 -48 0 -24 spline
+1 1.00 -20 -20 -20 -32 0 -28 0 -24 spline
+1 1.00 20 32 20 16 0 12 0 36 spline
+1 1.00 20 12 20 -4 0 -8 0 16 spline
+1 1.00 20 -8 20 -24 0 -28 0 -4 spline
+1 1.00 -20 20 -20 8 0 12 0 16 spline
+1 1.00 -20 0 -20 -12 0 -8 0 -4 spline
+1 1.00 0 -48 0 -64 2 polygon
+1 1.00 0 36 0 48 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:L) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:l %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (H) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 32 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:L) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Inductor libinst
+
+/analog::inductor {
+begingate
+1 1.00 20 -28 20 -44 0 -48 0 -24 spline
+1 1.00 -20 -20 -20 -32 0 -28 0 -24 spline
+1 1.00 20 32 20 16 0 12 0 36 spline
+1 1.00 20 12 20 -4 0 -8 0 16 spline
+1 1.00 20 -8 20 -24 0 -28 0 -4 spline
+1 1.00 -20 20 -20 8 0 12 0 16 spline
+1 1.00 -20 0 -20 -12 0 -8 0 -4 spline
+1 1.00 0 -48 0 -64 2 polygon
+1 1.00 0 36 0 48 2 polygon
+1.000 0.000 0.000 scb
+(l.1) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(l.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:L%i %pl.1 %pl.2 1.0U) {/Times-Roman cf} 2 0 0 1.00 -208 -160 infolabel
+(sim:l %pl.1 %pl.2) {/Times-Roman cf} 2 0 0 1.00 -208 -208 infolabel
+endgate
+} def
+
+/analoglib2::Transformer {
+<< /@index (?) >> begingate
+1.00 0 -48 0 analog::inductor
+1 1.00 -16 48 -16 -64 2 polygon
+1 1.00 0 48 0 -64 2 polygon
+1.00 180 32 -16 analog::inductor
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 25 0 1.00 -48 48 pinlabel
+(2) {/Times-Roman cf} 2 29 0 1.00 -48 -64 pinlabel
+(3) {/Times-Roman cf} 2 25 0 1.00 32 48 pinlabel
+(4) {/Times-Roman cf} 2 29 0 1.00 32 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:T) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160 infolabel
+endgate
+} def
+
+/analog::source {
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/analoglib2::Vsource {
+<< /value (5) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 analog::source
+(+) {/Symbol cf} 2 5 p_rot 1.00 0 14 label
+(-) {/Symbol cf} 2 5 p_rot 1.00 0 -22 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(v.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark value (spice:V%i %pv.p %pv.m ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (V) {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Vsource libinst
+
+/generic::arrowhead {
+% trivial
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/analoglib2::Isource {
+<< /value (1) /units (m) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 analog::source
+1 0.75 0 20 0 -8 2 polygon
+0.80 180 0 -20 generic::arrowhead
+1.000 0.000 0.000 scb
+(i.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(i.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value (spice:I%i %pi.p %pi.m ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (A) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::Isource libinst
+
+/analoglib2::sinusoid {
+% hidden
+begingate
+1 0.80 0 -48 0 48 -16 0 16 0 spline
+endgate
+} def
+
+/analoglib2::ACsource {
+<< /value (5) /offset (0) /freq (1) /units (k) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 analog::source
+1.000 0.000 0.000 scb
+(s.p) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(s.m) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark (\)) units freq ( ) value ( ) offset (spice:V%i %ps.p %ps.m SIN\()
+{/Times-Roman cf} ctmk 20 0 1.00 -336 -160 infolabel
+sce
+mark (Hz) units {hS} freq {CR} (offset) {ss} (V) {hS} offset {CR} (p-p)
+{ss} (V) {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+1.00 p_rot 0 0 analoglib2::sinusoid
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::ACsource libinst
+
+/analoglib2::nMOS {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS GND ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -244 -139 infolabel
+mark ( %x %y) width ( ) length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-244 -187 infolabel
+sce
+mark length (=) {Tf} (L) {hS} {CR} width (=) {Ts} (W) {/Times-Roman cf} ctmk p_jst
+p_rot 1.00 16 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::nMOS libinst
+
+/analoglib2::pMOS {
+<< /width (3) /length (2) /model (pmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS Vdd ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -196 -139 infolabel
+mark ( %x %y) width ( ) length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-196 -187 infolabel
+sce
+mark length (=) {Tf} (L) {hS} {CR} width (=) {Ts} (W) {/Times-Roman cf} ctmk p_jst
+p_rot 1.00 16 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::pMOS libinst
+
+/analoglib2::nMOS4 {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS %pB ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -244 -139 infolabel
+mark ( %x %y) width ( ) length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-244 -187 infolabel
+sce
+mark length (/) width (W/L=) {/Times-Roman cf} ctmk p_jst p_rot 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::nMOS4 libinst
+
+/analoglib2::pMOS4 {
+<< /width (3) /length (2) /model (pmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS %pB ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -196 -139 infolabel
+mark ( %x %y) width ( ) length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-196 -187 infolabel
+sce
+mark length (/) width (W/L=) {/Times-Roman cf} ctmk p_jst p_rot 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /analoglib2::pMOS4 libinst
+
+/analoglib2::NPN {
+<< /model (npn) /@index (?) >> begingate
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 120 0 -48 generic::arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark model ( %pC %pB %pE ) @index (spice:Q) {/Times-Roman cf} ctmk 4 0 1.00 -244 -139
+infolabel
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/analoglib2::PNP {
+<< /model (pnp) /@index (?) >> begingate
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 240 -48 22 generic::arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark model ( %pC %pB %pE ) @index (spice:Q) {/Times-Roman cf} ctmk 4 0 1.00 -244 -139
+infolabel
+endgate
+} def
+
+/analoglib2::Diode {
+<< /@index (?) >> begingate
+248 1.00 -18 -16 0 16 18 -16 3 polygon
+1 1.00 0 -48 0 -16 2 polygon
+1 1.00 0 48 0 16 2 polygon
+1 1.00 -18 16 18 16 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -48 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:D) {/Times-Roman cf} ctmk 20 0 1.00 -64 -144 infolabel
+mark ( %p2 %p1 diode) @index (spice:D) {/Times-Roman cf} ctmk 4 0 1.00 -64 -192
+infolabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/analoglib3.lps b/lib/analoglib3.lps
new file mode 100644
index 0000000..ece3c9d
--- /dev/null
+++ b/lib/analoglib3.lps
@@ -0,0 +1,457 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.6
+% Library name is: analoglib3
+% Author: R. Timothy Edwards <tim@khachaturian.tim.linglan.net>
+%
+
+% Depend analoglib3::NPNModel generic::arrowhead
+% Depend analoglib3::Vsource analog::source
+% Depend analoglib3::ACsource analog::source analoglib2::sinusoid
+% Depend analoglib3::Vpwl analog::source
+% Depend analoglib3::Switch generic::circle generic::arrowhead
+
+% XCircuitLib library objects
+/analoglib3::pMOS {
+<</@subs (avdd) /p_yps2 48 /p_xps2 16 /p_yps1 -8 /p_xps1 16 /p_yps 16 /p_xps 16 /p_rot
+0 /@fingers (1) /@class (M) /@width (1u) /@length (0.18u) /@model (pfet) /@index
+(?) /p_jst 28 >> begingate
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -60 0 -64 0 2 polygon
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -52 0 8 0.000 360.000 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark @fingers ( M=) @length ( L=) @width ( W=) @model ( ) @subs ( %pD %pG %pS )
+@index @class (spice:) {/Times-Roman cf} ctmk 4 0 1.000 -196 -139 infolabel
+mark ( %x %y) @width ( ) @length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4
+0 1.000 -196 -187 infolabel
+0.647 0.165 0.165 scb
+mark @fingers {hS} (=) {hS} (M) {CR} @length (=) {Tf} (L) {hS} {CR} @width (=)
+{Ts} (W) {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps1 p_yps1 label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 16 p_rot 0.700 p_xps2 p_yps2 label
+sce
+mark @model {/Times-RomanISO cf} ctmk 16 p_rot 0.700 p_xps p_yps label
+endgate
+} def
+
+1.000 90 <</p_yps -32 /p_xps1 32 /p_yps1 -40 /p_rot 270 /p_xps2 -32 >> /analoglib3::pMOS libinst
+<</@model (hvpfet) /@length (0.36u) /@subs (dvdd3) >> /analoglib3::pMOS libinst
+1.000 90 <</p_yps -32 /p_xps1 32 /p_yps1 -40 /p_rot 270 /p_xps2 -32 /@model (hvpfet)
+/@length (0.36u) /@subs (dvdd3) >> /analoglib3::pMOS libinst
+
+/analoglib3::pMOS1finger {
+<</p_yps2 -16 /p_xps2 16 /p_yps1 8 /p_xps1 16 /p_yps 40 /p_xps 16 /p_rot 0 /@subs
+(avdd) /@class (M) /@width (1u) /@length (0.18u) /@model (pfet) /@index
+(?) /p_jst 28 >> begingate
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -60 0 -64 0 2 polygon
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -52 0 8 0.000 360.000 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark @length ( L=) @width ( W=) @model ( ) @subs ( %pD %pG %pS ) @index @class
+(spice:) {/Times-Roman cf} ctmk 4 0 1.000 -196 -139 infolabel
+mark ( %x %y) @width ( ) @length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4
+0 1.000 -196 -187 infolabel
+0.647 0.165 0.165 scb
+mark @length (=) {Tf} (L) {hS} {CR} @width (=) {Ts} (W) {/Times-Roman cf} ctmk
+p_jst p_rot 0.700 p_xps2 p_yps2 label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 16 p_rot 0.700 p_xps p_yps label
+sce
+mark @model {/Times-RomanISO cf} ctmk 16 p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 90 <</p_yps2 -32 /p_yps1 -24 /p_xps2 32 /p_rot 270 /p_xps -16 >> /analoglib3::pMOS1finger libinst
+<</@model (hvpfet) /@length (0.36u) /@subs (dvdd3) >> /analoglib3::pMOS1finger libinst
+1.000 90 <</p_yps2 -32 /p_yps1 -24 /p_xps2 32 /p_rot 270 /p_xps -16 /@model (hvpfet)
+/@length (0.36u) /@subs (dvdd3) >> /analoglib3::pMOS1finger libinst
+
+/analoglib3::nMOS {
+<</@subs (agnd) /p_yps2 -16 /p_xps2 16 /p_yps1 8 /p_xps1 16 /p_yps 40 /p_xps 16 /p_rot
+0 /@fingers (1) /@class (M) /@width (1u) /@length (0.18u) /@model (nfet) /@index
+(?) /p_jst 28 >> begingate
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark @fingers ( m=) @length ( l=) @width ( w=) @model ( ) @subs ( %pD %pG %pS )
+@index @class (spice:) {/Times-Roman cf} ctmk 4 0 1.000 -244 -139 infolabel
+mark ( %x %y) @width ( ) @length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4
+0 1.000 -244 -187 infolabel
+0.647 0.165 0.165 scb
+mark @fingers (=) {Tf} {Tf} (M) {CR} @length (=) {Tf} (L) {hS} {CR} @width (=)
+{Ts} (W) {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps2 p_yps2 label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+sce
+mark @model {/Times-RomanISO cf} ctmk 20 p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 90 <</p_yps1 -24 /p_xps2 32 /p_yps2 -32 /p_rot 270 /p_xps -32 >> /analoglib3::nMOS libinst
+<</p_jst 28 /p_xps2 16 /p_yps2 -16 /@model (hvnfet) /@length (0.36u) /@subs
+(dgnd) >> /analoglib3::nMOS libinst
+1.000 90 <</p_yps2 -32 /p_yps1 -24 /p_xps2 32 /p_rot 270 /p_xps -32 /@model (hvnfet)
+/@length (0.36u) /@subs (dgnd) >> /analoglib3::nMOS libinst
+
+/analoglib3::nMOS1finger {
+<</@subs (agnd) /p_yps2 -16 /p_xps2 16 /p_yps1 8 /p_xps1 16 /p_yps 40 /p_xps 16 /p_rot
+0 /@class (M) /@width (1u) /@length (0.18u) /@model (nfet) /@index (?) /p_jst
+28 >> begingate
+1 1.000 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.000 -44 -28 -44 28 2 polygon
+1 1.000 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark @length ( l=) @width ( w=) @model ( ) @subs ( %pD %pG %pS ) @index @class
+(spice:) {/Times-Roman cf} ctmk 4 360 1.000 -244 -139 infolabel
+mark ( %x %y) @width ( ) @length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4
+0 1.000 -244 -187 infolabel
+0.647 0.165 0.165 scb
+mark @length (=) {Tf} (L) {hS} {CR} @width (=) {Ts} (W) {/Times-Roman cf} ctmk
+p_jst p_rot 0.700 p_xps2 p_yps2 label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+sce
+mark @model {/Times-RomanISO cf} ctmk 20 p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 90 <</p_yps2 -32 /p_yps1 -24 /p_xps2 32 /p_rot 270 /p_xps -32 >> /analoglib3::nMOS1finger libinst
+<</@model (hvnfet) /@length (0.36u) /@subs (dgnd) >> /analoglib3::nMOS1finger libinst
+1.000 90 <</p_yps2 -32 /p_yps1 -24 /p_xps2 32 /p_rot 270 /p_xps -32 /@model (hvnfet)
+/@length (0.36u) /@subs (dgnd) >> /analoglib3::nMOS1finger libinst
+
+/generic::arrowhead {
+% nonetwork
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249
+1.000 endpath
+endgate
+} def
+
+/analoglib3::NPNModel {
+<</@subs (agnd) /p_yps2 56 /p_xps2 16 /p_yps1 0 /p_xps1 16 /p_yps 24 /p_xps 16 /p_rot
+0 /@length (10.16u) /@width (0.2u) /@m (1) /@model (bipolar) /@index (?) /@class
+(Q) >> begingate
+1 1.000 -48 0 -64 0 2 polygon
+1 1.000 -48 48 -48 -48 2 polygon
+1 1.000 0 48 -48 22 2 polygon
+1 1.000 0 48 0 64 2 polygon
+1 1.000 0 -48 -48 -22 2 polygon
+1 1.000 0 -48 0 -64 2 polygon
+1.000 120 0 -48 generic::arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.000 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @m ( M=) @length ( L=) @width ( W=) @model ( ) @subs ( %pC %pB %pE )
+@index @class (spice:) {/Times-Roman cf} ctmk 4 0 1.000 -244 -139 infolabel
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.000 -244 -187 infolabel
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 16 p_rot 0.700 p_xps2 p_yps2 label
+sce
+mark @model {/Times-RomanISO cf} ctmk 16 p_rot 0.700 p_xps p_yps label
+0.647 0.165 0.165 scb
+mark @m {Tf} (=) {Tf} (M) {CR} @length {Tf} (=) {Tf} (L) {CR} @width {Ts} {hS}
+(=) {Ts} {hS} (W) {/Times-Roman cf} ctmk 28 p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 90 <</p_yps -40 /p_xps2 -32 /p_xps 32 /p_xps1 48 /p_yps1 -32 /p_rot 270 >> /analoglib3::NPNModel libinst
+
+/analoglib3::ResModel {
+<</@substype (sub) (lindex {sub well} 0) pop /@subs (avdd) /@width (1u) /@length
+(1u) /p_yps2 -48 /p_xps2 32 /@model (resistor) /p_yps1 0 /p_xps1 32 /p_yps
+32 /p_xps 32 /p_rot 0 /@class (R) /@value (1.0) /@units (k) /@index (?) /p_jst
+20 >> begingate
+1 1.000 0 64 0 36 2 polygon
+1 1.000 0 -64 0 -36 2 polygon
+1 1.000 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @subs (=) @substype ( ) @width ( W=) @length ( L=) @units @value ( R=)
+@model ( %p1 %p2 ) @index @class (spice:) {/Times-Roman cf} ctmk 4 0 1.000 -208
+-160 infolabel
+(sim:r %p1 %p2) {/Times-Roman cf} 2 4 0 1.000 -208 -208 infolabel
+0.647 0.165 0.165 scb
+mark (W) {/Symbol cf} @units {hS} @value {/Times-Roman cf} ctmk p_jst p_rot
+0.700 p_xps1 p_yps1 label
+0.180 0.545 0.341 scb
+mark @index @class (pcb:) {/Times-Roman cf} ctmk 20 0 1.000 -208 -256 infolabel
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+0.647 0.165 0.165 scb
+mark @model {/Times-RomanISO cf} ctmk 16 p_rot 0.700 p_xps2 p_yps2 label
+endgate
+} def
+
+1.000 90 <</p_xps -32 /p_yps1 -32 /p_yps -16 /p_xps2 80 /p_yps2 -32 /p_rot 270 >> /analoglib3::ResModel libinst
+
+/analoglib3::MiMCap {
+<</@substype (sub) (lindex {sub well} 0) pop /@subs (agnd) /@fingers (1) /@length
+(1u) /@width (1u) /p_yps2 -8 /p_xps2 48 /p_yps1 24 /p_xps1 48 /p_yps
+56 /p_xps 48 /p_rot 0 /@class (C) /@value (1.0) /@units (p) /@index (?) /p_jst
+20 >> begingate
+1 1.000 0 -64 0 -6 2 polygon
+1 1.000 0 64 0 6 2 polygon
+1 1.000 -32 6 32 6 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @subs (=) @substype ( ) @fingers ( M=) @width ( W=) @length ( L=) @units
+@value ( %p1 %p2 MIM C=) @index (spice:C) {/Times-Roman cf} ctmk 4 0 1.000 -208
+-160 infolabel
+(sim:c %p1 %p2) {/Times-Roman cf} 2 4 0 1.000 -208 -208 infolabel
+0.647 0.165 0.165 scb
+mark (F) @units {hS} @value {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps1
+p_yps1 label
+0.180 0.545 0.341 scb
+mark @index (pcb:C) {/Times-Roman cf} ctmk 20 0 1.000 -208 -256 infolabel
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+0.647 0.165 0.165 scb
+mark @fingers {Tf} (=) {Tf} (M) {CR} @length {Tf} (=) {Tf} (L) {CR} @width {Ts}
+{hS} (=) {Ts} {hS} (W) {/Times-RomanISO cf} ctmk 28 p_rot 0.700 p_xps2 p_yps2
+label
+sce
+1 1.000 0 -80 74 66.000 114.000 xcarc
+endgate
+} def
+
+1.000 90 <</p_xps -48 /p_yps 24 /p_yps1 -24 /p_xps2 80 /p_yps2 -24 /p_rot 270 >> /analoglib3::MiMCap libinst
+
+/analoglib3::IndModel {
+<</@size (175u) /@width (2.5u) /@sep (2.5u) /@turns (6.5) /@substype (sub)
+(lindex {sub well} 0) pop /@subs (agnd) /p_yps2 -48 /p_xps2 32 /@model
+(inductor) /p_yps1 -16 /p_xps1 32 /p_yps 16 /p_xps 32 /@value (10) /@units (n) /@index
+(?) /p_jst 20 /p_rot 0 >> begingate
+1 1.000 20 -22 20 -38 0 -42 0 -18 spline
+1 1.000 -20 -14 -20 -26 0 -22 0 -18 spline
+1 1.000 20 38 20 22 0 18 0 42 spline
+1 1.000 20 18 20 2 0 -2 0 22 spline
+1 1.000 20 -2 20 -18 0 -22 0 2 spline
+1 1.000 -20 26 -20 14 0 18 0 22 spline
+1 1.000 -20 6 -20 -6 0 -2 0 2 spline
+1 1.000 0 -42 0 -64 2 polygon
+1 1.000 0 42 0 64 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @turns ( turns=) @sep ( sep=) @width ( width=) @size ( size=) @subs (=)
+@substype ( ) @units @value ( ind=) @model ( %p1 %p2 ) @index (spice:L)
+{/Times-Roman cf} ctmk 132 360 1.000 -208 -160 infolabel
+(sim:l %p1 %p2) {/Times-Roman cf} 2 4 0 1.000 -208 -208 infolabel
+0.647 0.165 0.165 scb
+mark (H) @units {hS} @value {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps1
+p_yps1 label
+0.180 0.545 0.341 scb
+mark @index (pcb:L) {/Times-Roman cf} ctmk 20 0 1.000 -208 -256 infolabel
+0.000 0.000 1.000 scb
+mark @index (L) {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+0.647 0.165 0.165 scb
+mark @model {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps2 p_yps2 label
+endgate
+} def
+
+1.000 90 <</p_rot 270 /p_yps1 -48 /p_xps1 48 /p_yps -16 /p_xps -48 /p_xps2 80 >> /analoglib3::IndModel libinst
+
+/analog::source {
+% hidden
+begingate
+1 1.000 0 0 32 0.000 360.000 xcarc
+1 1.000 0 32 0 64 2 polygon
+1 1.000 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/analoglib3::Vsource {
+<</p_yps 16 /p_xps 48 /p_rot 0 /@class (V) /@index (?) /@value (5) /p_jst 20 >> begingate
+1.000 360 0 0 analog::source
+(+) {/Symbol cf} 2 5 p_rot 1.000 0 14 label
+(-) {/Symbol cf} 2 5 p_rot 1.000 0 -22 label
+1.000 0.000 0.000 scb
+(v.p) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(v.m) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @value ( %pv.p %pv.m ) @index @class (spice:) {/Times-Roman cf} ctmk 20
+360 1.000 -96 -160 infolabel
+0.647 0.165 0.165 scb
+mark (V) {hS} @value {/Times-Roman cf} ctmk p_jst p_rot 0.700 48 -16 label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps p_yps label
+endgate
+} def
+
+1.000 270 <</p_xps -48 /p_yps -16 /p_rot 270 >> /analoglib3::Vsource libinst
+
+/analoglib2::sinusoid {
+% hidden
+begingate
+1 0.800 0 -48 0 48 -16 0 16 0 spline
+endgate
+} def
+
+/analoglib3::ACsource {
+<</p_yps1 -24 /p_xps1 48 /p_yps 32 /p_xps 48 /p_rot 0 /@index (?) /@value (5) /@offset
+(0) /@freq (1) /@units (k) /p_jst 20 >> begingate
+1.000 0 0 0 analog::source
+1.000 0.000 0.000 scb
+(s.p) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(s.m) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark (\)) @units @freq ( ) @value ( ) @offset ( %ps.p %ps.m SIN\() @index
+(spice:V) {/Times-Roman cf} ctmk 20 0 1.000 -336 -160 infolabel
+0.647 0.165 0.165 scb
+mark (Hz) @units {hS} @freq {CR} (offset) {ss} (V) {hS} @offset {CR} (p-p) {ss}
+(V) {hS} @value {/Times-Roman cf} ctmk p_jst p_rot 0.750 p_xps1 p_yps1 label
+sce
+1.000 p_rot 0 0 analoglib2::sinusoid
+0.000 0.000 1.000 scb
+mark @index (V) {/Times-RomanISO cf} ctmk 16 p_rot 0.700 p_xps p_yps label
+endgate
+} def
+
+1.000 90 <</p_xps -48 /p_yps -16 /p_xps1 80 /p_yps1 -40 /p_rot 270 >> /analoglib3::ACsource libinst
+
+/analoglib3::Vpwl {
+<</p_yps1 -16 /p_xps1 48 /@pwl (0 0 1u 5 2u 5 3u 0) /p_jst 20 /@index (?) /@class
+(V) /p_rot 0 /p_xps 48 /p_yps 16 >> begingate
+1.000 360 0 0 analog::source
+(+) {/Symbol cf} 2 5 p_rot 1.000 0 14 label
+(-) {/Symbol cf} 2 5 p_rot 1.000 0 -22 label
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps p_yps label
+0.180 0.545 0.341 scb
+mark (\)) @pwl ( %p1 %p2 PWL\() @index @class (spice:) {/Times-Roman cf} ctmk
+16 0 1.000 -304 -176 infolabel
+0.647 0.165 0.165 scb
+mark @pwl {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 270 <</p_yps1 -112 /p_rot 270 /p_xps -56 /p_yps -16 /p_xps1 56 >> /analoglib3::Vpwl libinst
+
+/analoglib3::Capacitor {
+<</p_yps1 16 /p_xps1 48 /p_yps -16 /p_xps 48 /@class (C) /@value (1.0) /@units
+(p) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.000 0 -64 0 -6 2 polygon
+1 1.000 0 64 0 6 2 polygon
+1 1.000 -32 6 32 6 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @units @value ( %p1 %p2 ) @index @class (spice:) {/Times-Roman cf} ctmk 4
+0 1.000 -208 -160 infolabel
+(sim:e %p1 %p2) {/Times-Roman cf} 2 4 0 1.000 -208 -208 infolabel
+0.647 0.165 0.165 scb
+mark (F) @units {hS} @value {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps
+p_yps label
+0.180 0.545 0.341 scb
+mark @index @class (pcb:) {/Times-Roman cf} ctmk 20 0 1.000 -208 -256 infolabel
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk 20 p_rot 0.700 p_xps1 p_yps1 label
+sce
+1 1.000 -32 -6 32 -6 2 polygon
+endgate
+} def
+
+1.000 90 <</p_xps 56 /p_yps1 -16 /p_xps1 -56 /p_yps -32 /p_rot 270 >> /analoglib3::Capacitor libinst
+
+/analoglib3::Resistor {
+<</@class (R) /@value (1.0) /@units (k) /@index (?) /p_jst 20 /p_rot 0 /p_xps
+32 /p_yps -16 /p_xps1 32 /p_yps1 16 >> begingate
+1 1.000 0 64 0 36 2 polygon
+1 1.000 0 -64 0 -36 2 polygon
+1 1.000 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark @units @value ( %p1 %p2 ) @index @class (spice:) {/Times-Roman cf} ctmk 4
+0 1.000 -208 -160 infolabel
+mark @index @class (pcb:) {/Times-Roman cf} ctmk 20 0 1.000 -208 -256 infolabel
+(sim:r %p1 %p2) {/Times-Roman cf} 2 4 0 1.000 -208 -208 infolabel
+0.647 0.165 0.165 scb
+mark (W) {/Symbol cf} @units {hS} @value {/Times-Roman cf} ctmk p_jst p_rot
+0.700 p_xps p_yps label
+0.000 0.000 1.000 scb
+mark @index @class {/Times-Roman cf} ctmk p_jst p_rot 0.700 p_xps1 p_yps1 label
+endgate
+} def
+
+1.000 90 <</p_yps1 -16 /p_xps1 -32 /p_yps -32 /p_rot 270 >> /analoglib3::Resistor libinst
+
+/generic::circle {
+% trivial
+begingate
+1 1.000 16 0 6 0.000 360.000 xcarc
+1 1.000 0 0 10 0 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.000 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.000 0 0 pinlabel
+endgate
+} def
+
+/analoglib3::Switch {
+<</@model (switch) /@class (S) /@index (?) >> begingate
+1 1.300 32 32 2 -43 2 polygon
+1 0.600 8 -24 57 49.000 90.000 xcarc
+-1.000 90 0 -64 generic::circle
+1.000 90 0 48 generic::circle
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.000 0 48 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.000 0 -64 pinlabel
+sce
+1 1.000 32 -16 96 -16 2 polygon
+-1.000 270 16 -16 generic::arrowhead
+1.000 0.000 0.000 scb
+(3) {/Times-Roman cf} 2 20 0 1.000 96 -16 pinlabel
+(4) {/Times-Roman cf} 2 20 0 1.000 96 -48 pinlabel
+0.180 0.545 0.341 scb
+mark @model ( %p1 %p2 %p3 %p4 ) @index @class (spice1:) {/Times-Roman cf} ctmk
+16 0 0.700 -128 -192 infolabel
+sce
+(+) {/Symbol cf} 2 17 0 0.700 96 -8 label
+(-) {/Symbol cf} 2 17 0 0.700 96 -40 label
+1 1.000 96 -48 72 -48 72 -64 3 polygon
+1 1.000 54 -64 90 -64 2 polygon
+1 1.000 62 -72 82 -72 2 polygon
+1 1.000 70 -80 74 -80 2 polygon
+0.180 0.545 0.341 scb
+mark ( sw) @model (spice@1:.model ) {/Times-Roman cf} ctmk 16 0 0.700 -128 -160
+infolabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/asg_spice.lps b/lib/asg_spice.lps
new file mode 100644
index 0000000..a0c2dc9
--- /dev/null
+++ b/lib/asg_spice.lps
@@ -0,0 +1,311 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: asg_spice
+% Author: R. Timothy Edwards <tim@opencircuitdesign.com>
+%
+
+% Depend VAMP source
+% Depend IAMP source arrowhead
+% Depend ACAMP source sinusoid
+
+% XCircuitLib library objects for ASG SPICE
+/CAPC {
+<< /value (1.0) /units (p) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:C) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:c %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (F) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:C) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /CAPC libinst
+
+/RESTR {
+<< /value (1.0) /units (k) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:R) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:r %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (W) {/Symbol cf} units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 32 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:R) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /RESTR libinst
+
+/INDR {
+<< /value (1.0) /units (m) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 20 -28 20 -44 0 -48 0 -24 spline
+1 1.00 -20 -20 -20 -32 0 -28 0 -24 spline
+1 1.00 20 32 20 16 0 12 0 36 spline
+1 1.00 20 12 20 -4 0 -8 0 16 spline
+1 1.00 20 -8 20 -24 0 -28 0 -4 spline
+1 1.00 -20 20 -20 8 0 12 0 16 spline
+1 1.00 -20 0 -20 -12 0 -8 0 -4 spline
+1 1.00 0 -48 0 -64 2 polygon
+1 1.00 0 36 0 48 2 polygon
+1.000 0.000 0.000 scb
+(1) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value ( %p1 %p2 ) @index (spice:L) {/Times-Roman cf} ctmk 4 0 1.00 -208 -160
+infolabel
+(sim:l %p1 %p2) {/Times-Roman cf} 2 4 0 1.00 -208 -208 infolabel
+sce
+mark (H) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 32 0 label
+0.180 0.545 0.341 scb
+mark @index (pcb:L) {/Times-Roman cf} ctmk 20 0 1.00 -208 -256 infolabel
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /Inductor libinst
+
+/source {
+% hidden
+begingate
+1 1.00 0 0 32 0.00 360.00 xcarc
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+endgate
+} def
+
+/VAMP {
+<< /value (5) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 source
+(+) {/Symbol cf} 2 5 p_rot 1.00 0 18 label
+(-) {/Symbol cf} 2 5 p_rot 1.00 0 -18 label
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(1) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark value (spice:V%i %pP %pM ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (V) {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /VAMP libinst
+
+/arrowhead {
+% trivial
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/IAMP {
+<< /value (1) /units (m) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 source
+1 0.75 0 20 0 -8 2 polygon
+0.80 180 0 -20 arrowhead
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(1) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark units value (spice:I%i %pP %pM ) {/Times-Roman cf} ctmk 20 0 1.00 -96 -160
+infolabel
+sce
+mark (A) units {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /IAMP libinst
+
+/sinusoid {
+% hidden
+begingate
+1 0.80 0 -48 0 48 -16 0 16 0 spline
+endgate
+} def
+
+/ACAMP {
+<< /value (5) /offset (0) /freq (1) /units (k) /p_jst 20 /p_rot 0 >> begingate
+1.00 0 0 0 source
+1.000 0.000 0.000 scb
+(P) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(M) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark (\)) units freq ( ) value ( ) offset (spice:V%i %pP %pM SIN\()
+{/Times-Roman cf} ctmk 20 0 1.00 -336 -160 infolabel
+sce
+mark (Hz) units {hS} freq {CR} (offset) {ss} (V) {hS} offset {CR} (p-p)
+{ss} (V) {hS} value {/Times-Roman cf} ctmk p_jst p_rot 1.00 48 0 label
+1.00 p_rot 0 0 sinusoid
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /ACAMP libinst
+
+/NMOS3 {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS GND ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -244 -139 infolabel
+mark ( %x %y) width ( ) length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-244 -187 infolabel
+sce
+mark length (=) {Tf} (L) {hS} {CR} width (=) {Ts} (W) {/Times-Roman cf} ctmk p_jst
+p_rot 1.00 16 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /NMOS3 libinst
+
+/PMOS3 {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS Vdd ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -196 -139 infolabel
+mark ( %x %y) width ( ) length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-196 -187 infolabel
+sce
+mark length (=) {Tf} (L) {hS} {CR} width (=) {Ts} (W) {/Times-Roman cf} ctmk p_jst
+p_rot 1.00 16 0 label
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /PMOS3 libinst
+
+/MSFET {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -44 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS %pB ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -244 -139 infolabel
+mark ( %x %y) width ( ) length (sim:n %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-244 -187 infolabel
+sce
+mark length (/) width (W/L=) {/Times-Roman cf} ctmk p_jst p_rot 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /MSFET libinst
+
+/PMOS {
+<< /width (3) /length (2) /model (nmos) /@index (?) /p_jst 20 /p_rot 0 >> begingate
+1 1.00 -44 -28 -44 28 2 polygon
+1 1.00 -60 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -32 -28 -32 28 0 28 0 64 6 polygon
+1 1.00 -52 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(B) {/Times-Roman cf} 2 4 0 1.00 32 0 pinlabel
+0.180 0.545 0.341 scb
+mark length ( L=) width ( W=) model ( %pD %pG %pS %pB ) @index (spice:M) {/Times-Roman cf}
+ctmk 4 0 1.00 -196 -139 infolabel
+mark ( %x %y) width ( ) length (sim:p %pG %pD %pS ) {/Times-Roman cf} ctmk 4 0 1.00
+-196 -187 infolabel
+sce
+mark length (/) width (W/L=) {/Times-Roman cf} ctmk p_jst p_rot 1.00 16 32 label
+1 1.00 -32 0 32 0 2 polygon
+endgate
+} def
+
+1.00 270 << /p_jst 17 /p_rot 90 >> /PMOS libinst
+
+/NPN {
+<< /model (npn) /@index (?) >> begingate
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 120 0 -48 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+mark model ( %pC %pB %pE ) @index (spice:Q) {/Times-Roman cf} ctmk 4 0 1.00 -244 -139
+infolabel
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/PNP {
+<< /model (npn) /@index (?) >> begingate
+1 1.00 -48 0 -64 0 2 polygon
+1 1.00 -48 48 -48 -48 2 polygon
+1 1.00 0 48 -48 22 2 polygon
+1 1.00 0 48 0 64 2 polygon
+1 1.00 0 -48 -48 -22 2 polygon
+1 1.00 0 -48 0 -64 2 polygon
+1.00 240 -48 22 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(E) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+mark model ( %pC %pB %pE ) @index (spice:Q) {/Times-Roman cf} ctmk 4 0 1.00 -244 -139
+infolabel
+endgate
+} def
+
+/DIODE {
+<< /@index (?) >> begingate
+248 1.00 -18 -16 0 16 18 -16 3 polygon
+1 1.00 0 -48 0 -16 2 polygon
+1 1.00 0 48 0 16 2 polygon
+1 1.00 -18 16 18 16 2 polygon
+1.000 0.000 0.000 scb
+(P) {/Times-Roman cf} 2 9 0 1.00 0 48 pinlabel
+(M) {/Times-Roman cf} 2 13 0 1.00 0 -48 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:D) {/Times-Roman cf} ctmk 20 0 1.00 -64 -144 infolabel
+mark ( %pP %pM diode) @index (spice:D) {/Times-Roman cf} ctmk 4 0 1.00 -64 -192
+infolabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/avlsi.lps b/lib/avlsi.lps
new file mode 100644
index 0000000..f9f9b7b
--- /dev/null
+++ b/lib/avlsi.lps
@@ -0,0 +1,41 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: avlsi
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+
+% XCircuitLib library built-in objects
+
+/avlsi::samp {
+% trivial
+begingate
+0 1.0 -80 -80 -80 80 80 0 3 polygon
+0 -40 0 -80 wire
+(-) {/Symbol cf} 1 5 0 1.0 -61 42 label
+(+) {/Symbol cf} 1 5 0 1.0 -61 -50 label
+1 0 0 scb
+(in.m) {/Times-Roman cf} 1 7 0 1.0 -80 48 pinlabel
+(in.p) {/Times-Roman cf} 1 7 0 1.0 -80 -48 pinlabel
+(out) {/Times-Roman cf} 1 4 0 1.0 80 0 pinlabel
+(bias) {/Times-Roman cf} 1 13 0 1.0 0 -80 pinlabel
+sce
+endgate
+} def
+
+/avlsi::wramp {
+% trivial
+begingate
+0 1.0 -80 -80 -80 80 48 24 48 -24 4 polygon
+0 -80 0 -45 wire
+48 0 80 0 wire
+(-) {/Symbol cf} 1 5 0 1.0 -61 42 label
+(+) {/Symbol cf} 1 5 0 1.0 -61 -50 label
+1 0 0 scb
+(in.m) {/Times-Roman cf} 1 7 0 1.0 -80 48 pinlabel
+(in.p) {/Times-Roman cf} 1 7 0 1.0 -80 -48 pinlabel
+(out) {/Times-Roman cf} 1 4 0 1.0 80 0 pinlabel
+(bias) {/Times-Roman cf} 1 13 0 1.0 0 -80 pinlabel
+sce
+endgate
+} def
+
+% EndLib
diff --git a/lib/digital.lps b/lib/digital.lps
new file mode 100644
index 0000000..6c92c50
--- /dev/null
+++ b/lib/digital.lps
@@ -0,0 +1,190 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: digital
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+
+% XCircuitLib library built-in objects
+
+/digital::nand {
+% trivial
+begingate
+1 1.0 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.0 56 0 8 0 360 xcarc
+1 1.0 0 0 48 -90 90 xcarc
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -64 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -64 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::nor {
+% trivial
+begingate
+-64 48 -35 48 wire
+-64 -48 -35 -48 wire
+1 1.0 -128 0 80 -37 37 xcarc
+1 1.0 56 0 8 0 360 xcarc
+1 1.0 -35 -48 96 30 90 xcarc
+1 1.0 -35 48 96 270 330 xcarc
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -56 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -56 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::invert {
+% trivial
+begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 48 0 8 0.00 360.00 xcarc
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 56 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In) {/Times-Roman cf} 1 7 0 1.0 -48 0 pinlabel
+sce
+endgate
+} def
+
+/digital::and {
+% trivial
+begingate
+1 1.0 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.0 0 0 48 -90 90 xcarc
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 48 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -64 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -64 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::or {
+% trivial
+begingate
+1 1.0 -19 -48 96 30 90 xcarc
+1 1.0 -19 48 96 270 330 xcarc
+1 1.0 -112 0 80 -37 37 xcarc
+-48 48 -19 48 wire
+-48 -48 -19 -48 wire
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -40 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -40 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::buffer {
+% trivial
+begingate
+0 1.0 -32 -40 -32 40 40 0 3 polygon
+-32 0 -48 0 wire
+40 0 64 0 wire
+1.000 0.000 0.000 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In) {/Times-Roman cf} 1 7 0 1.0 -48 0 pinlabel
+sce
+endgate
+} def
+
+/digital::xor {
+% trivial
+begingate
+1 1.0 -19 -48 96 30 90 xcarc
+1 1.0 -19 48 96 270 330 xcarc
+1 1.0 -128 0 80 -37 37 xcarc
+1 1.0 -112 0 80 -37 37 xcarc
+-48 48 -19 48 wire
+-48 -48 -19 -48 wire
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 64 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -56 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -56 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::xnor {
+% trivial
+begingate
+1 1.0 72 0 8 0 360 xcarc
+1 1.0 -19 -48 96 30 90 xcarc
+1 1.0 -19 48 96 270 330 xcarc
+1 1.0 -128 0 80 -37 37 xcarc
+1 1.0 -112 0 80 -37 37 xcarc
+-48 48 -19 48 wire
+-48 -48 -19 -48 wire
+1 0 0 scb
+(Out) {/Times-Roman cf} 1 4 0 1.0 80 0 pinlabel
+(In.1) {/Times-Roman cf} 1 7 0 1.0 -56 32 pinlabel
+(In.2) {/Times-Roman cf} 1 7 0 1.0 -56 -32 pinlabel
+sce
+endgate
+} def
+
+/digital::5V {
+% trivial
+begingate
+-32 0 32 0 wire
+0 0 0 -32 wire
+(V) {/Times-Roman cf} (+5) {/Symbol cf} 2 17 0 0.9 0 8 label
+0.933 0.604 0 scb
+(dVdd) {/Times-Roman cf} 1 13 0 1.0 0 -32 pinglobal
+sce
+endgate
+} def
+
+/analog::gnd {
+% trivial
+begingate
+0 0 0 -32 wire
+-32 -32 32 -32 wire
+-18 -46 18 -46 wire
+-4 -60 4 -60 wire
+0.933 0.604 0 scb
+(GND) {/Times-Roman cf} 1 1 0 1.0 0 0 pinglobal
+sce
+endgate
+} def
+
+/digital::battery {
+% trivial
+begingate
+-32 32 32 32 wire
+0 64 0 32 wire
+-16 12 16 12 wire
+-16 -28 16 -28 wire
+-32 -8 32 -8 wire
+0 -64 0 -28 wire
+1 0 0 scb
+(b.p) {/Times-Roman cf} 1 9 0 1.0 0 64 pinlabel
+(b.m) {/Times-Roman cf} 1 13 0 1.0 0 -64 pinlabel
+sce
+endgate
+} def
+
+/digital::passtrans {
+% trivial
+begingate
+0 1.0 -64 48 0 -48 64 48 3 polygon
+0 1.0 0 48 -64 -48 64 -48 3 polygon
+-50 0 -80 0 wire
+32 0 80 0 wire
+0 48 0 64 wire
+0 -48 0 -64 wire
+1 1.0 -42 0 8 0 360 xcarc
+1 0 0 scb
+(c.p) {/Times-Roman cf} 1 7 0 1.0 -80 0 pinlabel
+(c.n) {/Times-Roman cf} 1 4 0 1.0 80 0 pinlabel
+(p.1) {/Times-Roman cf} 1 9 0 1.0 0 64 pinlabel
+(p.2) {/Times-Roman cf} 1 13 0 1.0 0 -64 pinlabel
+sce
+endgate
+} def
+
+% EndLib
diff --git a/lib/digitallib.lps b/lib/digitallib.lps
new file mode 100644
index 0000000..1fafdb6
--- /dev/null
+++ b/lib/digitallib.lps
@@ -0,0 +1,352 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.6
+% Library name is: digitallib.lps
+% Author: R. Timothy Edwards <tim.edwards@multigig.com>
+%
+
+% XCircuitLib library objects
+/digitallib::INV {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () /strength (1) >> begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 48 0 8 0.00 360.00 xcarc
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 56 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -48 0 pinlabel
+0.180 0.545 0.341 scb
+mark voltage strength ( %pA %pY INVX) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -32 -136 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -32 -96 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.60 -8 0 label
+mark strength {qS} (\327) {/Times-RomanISO cf} ctmk 16 0 0.60 0 24 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 8 -24 label
+endgate
+} def
+
+<</strength (2) >> /digitallib::INV libinst
+<</strength (4) >> /digitallib::INV libinst
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::INV libinst
+<</voltage (_3V) /strength (2) /vdd (dvdd3) >> /digitallib::INV libinst
+<</voltage (_3V) /strength (4) /vdd (dvdd3) >> /digitallib::INV libinst
+
+/digitallib::BUF {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () /strength (2) >> begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 40 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -48 0 pinlabel
+0.180 0.545 0.341 scb
+mark voltage strength ( %pA %pY BUFX) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -32 -112 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -32 -80 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-RomanISO cf} ctmk 21 0 0.50 -8 0 label
+mark strength {qS} (\327) {/Times-RomanISO cf} ctmk 16 0 0.50 8 24 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 16 0 0.60 24 -32 label
+endgate
+} def
+
+<</strength (4) >> /digitallib::BUF libinst
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::BUF libinst
+<</voltage (_3V) /strength (4) /vdd (dvdd3) >> /digitallib::BUF libinst
+
+/digitallib::NAND2 {
+<</gnd (dgnd) /vdd (dvdd) /voltage () /@index (?) >> begingate
+1 1.00 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 0 0 48 -90.00 90.00 xcarc
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+sce
+1 1.00 -64 -48 -64 48 2 polygon
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pY NAND2X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+0.180 0.545 0.341 scb
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NAND2 libinst
+
+/digitallib::NAND3 {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () >> begingate
+1 1.00 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 0 0 48 -90.00 90.00 xcarc
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+(C) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+sce
+1 1.00 -64 -64 -64 64 2 polygon
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pC %pY NAND3X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NAND3 libinst
+
+/digitallib::NAND4 {
+<</gnd (dgnd) /vdd (dvdd) /voltage () /@index (?) >> begingate
+1 1.00 0 -64 -64 -64 -64 64 0 64 4 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 0 0 48 64 -90.00 90.00 ellipse
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 48 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 16 pinlabel
+(C) {/Times-Roman cf} 2 7 0 1.00 -64 -16 pinlabel
+(D) {/Times-Roman cf} 2 7 0 1.00 -64 -48 pinlabel
+sce
+1 1.00 -64 -80 -64 80 2 polygon
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pC %pD %pY NAND4X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -144 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -112 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NAND4 libinst
+
+/digitallib::NOR2 {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () >> begingate
+1 1.00 56 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pY NOR2X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+sce
+1 1.00 -35 48 96 270.00 330.00 xcarc
+1 1.00 -64 -48 -35 -48 2 polygon
+1 1.00 -128 0 80 -37.00 37.00 xcarc
+1 1.00 -35 -48 96 30.00 90.00 xcarc
+1 1.00 -64 48 -35 48 2 polygon
+1 1.00 -64 32 -56 32 2 polygon
+1 1.00 -64 -32 -56 -32 2 polygon
+0.180 0.545 0.341 scb
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NOR2 libinst
+
+/digitallib::NOR3 {
+<</voltage () /@index (?) /vdd (dvdd) /gnd (dgnd) >> begingate
+1 1.00 56 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pC %pY NOR3X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+sce
+1 1.00 -35 48 96 270.00 330.00 xcarc
+1 1.00 -64 -48 -35 -48 2 polygon
+1 1.00 -128 0 80 -36.87 36.87 xcarc
+1 1.00 -35 -48 96 30.00 90.00 xcarc
+1 1.00 -64 48 -35 48 2 polygon
+1 1.00 -64 32 -56 32 2 polygon
+1 1.00 -64 -32 -56 -32 2 polygon
+1 1.00 -48 0 -64 0 2 polygon
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+sce
+1 1.00 -64 48 -64 64 2 polygon
+1 1.00 -64 -48 -64 -64 2 polygon
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NOR3 libinst
+
+/digitallib::NOR4 {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () >> begingate
+1 1.00 56 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 48 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 16 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pC %pD %pY NOR4X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 21 0 0.70 -8 -16 label
+sce
+1 1.00 -64 48 -58 48 2 polygon
+1 1.00 -64 -16 -48 -16 2 polygon
+1 1.00 -48 16 -64 16 2 polygon
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 7 0 1.00 -64 -16 pinlabel
+sce
+1 1.00 32 32 0 56 -40 56 48 0 spline
+1 1.00 32 -32 0 -56 -40 -56 48 0 spline
+1 1.00 -40 32 -40 -24 -64 -56 -64 56 spline
+1 1.00 -64 56 -40 56 2 polygon
+1 1.00 -64 -56 -40 -56 2 polygon
+1.000 0.000 0.000 scb
+(D) {/Times-Roman cf} 2 7 0 1.00 -64 -48 pinlabel
+sce
+1 1.00 -64 -48 -60 -48 2 polygon
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::NOR4 libinst
+
+/digitallib::OR2 {
+<</voltage () /@index (?) /vdd (dvdd) /gnd (dgnd) >> begingate
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -64 -32 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pY OR2X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -64 -128 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -64 -96 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.70 -40 -8 label
+sce
+1 1.00 -35 48 96 270.00 330.00 xcarc
+1 1.00 -64 -48 -35 -48 2 polygon
+1 1.00 -128 0 80 -37.00 37.00 xcarc
+1 1.00 -35 -48 96 30.00 90.00 xcarc
+1 1.00 -64 48 -35 48 2 polygon
+1 1.00 -64 32 -56 32 2 polygon
+1 1.00 -64 -32 -56 -32 2 polygon
+1 1.00 48 0 64 0 2 polygon
+endgate
+} def
+
+/digitallib::TBUF {
+<</strength (2) /voltage () /@index (?) /vdd (dvdd) /gnd (dgnd) >> begingate
+0 1.00 -32 -40 -32 40 40 0 3 polygon
+1 1.00 -32 0 -48 0 2 polygon
+1 1.00 40 0 64 0 2 polygon
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 0 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -48 0 pinlabel
+0.180 0.545 0.341 scb
+mark voltage strength ( %pA %pY %pEn TBUFX) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -176 -112 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -176 -80 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-RomanISO cf} ctmk 21 0 0.50 -8 0 label
+mark strength {qS} (\327) {/Times-RomanISO cf} ctmk 16 0 0.50 8 24 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 16 0 0.60 24 -32 label
+sce
+1 1.00 0 24 0 48 2 polygon
+1.000 0.000 0.000 scb
+(En) {/Times-Roman cf} 2 17 0 1.00 0 48 pinlabel
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::TBUF libinst
+
+/digitallib::MUX2 {
+<</gnd (dgnd) /vdd (dvdd) /@index (?) /voltage () >> begingate
+1 1.00 -16 16 -32 16 2 polygon
+1 1.00 48 -16 64 -16 2 polygon
+1.000 0.000 0.000 scb
+(Y) {/Times-Roman cf} 2 4 0 1.00 64 -16 pinlabel
+(A) {/Times-Roman cf} 2 7 0 1.00 -32 16 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pA %pB %pY %pS MUX2X1) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -128 -176 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -128 -144 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-RomanISO cf} ctmk 21 0 0.50 16 -16 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 28 0 0.60 24 -80 label
+sce
+1 1.00 16 32 16 64 2 polygon
+1.000 0.000 0.000 scb
+(S) {/Times-Roman cf} 2 17 0 1.00 16 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -32 -48 pinlabel
+sce
+1 1.00 -32 -48 -16 -48 2 polygon
+1 1.00 -16 48 48 16 48 -48 -16 -80 -16 48 5 polygon
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::MUX2 libinst
+
+/digitallib::LATCH {
+<</@index (?) /voltage () /vdd (dvdd) /gnd (dgnd) >> begingate
+1.000 0.000 0.000 scb
+(Q) {/Times-Roman cf} 2 4 0 1.00 32 32 pinlabel
+(D) {/Times-Roman cf} 2 7 0 1.00 -64 32 pinlabel
+(CLK) {/Times-Roman cf} 2 13 0 1.00 -16 -48 pinlabel
+0.180 0.545 0.341 scb
+mark voltage ( %pCLK %pD %pQ LATCH) gnd ( ) vdd ( ) @index (spice:X)
+{/Times-Roman cf} ctmk 16 360 0.70 -192 -160 infolabel
+mark (.cir) voltage (spice@1:%F$XCIRCUIT_LIB_DIR/standard_cells) {/Times-Roman cf}
+ctmk 16 0 0.70 -192 -128 infolabel
+0.647 0.165 0.165 scb
+mark voltage {/Times-Roman cf} ctmk 21 0 0.70 -16 64 label
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-RomanISO cf} ctmk 17 0 0.70 -16 128 label
+sce
+0 1.00 -64 -48 -64 112 32 112 32 -48 4 polygon
+1 1.00 -32 -48 -16 -32 0 -48 3 polygon
+(D) {/Times-Roman cf} 2 21 0 0.70 -48 32 label
+(Q) {/Times-Roman cf} 2 21 0 0.70 16 32 label
+0.000 0.000 1.000 scb
+(LATCH) {/Times-Roman cf} 2 29 0 0.70 -16 96 label
+endgate
+} def
+
+<</voltage (_3V) /vdd (dvdd3) >> /digitallib::LATCH libinst
+
+% EndLib
diff --git a/lib/digitaltcl.lps b/lib/digitaltcl.lps
new file mode 100644
index 0000000..4cb9c49
--- /dev/null
+++ b/lib/digitaltcl.lps
@@ -0,0 +1,43 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: digital
+% Author: R. Timothy Edwards <tim.edwards@multigig.com>
+
+% XCircuitLib library built-in objects
+
+/digital::LED {
+% nonetwork
+<</p_col6 {0 0 0 }
+(switch -glob @digit {[1,4,7] {color value @offcolor} default {expr @p_color}})
+pop /p_col5 {0 0 0 }
+(switch @digit {2 {color value @offcolor} default {expr @p_color}})
+pop /p_col4 {0 0 0 }
+(switch -glob @digit {[0,2,6,8] {expr @p_color} default {color value @offcolor}})
+pop /p_col3 {1.000 1.000 1.000 }
+(switch -glob @digit {[0-1,7] {color value @offcolor} default {expr @p_color}})
+pop /p_col2 {0 0 0 }
+(switch -glob @digit {[5-6] {color value @offcolor} default {expr @p_color}})
+pop /p_col1 {0 0 0 }
+(switch -glob @digit {[1-3,7] {color value @offcolor} default {expr @p_color}})
+pop /p_col {0 0 0 }
+(switch @digit {1 - 4 {color value @offcolor} default {expr @p_color}})
+pop /@offcolor (white) /@digit (0)
+(lindex {0 1 2 3 4 5 6 7 8 9} 0) pop >> begingate
+p_col4 scb
+496 1.000 -36 -53 -28 -66 -20 -58 -20 -10 -28 -2 -36 -10 6 polygon
+p_col1 scb
+496 1.000 -36 10 -28 2 -20 10 -20 58 -28 66 -36 58 6 polygon
+p_col2 scb
+496 1.000 20 10 28 2 36 10 36 58 28 66 20 58 6 polygon
+p_col5 scb
+496 1.000 20 -58 28 -66 36 -58 36 -10 28 -2 20 -10 6 polygon
+p_col6 scb
+496 1.000 -26 -68 -18 -60 18 -60 26 -68 18 -76 -18 -76 6 polygon
+p_col3 scb
+496 1.000 -26 0 -18 8 18 8 26 0 18 -8 -18 -8 6 polygon
+p_col scb
+496 1.000 -26 68 -18 76 18 76 26 68 18 60 -18 60 6 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/courier.lps b/lib/fonts/courier.lps
new file mode 100644
index 0000000..26a7cba
--- /dev/null
+++ b/lib/fonts/courier.lps
@@ -0,0 +1,1825 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Cr
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/Cr::nullchar {
+% 0 0 24 32 bbox
+begingate
+0 1.00 0 0 0 32 24 32 24 0 4 polygon
+endgate
+} def
+
+/Cr::space {
+% 0 0 24 26 bbox
+begingate
+endgate
+} def
+
+/Cr::exclam {
+% 10 1 14 22 bbox
+begingate
+241 1.00 12 3 2 0.00 360.00 xcarc
+0 1.00 13 23 12 8 11 23 3 polygon
+endgate
+} def
+
+/Cr::quote {
+% 9 21 15 7 bbox
+begingate
+0 1.00 16 28 15 21 14 28 3 polygon
+0 1.00 11 28 10 21 9 28 3 polygon
+endgate
+} def
+
+/Cr::pound {
+% 2 0 22 26 bbox
+begingate
+1 1.00 4 17 21 17 2 polygon
+1 1.00 12 0 19 26 2 polygon
+1 1.00 4 0 11 26 2 polygon
+1 1.00 2 9 19 9 2 polygon
+endgate
+} def
+
+/Cr::dollar {
+% 5 0 19 30 bbox
+begingate
+1 1.00 5 8 7 6 11 4 15 4 19 6 21 8 21 10 19 12 7 18 5 20 5 22 7 24 11 26 15 26
+19 24 21 22 16 polygon
+1 1.00 13 0 13 4 2 polygon
+1 1.00 5 9 5 6 2 polygon
+1 1.00 21 25 21 21 2 polygon
+1 1.00 13 26 13 30 2 polygon
+endgate
+} def
+
+/Cr::percent {
+% 4 4 20 18 bbox
+begingate
+1 1.00 14 7 3 0.00 360.00 xcarc
+1 1.00 7 19 3 0.00 360.00 xcarc
+1 1.00 4 8 17 18 2 polygon
+endgate
+} def
+
+/Cr::ampersand {
+% 8 0 16 26 bbox
+% hidden
+begingate
+1 1.00 24 0 10 20 10 24 12 26 16 26 18 24 6 polygon
+1 1.00 24 10 22 6 19 1 16 0 13 0 10 2 8 5 8 10 10 13 13 15 10 polygon
+endgate
+} def
+
+/Cr::apostrophe {
+% 12 20 12 8 bbox
+begingate
+0 1.00 12 20 16 28 14 28 3 polygon
+endgate
+} def
+
+/Cr::lparen {
+% 14 -4 10 32 bbox
+% hidden
+begingate
+1 1.00 20 -4 16 1 14 7 14 17 16 23 20 28 6 polygon
+endgate
+} def
+
+/Cr::rparen {
+% 8 -5 16 32 bbox
+begingate
+1 1.00 8 -5 12 0 14 6 14 16 12 22 8 27 6 polygon
+endgate
+} def
+
+/Cr::asterisk {
+% 8 13 16 7 bbox
+begingate
+1 1.00 12 16 12 20 2 polygon
+1 1.00 12 16 16 18 2 polygon
+1 1.00 12 16 8 18 2 polygon
+1 1.00 12 16 15 13 2 polygon
+1 1.00 12 16 9 13 2 polygon
+endgate
+} def
+
+/Cr::plus {
+% 4 8 20 16 bbox
+begingate
+1 1.00 12 8 12 24 2 polygon
+1 1.00 4 16 20 16 2 polygon
+endgate
+} def
+
+/Cr::comma {
+% 10 -4 14 8 bbox
+begingate
+0 1.00 12 4 10 -4 14 4 3 polygon
+endgate
+} def
+
+/Cr::minus {
+% 4 16 20 0 bbox
+begingate
+1 1.00 4 16 20 16 2 polygon
+endgate
+} def
+
+/Cr::period {
+% 10 1 14 4 bbox
+begingate
+241 1.00 12 3 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::slash {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 0 20 26 2 polygon
+endgate
+} def
+
+/Cr::zero {
+% 6 0 18 26 bbox
+% hidden
+begingate
+1 1.00 12 0 8 4 6 10 6 16 8 22 12 26 18 26 22 22 24 16 24 10 22 4 18 0 12 0
+13 polygon
+endgate
+} def
+
+/Cr::one {
+% 8 0 16 26 bbox
+begingate
+1 1.00 8 0 16 0 2 polygon
+1 1.00 12 0 12 26 8 24 3 polygon
+endgate
+} def
+
+/Cr::two {
+% 4 0 20 26 bbox
+begingate
+1 1.00 22 4 22 0 4 0 12 6 20 12 22 16 22 20 20 24 16 26 12 26 8 24 6 22
+12 polygon
+endgate
+} def
+
+/Cr::three {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 14 0 18 2 20 6 20 10 16 14 14 14 9 polygon
+1 1.00 16 14 20 18 20 20 18 24 14 26 10 26 6 24 6 24 8 polygon
+endgate
+} def
+
+/Cr::four {
+% 4 0 20 26 bbox
+begingate
+1 1.00 16 0 16 26 8 16 4 8 20 8 5 polygon
+1 1.00 12 0 20 0 2 polygon
+endgate
+} def
+
+/Cr::five {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 2 8 0 14 0 18 2 20 6 20 10 18 14 14 16 10 16 6 14 6 26 20 26
+12 polygon
+endgate
+} def
+
+/Cr::six {
+% 3 0 21 28 bbox
+begingate
+1 1.00 19 28 13 26 9 24 5 20 3 14 3 8 5 2 9 0 15 0 19 2 21 6 21 10 19 14 15 16
+9 16 5 14 3 8 17 polygon
+endgate
+} def
+
+/Cr::seven {
+% 6 0 18 26 bbox
+begingate
+1 1.00 10 0 20 26 6 26 6 24 4 polygon
+endgate
+} def
+
+/Cr::eight {
+% 5 0 19 26 bbox
+begingate
+1 1.00 9 0 7 2 5 4 5 8 7 10 17 16 19 18 19 22 15 26 9 26 5 22 5 18 7 16 17 10
+19 8 19 4 17 2 15 0 9 0 19 polygon
+endgate
+} def
+
+/Cr::nine {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 10 0 14 2 18 6 20 12 20 18 18 24 14 26 10 26 6 24 4 20 4 16 6 12
+10 10 14 10 18 12 20 16 17 polygon
+endgate
+} def
+
+/Cr::colon {
+% 10 6 14 14 bbox
+begingate
+241 1.00 12 8 2 0.00 360.00 xcarc
+241 1.00 12 18 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::semi {
+% 8 -4 16 20 bbox
+begingate
+241 1.00 12 14 2 0.00 360.00 xcarc
+0 1.00 12 2 8 -4 10 2 3 polygon
+endgate
+} def
+
+/Cr::less {
+% 4 6 20 12 bbox
+begingate
+1 1.00 16 6 4 12 16 18 3 polygon
+endgate
+} def
+
+/Cr::equal {
+% 4 12 20 6 bbox
+begingate
+1 1.00 4 12 20 12 2 polygon
+1 1.00 4 18 20 18 2 polygon
+endgate
+} def
+
+/Cr::more {
+% 6 6 18 12 bbox
+begingate
+1 1.00 6 6 18 12 6 18 3 polygon
+endgate
+} def
+
+/Cr::question {
+% 5 1 19 25 bbox
+begingate
+241 1.00 11 3 2 0.00 360.00 xcarc
+1 1.00 5 20 5 22 9 26 15 26 19 22 19 18 17 14 11 12 11 10 9 polygon
+endgate
+} def
+
+/Cr::at {
+% 4 0 20 26 bbox
+begingate
+1 1.00 20 6 18 2 14 0 10 0 6 4 4 12 6 22 10 26 14 26 18 24 20 20 20 10
+12 polygon
+1 1.00 20 12 16 8 12 8 10 10 10 14 12 18 14 20 19 22 8 polygon
+endgate
+} def
+
+/Cr::V {
+% 2 0 22 26 bbox
+begingate
+1 1.00 4 26 12 0 20 26 3 polygon
+1 1.00 2 26 8 26 2 polygon
+1 1.00 22 26 16 26 2 polygon
+endgate
+} def
+
+/Cr::A {
+% 4 0 20 26 bbox
+begingate
+1 1.00 10 10 18 10 2 polygon
+1 1.00 14 26 10 26 2 polygon
+1.00 180 26 26 Cr::V
+endgate
+} def
+
+/Cr::B {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 26 14 26 19 25 21 22 21 18 17 14 6 14 7 polygon
+1 1.00 4 0 17 0 21 2 23 6 23 8 21 12 17 14 7 polygon
+1 1.00 6 26 6 0 2 polygon
+endgate
+} def
+
+/Cr::C {
+% 2 0 22 26 bbox
+begingate
+1 1.00 18 0 10 0 4 4 2 10 2 16 4 22 10 26 16 26 22 22 9 polygon
+1 1.00 18 0 22 4 2 polygon
+1 1.00 22 26 22 22 2 polygon
+endgate
+} def
+
+/Cr::D {
+% 3 0 21 26 bbox
+begingate
+1 1.00 3 0 14 0 20 4 22 10 22 16 20 22 14 26 3 26 8 polygon
+1 1.00 6 26 6 0 2 polygon
+endgate
+} def
+
+/Cr::F {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 6 14 14 14 2 polygon
+1 1.00 14 17 14 11 2 polygon
+1 1.00 4 26 20 26 20 22 3 polygon
+1 1.00 4 0 10 0 2 polygon
+endgate
+} def
+
+/Cr::E {
+% 4 0 20 26 bbox
+begingate
+1 1.00 20 4 20 0 10 0 3 polygon
+1.00 0 0 0 Cr::F
+endgate
+} def
+
+/Cr::G {
+% 2 0 22 26 bbox
+begingate
+1 1.00 14 0 8 0 4 4 2 10 2 16 4 22 8 26 14 26 20 22 9 polygon
+1 1.00 14 0 18 2 20 4 3 polygon
+1 1.00 20 26 20 22 2 polygon
+1 1.00 20 12 20 2 2 polygon
+1 1.00 22 12 14 12 2 polygon
+endgate
+} def
+
+/Cr::H {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 20 0 20 26 2 polygon
+1 1.00 6 14 20 14 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 16 26 22 26 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 16 0 22 0 2 polygon
+endgate
+} def
+
+/Cr::I {
+% 6 0 18 26 bbox
+begingate
+1 1.00 6 0 20 0 2 polygon
+1 1.00 13 0 13 26 2 polygon
+1 1.00 6 26 19 26 2 polygon
+endgate
+} def
+
+/Cr::J {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 12 0 16 2 18 6 18 26 7 polygon
+1 1.00 4 8 4 4 2 polygon
+1 1.00 10 26 22 26 2 polygon
+endgate
+} def
+
+/Cr::K {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 20 26 6 10 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 22 26 16 26 2 polygon
+1 1.00 10 14 12 12 18 2 20 0 22 0 5 polygon
+endgate
+} def
+
+/Cr::L {
+% 4 0 20 26 bbox
+begingate
+1 1.00 8 26 8 0 2 polygon
+1 1.00 4 26 12 26 2 polygon
+1 1.00 4 0 20 0 20 6 3 polygon
+endgate
+} def
+
+/Cr::M {
+% 2 0 22 26 bbox
+begingate
+1 1.00 4 0 6 26 12 8 18 26 20 0 5 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 16 0 22 0 2 polygon
+1 1.00 2 26 6 26 2 polygon
+1 1.00 18 26 22 26 2 polygon
+endgate
+} def
+
+/Cr::N {
+% 2 0 22 26 bbox
+begingate
+1 1.00 4 0 4 26 20 0 20 26 4 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 22 26 16 26 2 polygon
+1 1.00 4 26 2 26 2 polygon
+endgate
+} def
+
+/Cr::O {
+% 2 0 22 26 bbox
+begingate
+1 1.00 15 0 9 0 4 4 2 10 2 16 4 22 9 26 15 26 20 22 22 16 22 10 20 4 15 0
+13 polygon
+endgate
+} def
+
+/Cr::P {
+% 4 0 20 26 bbox
+begingate
+1 1.00 8 0 8 26 2 polygon
+1 1.00 4 0 12 0 2 polygon
+1 1.00 8 12 17 12 21 14 23 17 23 20 21 24 17 26 4 26 8 polygon
+endgate
+} def
+
+/Cr::Q {
+% 3 -2 21 28 bbox
+begingate
+1.00 0 0 0 Cr::O
+1 1.00 8 -2 12 0 14 0 18 -2 20 -2 22 0 6 polygon
+endgate
+} def
+
+/Cr::R {
+% 2 0 22 26 bbox
+begingate
+1.00 0 -2 0 Cr::P
+1 1.00 14 12 16 10 20 0 22 0 4 polygon
+endgate
+} def
+
+/Cr::S {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 16 0 20 2 22 6 22 8 18 12 6 14 4 18 4 20 6 24 10 26 14 26
+18 24 20 22 16 polygon
+1 1.00 20 26 20 22 2 polygon
+1 1.00 4 4 4 0 2 polygon
+endgate
+} def
+
+/Cr::T {
+% 2 0 22 26 bbox
+begingate
+1 1.00 12 0 12 26 2 polygon
+1 1.00 2 20 2 26 22 26 22 20 4 polygon
+1 1.00 8 0 16 0 2 polygon
+endgate
+} def
+
+/Cr::U {
+% 2 0 22 26 bbox
+begingate
+1 1.00 4 26 4 7 5 4 7 1 10 0 14 0 17 1 19 4 20 7 20 26 10 polygon
+1 1.00 2 26 8 26 2 polygon
+1 1.00 22 26 16 26 2 polygon
+endgate
+} def
+
+/Cr::W {
+% 3 0 21 26 bbox
+begingate
+1 1.00 5 26 8 0 13 18 18 0 21 26 5 polygon
+1 1.00 17 26 23 26 2 polygon
+1 1.00 3 26 9 26 2 polygon
+endgate
+} def
+
+/Cr::X {
+% 3 0 21 26 bbox
+begingate
+1 1.00 5 0 21 26 2 polygon
+1 1.00 5 26 21 0 2 polygon
+1 1.00 3 0 9 0 2 polygon
+1 1.00 23 0 17 0 2 polygon
+1 1.00 23 26 17 26 2 polygon
+1 1.00 3 26 9 26 2 polygon
+endgate
+} def
+
+/Cr::Y {
+% 3 0 21 26 bbox
+begingate
+1 1.00 5 26 13 12 13 0 3 polygon
+1 1.00 21 26 13 12 2 polygon
+1 1.00 3 26 9 26 2 polygon
+1 1.00 23 26 17 26 2 polygon
+1 1.00 9 0 17 0 2 polygon
+endgate
+} def
+
+/Cr::Z {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 20 4 26 20 26 4 0 20 0 20 6 6 polygon
+endgate
+} def
+
+/Cr::lbracket {
+% 12 -2 12 30 bbox
+begingate
+1 1.00 18 -2 12 -2 12 28 18 28 4 polygon
+endgate
+} def
+
+/Cr::backslash {
+% 4 0 20 26 bbox
+begingate
+1 1.00 20 0 4 26 2 polygon
+endgate
+} def
+
+/Cr::rbracket {
+% 10 -2 14 30 bbox
+begingate
+1 1.00 10 -2 16 -2 16 28 10 28 4 polygon
+endgate
+} def
+
+/Cr::caret {
+% 7 24 17 6 bbox
+begingate
+1 1.00 7 24 12 30 17 24 3 polygon
+endgate
+} def
+
+/Cr::underscore {
+% 2 0 22 0 bbox
+begingate
+1 1.00 2 0 22 0 2 polygon
+endgate
+} def
+
+/Cr::a {
+% 3 0 21 18 bbox
+begingate
+1 1.00 21 0 17 0 17 14 13 18 7 18 5 16 6 polygon
+1 1.00 17 2 13 0 7 0 3 2 3 8 7 10 13 10 17 8 8 polygon
+endgate
+} def
+
+/Cr::b {
+% 2 0 22 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 6 2 10 0 16 0 20 2 22 6 22 12 20 16 16 18 10 18 6 14 10 polygon
+1 1.00 2 26 6 26 2 polygon
+1 1.00 6 0 2 0 2 polygon
+endgate
+} def
+
+/Cr::c {
+% 2 0 22 18 bbox
+begingate
+1 1.00 18 2 14 0 8 0 4 2 2 6 2 12 4 16 8 18 14 18 18 14 10 polygon
+1 1.00 18 18 18 14 2 polygon
+endgate
+} def
+
+/Cr::d {
+% 2 0 22 26 bbox
+begingate
+1 1.00 18 2 14 0 8 0 4 2 2 6 2 12 4 16 8 18 14 18 18 14 10 polygon
+1 1.00 18 0 18 26 2 polygon
+1 1.00 18 0 22 0 2 polygon
+1 1.00 18 26 14 26 2 polygon
+endgate
+} def
+
+/Cr::e {
+% 4 0 20 18 bbox
+begingate
+1 1.00 20 4 18 2 14 0 10 0 6 2 4 6 4 12 6 16 10 18 14 18 18 16 20 12 20 10
+4 10 14 polygon
+endgate
+} def
+
+/Cr::f {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 0 18 0 2 polygon
+1 1.00 8 0 8 24 11 26 16 26 20 24 5 polygon
+1 1.00 4 16 18 16 2 polygon
+endgate
+} def
+
+/Cr::g {
+% 3 -7 21 25 bbox
+begingate
+1 1.00 19 4 15 0 9 0 5 2 3 6 3 12 5 16 9 18 15 18 19 14 10 polygon
+1 1.00 8 -6 11 -7 15 -7 19 -3 19 18 5 polygon
+1 1.00 19 18 23 18 2 polygon
+endgate
+} def
+
+/Cr::h {
+% 2 0 22 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 6 14 10 18 16 18 20 14 20 0 5 polygon
+1 1.00 22 0 16 0 2 polygon
+1 1.00 2 26 6 26 2 polygon
+1 1.00 2 0 8 0 2 polygon
+endgate
+} def
+
+/Cr::i {
+% 6 0 18 24 bbox
+begingate
+1 1.00 6 0 18 0 2 polygon
+1 1.00 12 24 12 23 2 polygon
+1 1.00 12 0 12 18 8 18 3 polygon
+endgate
+} def
+
+/Cr::j {
+% 8 -6 14 30 bbox
+begingate
+1 1.00 8 -6 11 -6 15 -4 16 0 16 16 8 16 6 polygon
+1 1.00 16 24 16 23 2 polygon
+endgate
+} def
+
+/Cr::k {
+% 2 0 22 26 bbox
+begingate
+1 1.00 6 8 18 18 2 polygon
+1 1.00 20 0 10 10 2 polygon
+1 1.00 2 0 6 0 6 26 2 26 4 polygon
+1 1.00 14 18 20 18 2 polygon
+1 1.00 16 0 22 0 2 polygon
+endgate
+} def
+
+/Cr::l {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 0 18 0 2 polygon
+1 1.00 12 0 12 26 6 26 3 polygon
+endgate
+} def
+
+/Cr::m {
+% 2 0 22 18 bbox
+begingate
+1 1.00 2 0 6 0 2 polygon
+1 1.00 4 16 6 18 10 18 12 16 12 0 14 0 6 polygon
+1 1.00 12 16 14 18 17 18 20 15 20 0 22 0 6 polygon
+1 1.00 2 18 4 18 4 0 3 polygon
+endgate
+} def
+
+/Cr::n {
+% 4 0 20 18 bbox
+begingate
+1 1.00 6 0 6 18 2 polygon
+1 1.00 6 16 10 18 14 18 18 14 18 0 5 polygon
+1 1.00 4 18 6 18 2 polygon
+1 1.00 4 0 8 0 2 polygon
+1 1.00 16 0 20 0 2 polygon
+endgate
+} def
+
+/Cr::o {
+% 4 0 20 18 bbox
+begingate
+1 1.00 10 0 6 2 4 6 4 12 6 16 10 18 14 18 18 16 20 12 20 6 18 2 14 0 10 0
+13 polygon
+endgate
+} def
+
+/Cr::p {
+% 4 -6 20 24 bbox
+begingate
+1 1.00 6 2 10 0 14 0 18 2 20 6 20 12 18 16 14 18 10 18 6 16 10 polygon
+1 1.00 6 18 6 -6 2 polygon
+1 1.00 6 18 4 18 2 polygon
+1 1.00 4 -6 10 -6 2 polygon
+endgate
+} def
+
+/Cr::q {
+% 4 -6 20 24 bbox
+begingate
+1.00 -1 24 0 Cr::p
+endgate
+} def
+
+/Cr::r {
+% 3 0 21 18 bbox
+begingate
+1 1.00 4 0 16 0 2 polygon
+1 1.00 8 0 8 18 3 18 3 polygon
+1 1.00 8 14 14 18 18 18 3 polygon
+1 1.00 18 18 20 16 2 polygon
+endgate
+} def
+
+/Cr::s {
+% 6 0 18 18 bbox
+begingate
+1 1.00 6 4 10 0 16 0 20 2 20 6 18 8 8 10 6 12 6 16 10 18 16 18 20 14
+12 polygon
+1 1.00 20 18 20 14 2 polygon
+1 1.00 6 4 6 0 2 polygon
+endgate
+} def
+
+/Cr::t {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 18 20 18 2 polygon
+1 1.00 10 26 10 2 13 0 16 0 22 3 5 polygon
+endgate
+} def
+
+/Cr::u {
+% 4 0 20 18 bbox
+begingate
+1 1.00 20 0 20 0 20 18 16 18 4 polygon
+1 1.00 4 18 6 18 6 4 10 0 16 0 20 2 6 polygon
+endgate
+} def
+
+/Cr::v {
+% 2 0 22 18 bbox
+begingate
+1 1.00 4 18 12 0 20 18 3 polygon
+1 1.00 2 18 8 18 2 polygon
+1 1.00 16 18 22 18 2 polygon
+endgate
+} def
+
+/Cr::w {
+% 2 0 22 16 bbox
+begingate
+1 1.00 4 18 8 0 12 12 16 0 20 18 5 polygon
+1 1.00 2 18 8 18 2 polygon
+1 1.00 16 18 22 18 2 polygon
+endgate
+} def
+
+/Cr::x {
+% 4 0 20 18 bbox
+begingate
+1 1.00 6 0 20 18 2 polygon
+1 1.00 6 18 20 0 2 polygon
+1 1.00 4 18 10 18 2 polygon
+1 1.00 16 18 22 18 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 16 0 22 0 2 polygon
+endgate
+} def
+
+/Cr::y {
+% 2 -6 22 24 bbox
+begingate
+1 1.00 4 18 12 2 2 polygon
+1 1.00 20 18 8 -6 2 polygon
+1 1.00 2 18 8 18 2 polygon
+1 1.00 16 18 22 18 2 polygon
+1 1.00 4 -6 12 -6 2 polygon
+endgate
+} def
+
+/Cr::z {
+% 4 0 20 18 bbox
+begingate
+1 1.00 4 14 4 18 20 18 4 0 20 0 20 4 6 polygon
+endgate
+} def
+
+/Cr::lbrace {
+% 6 -4 18 32 bbox
+begingate
+1 1.00 14 -4 12 -4 10 -2 10 10 6 12 10 14 10 26 12 28 14 28 9 polygon
+endgate
+} def
+
+/Cr::vbar {
+% 12 -2 12 30 bbox
+begingate
+1 1.00 12 -2 12 28 2 polygon
+endgate
+} def
+
+/Cr::rbrace {
+% 8 -4 16 32 bbox
+begingate
+1 1.00 8 -4 10 -4 12 -2 12 10 16 12 12 14 12 26 10 28 8 28 9 polygon
+endgate
+} def
+
+/Cr::tilde {
+% 6 14 18 2 bbox
+begingate
+1 1.00 6 14 8 16 10 16 14 14 16 14 18 16 6 polygon
+endgate
+} def
+
+/Cr::upexclam {
+% 10 1 14 22 bbox
+begingate
+1.00 -181 0 24 Cr::exclam
+endgate
+} def
+
+/Cr::cent {
+% 4 -6 20 30 bbox
+begingate
+1 1.00 12 18 12 24 2 polygon
+1 1.00 12 0 12 -6 2 polygon
+1.00 0 2 0 Cr::c
+endgate
+} def
+
+/Cr::lb {
+% 4 0 20 26 bbox
+begingate
+1 1.00 20 2 18 0 16 0 10 2 8 2 5 polygon
+1 1.00 6 14 18 14 2 polygon
+1 1.00 4 0 8 2 10 6 10 12 8 18 8 22 12 26 16 26 20 24 9 polygon
+endgate
+} def
+
+/Cr::aslash {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 0 18 26 2 polygon
+endgate
+} def
+
+/Cr::yen {
+% 3 0 21 26 bbox
+begingate
+1 1.00 5 17 10 17 2 polygon
+1 1.00 5 12 21 12 2 polygon
+1 1.00 16 17 21 17 2 polygon
+1.00 0 0 0 Cr::Y
+endgate
+} def
+
+/Cr::itf {
+% 0 -6 24 32 bbox
+begingate
+1 1.00 6 18 16 18 2 polygon
+1 1.00 0 -4 2 -6 6 -6 8 -4 12 24 14 26 18 26 20 24 8 polygon
+endgate
+} def
+
+/Cr::sy1 {
+% 4 -6 20 32 bbox
+begingate
+1 1.00 18 0 20 2 20 6 8 16 6 20 8 24 12 26 18 26 18 22 9 polygon
+1 1.00 6 20 4 18 4 14 16 4 18 0 16 -4 12 -6 6 -6 6 -2 9 polygon
+endgate
+} def
+
+/Cr::sy2 {
+% 2 2 22 16 bbox
+begingate
+1 1.00 10 10 6 0.00 360.00 xcarc
+1 1.00 2 18 5 15 2 polygon
+1 1.00 18 18 15 15 2 polygon
+1 1.00 18 2 15 5 2 polygon
+1 1.00 2 2 5 5 2 polygon
+endgate
+} def
+
+/Cr::apos2 {
+% 10 24 14 8 bbox
+begingate
+0 1.00 12 32 11 24 10 32 3 polygon
+endgate
+} def
+
+/Cr::lqt {
+% 6 24 18 8 bbox
+begingate
+1.00 180 22 52 Cr::apostrophe
+1.00 180 28 52 Cr::apostrophe
+endgate
+} def
+
+/Cr::lgqt {
+% 4 4 20 14 bbox
+begingate
+1 1.00 10 4 4 11 10 18 3 polygon
+1 1.00 16 4 10 11 16 18 3 polygon
+endgate
+} def
+
+/Cr::lsang {
+% 8 4 16 14 bbox
+begingate
+1 1.00 14 4 8 11 14 18 3 polygon
+endgate
+} def
+
+/Cr::rsang {
+% 10 4 14 14 bbox
+begingate
+1 1.00 10 4 16 11 10 18 3 polygon
+endgate
+} def
+
+/Cr::fi {
+% 2 0 22 26 bbox
+begingate
+1 1.00 6 0 6 24 8 26 12 26 4 polygon
+1 1.00 13 18 16 18 16 0 3 polygon
+1 1.00 16 22 16 23 2 polygon
+1 1.00 10 18 2 18 2 polygon
+1 1.00 2 0 10 0 2 polygon
+1 1.00 12 0 20 0 2 polygon
+endgate
+} def
+
+/Cr::fl {
+% 4 0 20 26 bbox
+begingate
+1 1.00 8 0 8 24 10 26 18 26 4 polygon
+1 1.00 18 26 18 0 2 polygon
+1 1.00 4 18 12 18 2 polygon
+1 1.00 4 0 12 0 2 polygon
+1 1.00 14 0 22 0 2 polygon
+endgate
+} def
+
+/Cr::dag {
+% 6 2 18 22 bbox
+begingate
+1 1.00 12 2 12 24 2 polygon
+1 1.00 6 18 18 18 2 polygon
+endgate
+} def
+
+/Cr::ddag {
+% 6 0 18 24 bbox
+begingate
+1 1.00 12 0 12 24 2 polygon
+1 1.00 6 18 18 18 2 polygon
+1 1.00 6 6 18 6 2 polygon
+endgate
+} def
+
+/Cr::dot {
+% 10 22 14 4 bbox
+begingate
+241 1.00 12 24 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::para {
+% 5 2 19 24 bbox
+begingate
+1 1.00 13 2 13 26 2 polygon
+1 1.00 17 2 17 26 2 polygon
+1 1.00 20 26 12 26 2 polygon
+240 1.00 12 19 7 90.00 270.00 xcarc
+endgate
+} def
+
+/Cr::bullet {
+% 10 15 14 4 bbox
+begingate
+1.00 0 0 -7 Cr::dot
+endgate
+} def
+
+/Cr::comma2 {
+% 10 -6 14 8 bbox
+begingate
+1.00 0 0 -2 Cr::comma
+endgate
+} def
+
+/Cr::rqt2 {
+% 7 -7 17 8 bbox
+begingate
+1.00 180 23 25 Cr::lqt
+endgate
+} def
+
+/Cr::rqt {
+% 6 22 18 8 bbox
+begingate
+1.00 180 22 54 Cr::lqt
+endgate
+} def
+
+/Cr::rgqt {
+% 8 6 16 14 bbox
+begingate
+1.00 -1 24 2 Cr::lgqt
+endgate
+} def
+
+/Cr::dots {
+% 2 1 22 4 bbox
+begingate
+1.00 0 -8 0 Cr::period
+1.00 0 0 0 Cr::period
+1.00 0 8 0 Cr::period
+endgate
+} def
+
+/Cr::perzer {
+% 3 4 21 18 bbox
+begingate
+1.00 0 -1 0 Cr::percent
+1 1.00 22 7 3 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::uqest {
+% 6 3 18 25 bbox
+begingate
+1.00 180 25 29 Cr::question
+endgate
+} def
+
+/Cr::grave {
+% 9 28 13 4 bbox
+begingate
+0 1.00 9 32 19 28 9 30 3 polygon
+endgate
+} def
+
+/Cr::acute {
+% 6 28 18 4 bbox
+begingate
+1.00 -1 25 0 Cr::grave
+endgate
+} def
+
+/Cr::hat {
+% 8 28 16 4 bbox
+begingate
+1 1.00 8 28 12 32 16 28 3 polygon
+endgate
+} def
+
+/Cr::tilchar {
+% 6 29 18 2 bbox
+begingate
+1.00 0 0 15 Cr::tilde
+endgate
+} def
+
+/Cr::bar {
+% 8 31 16 0 bbox
+begingate
+1 1.00 8 31 16 31 2 polygon
+endgate
+} def
+
+/Cr::uu {
+% 6 29 18 3 bbox
+begingate
+1 1.00 6 32 7 30 9 29 13 29 15 30 16 32 6 polygon
+endgate
+} def
+
+/Cr::umlaut {
+% 7 29 19 2 bbox
+begingate
+1 1.00 8 30 1 0.00 360.00 xcarc
+1 1.00 15 30 1 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::circ {
+% 9 25 15 6 bbox
+begingate
+1 1.00 12 28 3 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::cedilla {
+% 10 -6 14 6 bbox
+begingate
+1 1.00 12 0 10 -2 14 -4 12 -6 4 polygon
+endgate
+} def
+
+/Cr::uml2 {
+% 5 26 19 6 bbox
+begingate
+0 1.00 11 32 5 26 9 32 3 polygon
+0 1.00 17 32 11 26 15 32 3 polygon
+endgate
+} def
+
+/Cr::ced2 {
+% 8 -4 16 4 bbox
+begingate
+1 1.00 12 0 8 -2 10 -4 12 -3 4 polygon
+endgate
+} def
+
+/Cr::vee {
+% 7 28 17 4 bbox
+begingate
+1 1.00 7 32 11 28 15 32 3 polygon
+endgate
+} def
+
+/Cr::Oslash {
+% 1 0 23 26 bbox
+begingate
+1 1.00 1 0 21 26 2 polygon
+1.00 0 0 0 Cr::O
+endgate
+} def
+
+/Cr::osl {
+% 4 0 20 18 bbox
+begingate
+1 1.00 5 0 20 17 2 polygon
+1.00 0 0 0 Cr::o
+endgate
+} def
+
+/Cr::sset {
+% 4 0 20 26 bbox
+begingate
+1 1.00 14 16 19 14 22 10 22 4 18 0 14 0 11 1 7 polygon
+1 1.00 4 0 8 0 8 20 10 24 13 26 17 26 20 24 20 20 18 17 14 16 12 16 11 polygon
+endgate
+} def
+
+/Cr::Agrave {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 -2 2 Cr::grave
+endgate
+} def
+
+/Cr::Aacute {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 2 2 Cr::acute
+endgate
+} def
+
+/Cr::Acircum {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 2 2 Cr::hat
+endgate
+} def
+
+/Cr::Atilde {
+% 4 0 20 31 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 2 0 Cr::tilchar
+endgate
+} def
+
+/Cr::Adier {
+% 4 0 20 33 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 2 2 Cr::umlaut
+endgate
+} def
+
+/Cr::Aring {
+% 4 0 20 35 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 2 4 Cr::circ
+endgate
+} def
+
+/Cr::Egrave {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 -2 2 Cr::grave
+endgate
+} def
+
+/Cr::Eacute {
+% 0 0 24 28 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 0 2 Cr::acute
+endgate
+} def
+
+/Cr::Ecircum {
+% 0 0 24 28 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 0 2 Cr::hat
+endgate
+} def
+
+/Cr::Edier {
+% 6 0 18 31 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 0 0 Cr::umlaut
+endgate
+} def
+
+/Cr::Ccedil {
+% 0 0 24 26 bbox
+begingate
+1.00 0 0 0 Cr::C
+1.00 0 3 0 Cr::cedilla
+endgate
+} def
+
+/Cr::Igrave {
+% 6 0 18 33 bbox
+begingate
+1.00 0 0 0 Cr::I
+1.00 0 -2 1 Cr::grave
+endgate
+} def
+
+/Cr::Iacute {
+% 10 0 14 33 bbox
+begingate
+1.00 0 0 0 Cr::I
+1.00 0 1 1 Cr::acute
+endgate
+} def
+
+/Cr::Icircum {
+% 10 0 14 34 bbox
+begingate
+1.00 0 0 0 Cr::I
+1.00 0 0 2 Cr::hat
+endgate
+} def
+
+/Cr::Idier {
+% 10 0 14 32 bbox
+begingate
+1.00 0 0 0 Cr::I
+1.00 0 1 1 Cr::umlaut
+endgate
+} def
+
+/Cr::Otilde {
+% 2 0 22 31 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 0 0 Cr::tilchar
+endgate
+} def
+
+/Cr::Ugrave {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 -2 2 Cr::grave
+endgate
+} def
+
+/Cr::Uacute {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 2 2 Cr::acute
+endgate
+} def
+
+/Cr::Ucircum {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 0 2 Cr::hat
+endgate
+} def
+
+/Cr::Udier {
+% 2 0 22 33 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 0 2 Cr::umlaut
+endgate
+} def
+
+/Cr::Ograve {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 -2 2 Cr::grave
+endgate
+} def
+
+/Cr::Oacute {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 0 2 Cr::acute
+endgate
+} def
+
+/Cr::Ocircum {
+% 2 0 22 34 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 0 2 Cr::hat
+endgate
+} def
+
+/Cr::Odier {
+% 2 0 22 33 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 0 2 Cr::umlaut
+endgate
+} def
+
+/Cr::Ntilde {
+% 2 0 22 31 bbox
+begingate
+1.00 0 0 0 Cr::N
+1.00 0 0 0 Cr::tilchar
+endgate
+} def
+
+/Cr::AE {
+% 4 0 20 26 bbox
+begingate
+1 1.00 16 26 6 0 2 polygon
+1 1.00 16 10 10 10 2 polygon
+1 1.00 16 26 16 0 2 polygon
+1 1.00 12 26 24 26 24 22 3 polygon
+1 1.00 13 0 24 0 24 6 3 polygon
+1 1.00 16 13 22 13 2 polygon
+1 1.00 22 16 22 10 2 polygon
+1 1.00 4 0 9 0 2 polygon
+endgate
+} def
+
+/Cr::Eth {
+% 3 0 21 26 bbox
+begingate
+1.00 0 0 0 Cr::D
+1 1.00 11 13 3 13 2 polygon
+endgate
+} def
+
+/Cr::Yacute {
+% 3 0 21 34 bbox
+begingate
+1.00 0 0 0 Cr::Y
+1.00 0 2 2 Cr::acute
+endgate
+} def
+
+/Cr::agrave {
+% 3 0 21 25 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 -3 -7 Cr::grave
+endgate
+} def
+
+/Cr::aacute {
+% 3 0 21 25 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 0 -7 Cr::acute
+endgate
+} def
+
+/Cr::acircum {
+% 3 0 21 25 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 -1 -7 Cr::hat
+endgate
+} def
+
+/Cr::atilde {
+% 3 0 21 23 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 -2 -8 Cr::tilchar
+endgate
+} def
+
+/Cr::adier {
+% 3 0 21 24 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 -1 -7 Cr::umlaut
+endgate
+} def
+
+/Cr::aring {
+% 3 0 21 29 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 0 -2 Cr::circ
+endgate
+} def
+
+/Cr::ntilde {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::n
+1.00 0 -1 -7 Cr::tilchar
+endgate
+} def
+
+/Cr::egrave {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::e
+1.00 0 -2 -7 Cr::grave
+endgate
+} def
+
+/Cr::eacute {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::e
+1.00 0 1 -7 Cr::acute
+endgate
+} def
+
+/Cr::ecircum {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::e
+1.00 0 0 -7 Cr::hat
+endgate
+} def
+
+/Cr::edier {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::e
+1.00 0 1 -7 Cr::umlaut
+endgate
+} def
+
+/Cr::ae {
+% 3 0 21 17 bbox
+begingate
+1 1.00 12 2 9 0 6 0 3 2 3 6 6 9 12 9 7 polygon
+1 1.00 4 15 6 17 10 17 12 15 4 polygon
+1 1.00 12 13 12 5 13 2 15 0 18 0 21 2 6 polygon
+1 1.00 12 13 13 16 15 17 18 17 20 16 21 13 21 9 12 9 8 polygon
+endgate
+} def
+
+/Cr::igrave {
+% 5 0 19 26 bbox
+begingate
+1.00 0 -4 -6 Cr::grave
+1 1.00 6 0 20 0 2 polygon
+1 1.00 8 18 13 18 13 0 3 polygon
+endgate
+} def
+
+/Cr::iacute {
+% 6 0 18 26 bbox
+begingate
+1.00 0 0 -6 Cr::acute
+1 1.00 6 0 18 0 2 polygon
+1 1.00 8 18 12 18 12 0 3 polygon
+endgate
+} def
+
+/Cr::icircum {
+% 6 0 18 26 bbox
+begingate
+1.00 0 -2 -6 Cr::hat
+1 1.00 6 0 18 0 2 polygon
+1 1.00 8 18 12 18 12 0 3 polygon
+endgate
+} def
+
+/Cr::idier {
+% 4 0 20 25 bbox
+begingate
+1.00 0 -2 -6 Cr::umlaut
+1 1.00 6 18 10 18 10 0 3 polygon
+1 1.00 4 0 16 0 2 polygon
+endgate
+} def
+
+/Cr::ydier {
+% 2 -6 22 31 bbox
+begingate
+1.00 0 0 0 Cr::y
+1.00 0 0 -6 Cr::umlaut
+endgate
+} def
+
+/Cr::yacute {
+% 2 -6 22 31 bbox
+begingate
+1.00 0 0 0 Cr::y
+1.00 0 0 -7 Cr::acute
+endgate
+} def
+
+/Cr::ograve {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 -2 -7 Cr::grave
+endgate
+} def
+
+/Cr::oacute {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 0 -7 Cr::acute
+endgate
+} def
+
+/Cr::ocircum {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 0 -6 Cr::hat
+endgate
+} def
+
+/Cr::otilde {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 0 -7 Cr::tilchar
+endgate
+} def
+
+/Cr::odier {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 0 -6 Cr::umlaut
+endgate
+} def
+
+/Cr::eth {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::o
+1 1.00 18 16 12 24 6 26 3 polygon
+1 1.00 14 26 8 22 2 polygon
+endgate
+} def
+
+/Cr::ugrave {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 -2 -6 Cr::grave
+endgate
+} def
+
+/Cr::uacute {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 0 -6 Cr::acute
+endgate
+} def
+
+/Cr::ucircum {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 0 -6 Cr::hat
+endgate
+} def
+
+/Cr::udier {
+% 4 0 20 25 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 0 -6 Cr::umlaut
+endgate
+} def
+
+/Cr::ccedil {
+% 4 -6 20 24 bbox
+begingate
+1.00 0 2 0 Cr::cedilla
+1.00 0 2 0 Cr::c
+endgate
+} def
+
+/Cr::ordfem {
+% 5 20 19 10 bbox
+begingate
+0.60 0 4 20 Cr::a
+endgate
+} def
+
+/Cr::Lslash {
+% 6 0 18 26 bbox
+begingate
+1.00 0 4 0 Cr::L
+1 1.00 18 19 6 11 2 polygon
+endgate
+} def
+
+/Cr::ordmasc {
+% 4 18 20 9 bbox
+begingate
+0.60 0 2 18 Cr::o
+endgate
+} def
+
+/Cr::lslash {
+% 10 0 14 26 bbox
+begingate
+1.00 0 6 0 Cr::l
+1 1.00 21 16 15 12 2 polygon
+endgate
+} def
+
+/Cr::OE {
+% 4 0 20 26 bbox
+begingate
+1 1.00 24 0 14 0 14 26 24 26 4 polygon
+1 1.00 20 14 14 14 2 polygon
+1 1.00 14 26 10 26 6 22 4 16 4 10 6 4 10 0 14 0 8 polygon
+1 1.00 20 18 20 10 2 polygon
+1 1.00 24 6 24 0 2 polygon
+1 1.00 24 20 24 26 2 polygon
+endgate
+} def
+
+/Cr::oe {
+% 3 0 21 18 bbox
+begingate
+1 1.00 24 4 23 2 21 0 17 0 15 2 14 6 14 12 15 16 17 18 21 18 23 16 24 12 24 10
+14 10 14 polygon
+1 1.00 14 12 13 16 11 18 7 18 5 16 3 12 3 6 5 2 7 0 11 0 13 2 14 6 12 polygon
+endgate
+} def
+
+/Cr::emdash {
+% 2 10 22 0 bbox
+begingate
+1 1.00 2 10 22 10 2 polygon
+endgate
+} def
+
+/Cr::pm {
+% 4 10 20 17 bbox
+begingate
+1.00 0 0 3 Cr::plus
+1.00 0 0 -6 Cr::minus
+endgate
+} def
+
+/Cr::onesup {
+% 8 18 16 15 bbox
+begingate
+0.60 0 4 18 Cr::one
+endgate
+} def
+
+/Cr::twosup {
+% 4 18 20 15 bbox
+begingate
+0.60 0 2 18 Cr::two
+endgate
+} def
+
+/Cr::threesup {
+% 4 18 20 15 bbox
+begingate
+0.60 0 2 18 Cr::three
+endgate
+} def
+
+/Cr::quarter {
+% 4 0 20 27 bbox
+begingate
+0.60 0 10 0 Cr::four
+0.60 0 0 12 Cr::one
+1 1.00 4 0 20 24 2 polygon
+endgate
+} def
+
+/Cr::half {
+% 2 0 22 27 bbox
+begingate
+0.60 0 -2 12 Cr::one
+0.60 0 10 0 Cr::two
+1 1.00 2 0 18 24 2 polygon
+endgate
+} def
+
+/Cr::threeq {
+% 2 0 22 27 bbox
+begingate
+0.60 0 0 12 Cr::three
+0.60 0 10 0 Cr::four
+1 1.00 5 0 21 24 2 polygon
+endgate
+} def
+
+/Cr::copy {
+% 2 4 22 20 bbox
+begingate
+0.50 0 5 7 Cr::C
+1 1.00 12 14 10 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::regis {
+% 4 4 20 20 bbox
+begingate
+0.48 0 8 8 Cr::R
+1 1.00 14 14 10 0.00 360.00 xcarc
+endgate
+} def
+
+/Cr::mu {
+% 4 -8 20 26 bbox
+begingate
+1.00 0 0 0 Cr::u
+1 1.00 6 -8 6 4 2 polygon
+endgate
+} def
+
+/Cr::lognot {
+% 3 8 21 8 bbox
+begingate
+1 1.00 3 16 19 16 19 8 3 polygon
+endgate
+} def
+
+/Cr::times {
+% 5 6 19 12 bbox
+begingate
+1 1.00 5 6 17 18 2 polygon
+1 1.00 5 18 17 6 2 polygon
+endgate
+} def
+
+/Cr::divide {
+% 5 4 19 16 bbox
+begingate
+1 1.00 5 12 21 12 2 polygon
+1.00 0 1 15 Cr::period
+1.00 0 1 3 Cr::period
+endgate
+} def
+
+/Cr::thorn {
+% 2 -6 22 30 bbox
+begingate
+1.00 0 -2 0 Cr::p
+1 1.00 4 16 4 24 2 24 3 polygon
+endgate
+} def
+
+/Cr::Thorn {
+% 3 0 21 26 bbox
+begingate
+1 1.00 6 7 14 7 18 9 19 13 18 17 14 19 6 19 7 polygon
+1 1.00 3 0 10 0 2 polygon
+1 1.00 6 0 6 26 2 polygon
+1 1.00 3 26 10 26 2 polygon
+endgate
+} def
+
+/Cr::onesmall {
+% 9 4 15 19 bbox
+begingate
+0.75 0 3 4 Cr::one
+endgate
+} def
+
+/Cr::dash {
+% 8 12 16 0 bbox
+begingate
+1 1.00 8 12 16 12 2 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/courier.xfe b/lib/fonts/courier.xfe
new file mode 100644
index 0000000..8f9b57d
--- /dev/null
+++ b/lib/fonts/courier.xfe
@@ -0,0 +1,48 @@
+% XCircuit Font encoding (XFE) file
+name: Courier
+file: courier.lps
+family: Courier
+weight: normal
+shape: normal
+type: PostScript
+encoding: Standard
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar
+Cr::space Cr::exclam Cr::quote Cr::pound Cr::dollar Cr::percent Cr::ampersand
+Cr::apostrophe Cr::lparen Cr::rparen Cr::asterisk Cr::plus Cr::comma Cr::minus
+Cr::period Cr::slash Cr::zero Cr::one Cr::two Cr::three Cr::four Cr::five
+Cr::six Cr::seven Cr::eight Cr::nine Cr::colon Cr::semi Cr::less Cr::equal
+Cr::more Cr::question Cr::at Cr::A Cr::B Cr::C Cr::D Cr::E Cr::F Cr::G Cr::H
+Cr::I Cr::J Cr::K Cr::L Cr::M Cr::N Cr::O Cr::P Cr::Q Cr::R Cr::S Cr::T Cr::U
+Cr::V Cr::W Cr::X Cr::Y Cr::Z Cr::lbracket Cr::backslash Cr::rbracket Cr::caret
+Cr::underscore Cr::apostrophe Cr::a Cr::b Cr::c Cr::d Cr::e Cr::f Cr::g Cr::h
+Cr::i Cr::j Cr::k Cr::l Cr::m Cr::n Cr::o Cr::p Cr::q Cr::r Cr::s Cr::t Cr::u
+Cr::v Cr::w Cr::x Cr::y Cr::z Cr::lbrace Cr::vbar Cr::rbrace Cr::tilde Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::upexclam Cr::cent
+Cr::lb Cr::aslash Cr::yen Cr::itf Cr::sy1 Cr::sy2 Cr::apos2 Cr::lqt Cr::lgqt
+Cr::lsang Cr::rsang Cr::fi Cr::fl Cr::nullchar Cr::minus Cr::dag Cr::ddag Cr::dot
+Cr::nullchar Cr::para Cr::bullet Cr::comma2 Cr::rqt2 Cr::rqt Cr::rgqt Cr::dots
+Cr::perzer Cr::nullchar Cr::uqest Cr::nullchar Cr::grave Cr::acute Cr::hat Cr::tilchar
+Cr::bar Cr::uu Cr::dot Cr::umlaut Cr::nullchar Cr::circ Cr::cedilla Cr::nullchar
+Cr::uml2 Cr::ced2 Cr::vee Cr::emdash Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::AE Cr::nullchar Cr::ordfem Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::Lslash Cr::Oslash Cr::OE Cr::ordmasc Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::ae Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::onesup Cr::nullchar Cr::nullchar Cr::lslash
+Cr::osl Cr::oe Cr::sset Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+
+derived: Courier-Bold bold normal PostScript
+derived: Courier-Italic normal italic PostScript
+derived: Courier-BoldItalic bold italic PostScript
+
diff --git a/lib/fonts/courieriso.xfe b/lib/fonts/courieriso.xfe
new file mode 100644
index 0000000..87cc0b2
--- /dev/null
+++ b/lib/fonts/courieriso.xfe
@@ -0,0 +1,47 @@
+% XCircuit Font encoding (XFE) file
+name: CourierISO
+% file: courier.lps
+family: Courier
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin1
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar
+Cr::space Cr::exclam Cr::quote Cr::pound Cr::dollar Cr::percent Cr::ampersand
+Cr::apostrophe Cr::lparen Cr::rparen Cr::asterisk Cr::plus Cr::comma Cr::minus
+Cr::period Cr::slash Cr::zero Cr::one Cr::two Cr::three Cr::four Cr::five Cr::six
+Cr::seven Cr::eight Cr::nine Cr::colon Cr::semi Cr::less Cr::equal Cr::more
+Cr::question Cr::at Cr::A Cr::B Cr::C Cr::D Cr::E Cr::F Cr::G Cr::H Cr::I Cr::J
+Cr::K Cr::L Cr::M Cr::N Cr::O Cr::P Cr::Q Cr::R Cr::S Cr::T Cr::U Cr::V Cr::W
+Cr::X Cr::Y Cr::Z Cr::lbracket Cr::backslash Cr::rbracket Cr::caret
+Cr::underscore Cr::apostrophe Cr::a Cr::b Cr::c Cr::d Cr::e Cr::f Cr::g Cr::h
+Cr::i Cr::j Cr::k Cr::l Cr::m Cr::n Cr::o Cr::p Cr::q Cr::r Cr::s Cr::t Cr::u
+Cr::v Cr::w Cr::x
+Cr::y Cr::z Cr::lbrace Cr::vbar Cr::rbrace Cr::tilde
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::onesmall Cr::grave Cr::acute Cr::hat Cr::tilde Cr::bar Cr::uu Cr::dot
+Cr::umlaut Cr::nullchar Cr::circ Cr::cedilla Cr::nullchar Cr::uml2 Cr::ced2
+Cr::vee Cr::space
+Cr::upexclam Cr::cent Cr::lb Cr::sy2 Cr::yen Cr::vbar Cr::sy1 Cr::umlaut Cr::copy
+Cr::ordfem Cr::lgqt Cr::lognot Cr::dash Cr::regis Cr::bar Cr::circ Cr::pm Cr::twosup
+Cr::threesup Cr::acute Cr::mu Cr::para Cr::dot Cr::cedilla Cr::onesup Cr::ordmasc
+Cr::rgqt Cr::quarter Cr::half Cr::threeq Cr::uqest
+Cr::Agrave Cr::Aacute Cr::Acircum Cr::Atilde Cr::Adier Cr::Aring Cr::AE Cr::Ccedil
+Cr::Egrave Cr::Eacute Cr::Ecircum Cr::Edier Cr::Igrave Cr::Iacute Cr::Icircum Cr::Idier
+Cr::Eth Cr::Ntilde Cr::Ograve Cr::Oacute Cr::Ocircum Cr::Otilde Cr::Odier Cr::times
+Cr::Oslash Cr::Ugrave Cr::Uacute Cr::Ucircum Cr::Udier Cr::Yacute Cr::Thorn Cr::sset
+Cr::agrave Cr::aacute Cr::acircum Cr::atilde Cr::adier Cr::aring Cr::ae Cr::ccedil
+Cr::egrave Cr::eacute Cr::ecircum Cr::edier Cr::igrave Cr::iacute Cr::icircum Cr::idier
+Cr::eth Cr::ntilde Cr::ograve Cr::oacute Cr::ocircum Cr::otilde Cr::odier Cr::divide
+Cr::osl Cr::ugrave Cr::uacute Cr::ucircum Cr::udier Cr::yacute Cr::thorn Cr::ydier
+
+derived: Courier-BoldISO bold normal PostScript
+derived: Courier-ItalicISO normal italic PostScript
+derived: Courier-BoldItalicISO bold italic PostScript
diff --git a/lib/fonts/courieriso2.lps b/lib/fonts/courieriso2.lps
new file mode 100644
index 0000000..30c4f41
--- /dev/null
+++ b/lib/fonts/courieriso2.lps
@@ -0,0 +1,414 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Cr
+% Version: 2.0
+%
+
+% XCircuitLib font library
+/Cr::Aogonek {
+% 4 -5 20 31 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 12 0 Cr::ced2
+endgate
+} def
+
+/Cr::Lcaron {
+% 4 0 20 27 bbox
+begingate
+1.00 0 12 0 Cr::apostrophe
+1.00 0 0 0 Cr::L
+endgate
+} def
+
+/Cr::Scedil {
+% 4 -6 20 32 bbox
+begingate
+1.00 0 0 0 Cr::S
+1.00 0 4 0 Cr::cedilla
+endgate
+} def
+
+/Cr::Sacute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 Cr::S
+1.00 0 4 4 Cr::acute
+endgate
+} def
+
+/Cr::Scaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::S
+1.00 0 4 2 Cr::vee
+endgate
+} def
+
+/Cr::Zacute {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::Z
+1.00 0 2 2 Cr::acute
+endgate
+} def
+
+/Cr::Zcaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 4 2 Cr::vee
+1.00 0 0 0 Cr::Z
+endgate
+} def
+
+/Cr::Zdot {
+% 4 0 20 35 bbox
+begingate
+1.00 0 0 0 Cr::Z
+1.00 0 8 32 Cr::period
+endgate
+} def
+
+/Cr::aogonek {
+% 4 -5 20 21 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 8 0 Cr::ced2
+endgate
+} def
+
+/Cr::lcaron {
+% 3 0 21 27 bbox
+begingate
+1.00 0 0 0 Cr::l
+1.00 0 4 0 Cr::apostrophe
+endgate
+} def
+
+/Cr::sacute {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::s
+1.00 0 0 -8 Cr::acute
+endgate
+} def
+
+/Cr::zacute {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::z
+1.00 0 0 -8 Cr::acute
+endgate
+} def
+
+/Cr::zcaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 -8 Cr::vee
+1.00 0 0 0 Cr::z
+endgate
+} def
+
+/Cr::zdot {
+% 4 0 20 25 bbox
+begingate
+1.00 0 2 22 Cr::period
+1.00 0 0 0 Cr::z
+endgate
+} def
+
+/Cr::tcaron {
+% 4 0 20 27 bbox
+begingate
+1.00 0 0 0 Cr::t
+1.00 0 12 0 Cr::apostrophe
+endgate
+} def
+
+/Cr::scedil {
+% 4 -6 20 22 bbox
+begingate
+1.00 0 2 0 Cr::cedilla
+1.00 0 0 0 Cr::s
+endgate
+} def
+
+/Cr::Rcaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::R
+1.00 0 2 2 Cr::vee
+endgate
+} def
+
+/Cr::Racute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 Cr::R
+1.00 0 0 4 Cr::acute
+endgate
+} def
+
+/Cr::Abreve {
+% 4 0 20 32 bbox
+begingate
+1.00 0 0 0 Cr::A
+1.00 0 4 0 Cr::uu
+endgate
+} def
+
+/Cr::Lacute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 Cr::L
+1.00 0 -4 4 Cr::acute
+endgate
+} def
+
+/Cr::Cacute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 Cr::C
+1.00 0 8 4 Cr::acute
+endgate
+} def
+
+/Cr::Ccaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::C
+1.00 0 4 2 Cr::vee
+endgate
+} def
+
+/Cr::Eogonek {
+% 4 -5 20 31 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 8 0 Cr::ced2
+endgate
+} def
+
+/Cr::Ecaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::E
+1.00 0 4 2 Cr::vee
+endgate
+} def
+
+/Cr::Dcaron {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::D
+1.00 0 2 2 Cr::vee
+endgate
+} def
+
+/Cr::Ncaron {
+% 4 0 20 32 bbox
+begingate
+1.00 0 0 0 Cr::N
+1.00 0 0 0 Cr::vee
+endgate
+} def
+
+/Cr::Nacute {
+% 4 0 20 32 bbox
+begingate
+1.00 0 0 0 Cr::N
+1.00 0 4 0 Cr::acute
+endgate
+} def
+
+/Cr::Ouml2 {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::O
+1.00 0 2 2 Cr::uml2
+endgate
+} def
+
+/Cr::Ucirc {
+% 4 0 20 38 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 4 4 Cr::circ
+endgate
+} def
+
+/Cr::Uuml2 {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::U
+1.00 0 6 2 Cr::uml2
+endgate
+} def
+
+/Cr::Tcedil {
+% 4 -6 20 32 bbox
+begingate
+1.00 0 0 0 Cr::T
+1.00 0 4 0 Cr::cedilla
+endgate
+} def
+
+/Cr::racute {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::r
+1.00 0 0 -8 Cr::acute
+endgate
+} def
+
+/Cr::rcaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::r
+1.00 0 0 -8 Cr::vee
+endgate
+} def
+
+/Cr::abreve {
+% 4 0 20 23 bbox
+begingate
+1.00 0 0 0 Cr::a
+1.00 0 2 -9 Cr::uu
+endgate
+} def
+
+/Cr::lacute {
+% 3 0 21 36 bbox
+begingate
+1.00 0 0 0 Cr::l
+1.00 0 -4 4 Cr::acute
+endgate
+} def
+
+/Cr::cacute {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::c
+1.00 0 4 -8 Cr::acute
+endgate
+} def
+
+/Cr::ccaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::c
+1.00 0 2 -8 Cr::vee
+endgate
+} def
+
+/Cr::eogonek {
+% 4 -5 20 21 bbox
+begingate
+1.00 0 2 0 Cr::ced2
+1.00 0 0 0 Cr::e
+endgate
+} def
+
+/Cr::ecaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::e
+1.00 0 2 -8 Cr::vee
+endgate
+} def
+
+/Cr::dcaron {
+% 4 0 20 27 bbox
+begingate
+1.00 0 0 0 Cr::d
+1.00 0 10 0 Cr::apostrophe
+endgate
+} def
+
+/Cr::dbar {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::d
+1.00 0 8 -8 Cr::bar
+endgate
+} def
+
+/Cr::ncaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::n
+1.00 0 0 -8 Cr::vee
+endgate
+} def
+
+/Cr::nacute {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::n
+1.00 0 2 -8 Cr::acute
+endgate
+} def
+
+/Cr::ucirc {
+% 4 0 20 26 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 2 -8 Cr::circ
+endgate
+} def
+
+/Cr::uuml2 {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::u
+1.00 0 4 -8 Cr::uml2
+endgate
+} def
+
+/Cr::tcedil {
+% 4 -6 20 32 bbox
+begingate
+1.00 0 0 0 Cr::t
+1.00 0 4 0 Cr::cedilla
+endgate
+} def
+
+/Cr::togonek {
+% 4 -5 20 31 bbox
+begingate
+1.00 0 0 0 Cr::t
+1.00 0 5 0 Cr::ced2
+endgate
+} def
+
+/Cr::ouml2 {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::o
+1.00 0 4 -8 Cr::uml2
+endgate
+} def
+
+/Cr::scaron {
+% 4 0 20 24 bbox
+begingate
+1.00 0 0 0 Cr::s
+1.00 0 0 -8 Cr::vee
+endgate
+} def
+
+/Cr::Tcaron {
+% 4 0 20 33 bbox
+begingate
+1.00 0 0 0 Cr::T
+1.00 0 3 1 Cr::vee
+endgate
+} def
+
+/Cr::dotacc {
+% 8 30 16 3 bbox
+begingate
+1.00 0 4 30 Cr::period
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/courieriso2.xfe b/lib/fonts/courieriso2.xfe
new file mode 100644
index 0000000..ec37550
--- /dev/null
+++ b/lib/fonts/courieriso2.xfe
@@ -0,0 +1,49 @@
+% XCircuit Font encoding (XFE) file
+name: CourierISO2
+% file: courier.lps
+file: courieriso2.lps
+family: Courier
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin2
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar
+Cr::space Cr::exclam Cr::quote Cr::pound Cr::dollar Cr::percent Cr::ampersand
+Cr::apostrophe Cr::lparen Cr::rparen Cr::asterisk Cr::plus Cr::comma Cr::minus
+Cr::period Cr::slash Cr::zero Cr::one Cr::two Cr::three Cr::four Cr::five
+Cr::six Cr::seven Cr::eight Cr::nine Cr::colon Cr::semi Cr::less Cr::equal
+Cr::more Cr::question Cr::at Cr::A Cr::B Cr::C Cr::D Cr::E Cr::F Cr::G Cr::H
+Cr::I Cr::J Cr::K Cr::L Cr::M Cr::N Cr::O Cr::P Cr::Q Cr::R Cr::S Cr::T Cr::U
+Cr::V Cr::W Cr::X Cr::Y Cr::Z Cr::lbracket Cr::backslash Cr::rbracket Cr::caret
+Cr::underscore Cr::apostrophe Cr::a Cr::b Cr::c Cr::d Cr::e Cr::f Cr::g Cr::h
+Cr::i Cr::j Cr::k Cr::l Cr::m Cr::n Cr::o Cr::p Cr::q Cr::r Cr::s Cr::t Cr::u
+Cr::v Cr::w Cr::x Cr::y Cr::z Cr::lbrace Cr::vbar Cr::rbrace Cr::tilde Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::Aogonek Cr::uu Cr::Lslash Cr::sy2 Cr::Lcaron Cr::Sacute Cr::sy1
+Cr::umlaut Cr::Scaron Cr::Scedil Cr::Tcaron Cr::Zacute Cr::dash Cr::Zcaron
+Cr::Zdot Cr::circ Cr::aogonek Cr::ced2 Cr::lslash Cr::acute Cr::lcaron
+Cr::sacute Cr::vee Cr::cedilla Cr::scaron Cr::scedil Cr::tcaron Cr::zacute
+Cr::uml2 Cr::zcaron Cr::zdot Cr::Racute Cr::Aacute Cr::Acircum Cr::Abreve
+Cr::Adier Cr::Lacute Cr::Cacute Cr::Ccedil Cr::Ccaron Cr::Eacute Cr::Eogonek
+Cr::Edier Cr::Ecaron Cr::Iacute Cr::Icircum Cr::Dcaron Cr::Eth Cr::Nacute
+Cr::Ncaron Cr::Oacute Cr::Ocircum Cr::Ouml2 Cr::Odier Cr::times Cr::Rcaron
+Cr::Ucirc Cr::Uacute Cr::Uuml2 Cr::Udier Cr::Yacute Cr::Tcedil Cr::sset
+Cr::racute Cr::aacute Cr::acircum Cr::abreve Cr::adier Cr::lacute Cr::cacute
+Cr::ccedil Cr::ecaron Cr::eacute Cr::eogonek Cr::edier Cr::ecaron Cr::iacute
+Cr::icircum Cr::dcaron Cr::dbar Cr::nacute Cr::ncaron Cr::oacute Cr::ocircum
+Cr::ouml2 Cr::odier Cr::divide Cr::rcaron Cr::ucirc Cr::uacute Cr::uuml2
+Cr::udier Cr::yacute Cr::togonek Cr::dotacc
+
+derived: Courier-BoldISO2 bold normal PostScript
+derived: Courier-ItalicISO2 normal italic PostScript
+derived: Courier-BoldItalicISO2 bold italic PostScript
diff --git a/lib/fonts/courieriso5.lps b/lib/fonts/courieriso5.lps
new file mode 100644
index 0000000..7a543f8
--- /dev/null
+++ b/lib/fonts/courieriso5.lps
@@ -0,0 +1,56 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Cr
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/Cr::Guu {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Cr::G
+1.00 0 0 2 Cr::uu
+endgate
+} def
+
+/Cr::Idot {
+% 4 0 20 37 bbox
+begingate
+1.00 0 0 0 Cr::I
+1.00 0 1 12 Cr::dot
+endgate
+} def
+
+/Cr::Scedil {
+% 4 -6 20 32 bbox
+begingate
+1.00 0 0 0 Cr::S
+1.00 0 1 0 Cr::cedilla
+endgate
+} def
+
+/Cr::scedil {
+% 4 -6 20 22 bbox
+begingate
+1.00 0 0 0 Cr::s
+1.00 0 4 0 Cr::cedilla
+endgate
+} def
+
+/Cr::guu {
+% 4 -6 20 30 bbox
+begingate
+1.00 0 0 0 Cr::g
+1.00 0 2 -8 Cr::uu
+endgate
+} def
+
+/Cr::dotlessi {
+% 6 0 18 24 bbox
+begingate
+1 1.00 6 0 18 0 2 polygon
+1 1.00 12 0 12 18 8 18 3 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/courieriso5.xfe b/lib/fonts/courieriso5.xfe
new file mode 100644
index 0000000..f500fca
--- /dev/null
+++ b/lib/fonts/courieriso5.xfe
@@ -0,0 +1,47 @@
+% XCircuit Font encoding (XFE) file
+name: CourierISO5
+% file: courier.lps
+file: courieriso5.lps
+family: Courier
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin5
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar
+Cr::space Cr::exclam Cr::quote Cr::pound Cr::dollar Cr::percent Cr::ampersand
+Cr::apostrophe Cr::lparen Cr::rparen Cr::asterisk Cr::plus Cr::comma Cr::minus
+Cr::period Cr::slash Cr::zero Cr::one Cr::two Cr::three Cr::four Cr::five
+Cr::six Cr::seven Cr::eight Cr::nine Cr::colon Cr::semi Cr::less Cr::equal
+Cr::more Cr::question Cr::at Cr::A Cr::B Cr::C Cr::D Cr::E Cr::F Cr::G Cr::H
+Cr::I Cr::J Cr::K Cr::L Cr::M Cr::N Cr::O Cr::P Cr::Q Cr::R Cr::S Cr::T Cr::U
+Cr::V Cr::W Cr::X Cr::Y Cr::Z Cr::lbracket Cr::backslash Cr::rbracket Cr::caret
+Cr::underscore Cr::apostrophe Cr::a Cr::b Cr::c Cr::d Cr::e Cr::f Cr::g Cr::h
+Cr::i Cr::j Cr::k Cr::l Cr::m Cr::n Cr::o Cr::p Cr::q Cr::r Cr::s Cr::t Cr::u
+Cr::v Cr::w Cr::x Cr::y Cr::z Cr::lbrace Cr::vbar Cr::rbrace Cr::tilde
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar
+Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::nullchar Cr::onesmall
+Cr::grave Cr::acute
+Cr::hat Cr::tilde Cr::bar Cr::uu Cr::dot Cr::umlaut Cr::nullchar Cr::circ
+Cr::cedilla Cr::nullchar Cr::uml2 Cr::ced2 Cr::vee Cr::space
+Cr::upexclam Cr::cent Cr::lb Cr::sy2 Cr::yen Cr::vbar Cr::sy1 Cr::umlaut Cr::copy
+Cr::ordfem Cr::lgqt Cr::lognot Cr::dash Cr::regis Cr::bar Cr::circ Cr::pm Cr::twosup
+Cr::threesup Cr::acute Cr::mu Cr::para Cr::dot Cr::cedilla Cr::onesup Cr::ordmasc
+Cr::rgqt Cr::quarter Cr::half Cr::threeq Cr::uqest
+Cr::Agrave Cr::Aacute Cr::Acircum Cr::Atilde Cr::Adier Cr::Aring Cr::AE Cr::Ccedil
+Cr::Egrave Cr::Eacute Cr::Ecircum Cr::Edier Cr::Igrave Cr::Iacute Cr::Icircum Cr::Idier
+Cr::Guu Cr::Ntilde Cr::Ograve Cr::Oacute Cr::Ocircum Cr::Otilde Cr::Odier Cr::times
+Cr::Oslash Cr::Ugrave Cr::Uacute Cr::Ucircum Cr::Udier Cr::Idot Cr::Scedil Cr::sset
+Cr::agrave Cr::aacute Cr::acircum Cr::atilde Cr::adier Cr::aring Cr::ae Cr::ccedil
+Cr::egrave Cr::eacute Cr::ecircum Cr::edier Cr::igrave Cr::iacute Cr::icircum Cr::idier
+Cr::guu Cr::ntilde Cr::ograve Cr::oacute Cr::ocircum Cr::otilde Cr::odier Cr::divide
+Cr::osl Cr::ugrave Cr::uacute Cr::ucircum Cr::udier Cr::dotlessi Cr::scedil Cr::ydier
+
+derived: Courier-BoldISO5 bold normal PostScript
+derived: Courier-ItalicISO5 normal italic PostScript
+derived: Courier-BoldItalicISO5 bold italic PostScript
diff --git a/lib/fonts/fonttest.ps b/lib/fonts/fonttest.ps
new file mode 100644
index 0000000..498c290
--- /dev/null
+++ b/lib/fonts/fonttest.ps
@@ -0,0 +1,22 @@
+%!Adobe-Postscript
+%
+% Print a list of all PostScript fonts resident on the printer
+%
+% To get the same list each printed in its own font, set "usefonts" to 1 below.
+%
+% Note: This is NOT an xcircuit file! The list of files returned may be
+% used to give xcircuit the proper name for a font when using the "Add New
+% Font" command.
+%
+/usefonts 0 def
+%
+/y 72 def
+/x 72 def
+/Times-Roman findfont 12 scalefont setfont
+FontDirectory {pop usefonts 1 eq {dup findfont 12 scalefont setfont} if
+50 string cvs x y moveto show y 15 add dup 690 gt {pop /y 72 def /x 300 def}
+{/y exch def} ifelse } forall
+/Times-Roman findfont 14 scalefont setfont
+305 700 moveto (Resident PostScript Fonts) dup stringwidth pop 2 div neg
+0 rmoveto show
+showpage
diff --git a/lib/fonts/helvetica.lps b/lib/fonts/helvetica.lps
new file mode 100644
index 0000000..8ffc052
--- /dev/null
+++ b/lib/fonts/helvetica.lps
@@ -0,0 +1,1711 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Hv
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/Hv::nullchar {
+% 0 0 24 32 bbox
+begingate
+0 1.00 0 0 0 32 24 32 24 0 4 polygon
+endgate
+} def
+
+/Hv::space {
+% 0 0 14 26 bbox
+begingate
+endgate
+} def
+
+/Hv::exclam {
+% 5 -1 4 29 bbox
+begingate
+1 1.00 6 0 1 0.00 360.00 xcarc
+0 1.00 7 28 6 5 5 28 3 polygon
+endgate
+} def
+
+/Hv::quote {
+% 5 21 10 6 bbox
+begingate
+0 1.00 5 27 6 21 7 27 3 polygon
+0 1.00 10 27 11 21 12 27 3 polygon
+endgate
+} def
+
+/Hv::pound {
+% 3 0 19 26 bbox
+begingate
+1 1.00 4 17 20 17 2 polygon
+1 1.00 14 0 18 26 2 polygon
+1 1.00 6 0 10 26 2 polygon
+1 1.00 3 9 19 9 2 polygon
+endgate
+} def
+
+/Hv::dollar {
+% 3 -4 20 30 bbox
+begingate
+1 1.00 4 4 5 2 9 0 13 0 17 2 19 4 19 7 17 10 6 12 3 15 3 18 5 20 9 22 13 22
+17 20 18 18 16 polygon
+1 1.00 11 -4 11 26 2 polygon
+endgate
+} def
+
+/Hv::percent {
+% 3 0 20 25 bbox
+begingate
+1 1.00 13 0 11 2 11 6 13 8 15 8 17 6 17 2 15 0 13 0 9 polygon
+1 1.00 3 0 17 25 2 polygon
+1 1.00 5 17 3 19 3 23 5 25 7 25 9 23 9 19 7 17 5 17 9 polygon
+endgate
+} def
+
+/Hv::ampersand {
+% 3 0 20 26 bbox
+begingate
+1 1.00 19 0 5 20 5 24 7 26 11 26 13 24 13 20 11 18 5 14 3 10 3 6 5 2 9 0 11 0
+15 2 18 5 19 8 17 polygon
+endgate
+} def
+
+/Hv::period {
+% 4 0 6 3 bbox
+begingate
+240 1.00 4 3 4 0 7 0 7 3 4 polygon
+endgate
+} def
+
+/Hv::apostrophe {
+% 3 20 8 7 bbox
+begingate
+1 1.00 4 20 6 22 6 24 3 polygon
+1.00 0 -1 24 Hv::period
+endgate
+} def
+
+/Hv::lparen {
+% 4 -5 7 32 bbox
+begingate
+1 1.00 10 -5 6 0 4 6 4 16 6 22 10 27 6 polygon
+endgate
+} def
+
+/Hv::rparen {
+% 4 -5 10 32 bbox
+begingate
+1 1.00 4 -5 8 0 10 6 10 16 8 22 4 27 6 polygon
+endgate
+} def
+
+/Hv::asterisk {
+% 3 14 12 18 bbox
+begingate
+1 1.00 8 18 8 22 2 polygon
+1 1.00 8 18 13 20 2 polygon
+1 1.00 8 18 3 20 2 polygon
+1 1.00 8 18 5 14 2 polygon
+1 1.00 8 18 11 14 2 polygon
+endgate
+} def
+
+/Hv::plus {
+% 2 6 22 12 bbox
+begingate
+1 1.00 10 4 10 20 2 polygon
+1 1.00 2 12 18 12 2 polygon
+endgate
+} def
+
+/Hv::comma {
+% 8 -4 5 6 bbox
+begingate
+1.00 0 4 -24 Hv::apostrophe
+endgate
+} def
+
+/Hv::minus {
+% 2 12 20 0 bbox
+begingate
+1 1.00 4 12 16 12 2 polygon
+endgate
+} def
+
+/Hv::slash {
+% 4 0 10 26 bbox
+begingate
+1 1.00 4 0 14 26 2 polygon
+endgate
+} def
+
+/Hv::zero {
+% 4 0 18 26 bbox
+begingate
+1 1.00 10 0 6 4 4 10 4 16 6 22 10 26 16 26 20 22 22 16 22 10 20 4 16 0 10 0
+13 polygon
+endgate
+} def
+
+/Hv::one {
+% 5 0 9 26 bbox
+begingate
+1 1.00 10 0 10 26 8 22 5 20 4 polygon
+endgate
+} def
+
+/Hv::two {
+% 4 0 19 26 bbox
+begingate
+1 1.00 22 0 4 0 8 4 20 12 22 16 22 20 20 24 16 26 12 26 8 24 6 22 11 polygon
+endgate
+} def
+
+/Hv::three {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 14 0 18 2 20 6 20 10 16 14 12 14 9 polygon
+1 1.00 16 14 20 18 20 20 18 24 14 26 10 26 6 24 4 22 8 polygon
+endgate
+} def
+
+/Hv::four {
+% 4 0 21 26 bbox
+begingate
+1 1.00 20 0 20 26 4 8 22 8 4 polygon
+endgate
+} def
+
+/Hv::five {
+% 4 0 18 26 bbox
+begingate
+1 1.00 4 2 8 0 14 0 18 2 20 6 20 12 18 16 14 18 8 18 4 16 6 26 18 26
+12 polygon
+endgate
+} def
+
+/Hv::six {
+% 4 0 18 26 bbox
+begingate
+1 1.00 20 24 16 26 10 26 6 22 4 16 4 10 6 4 10 0 16 0 20 2 22 6 22 12 20 16
+16 18 10 18 6 16 4 14 17 polygon
+endgate
+} def
+
+/Hv::seven {
+% 4 0 16 26 bbox
+begingate
+1 1.00 10 0 10 4 12 12 20 26 4 26 5 polygon
+endgate
+} def
+
+/Hv::eight {
+% 4 0 20 26 bbox
+begingate
+1 1.00 10 0 6 2 4 4 4 8 8 12 18 16 20 20 20 22 16 26 10 26 6 22 6 20 8 16
+18 12 22 8 22 4 20 2 16 0 10 0 19 polygon
+endgate
+} def
+
+/Hv::nine {
+% 4 0 18 26 bbox
+begingate
+1 1.00 6 2 10 0 16 0 20 4 22 10 22 18 20 24 16 26 10 26 6 24 4 20 4 16 6 12
+10 10 16 10 20 12 22 14 17 polygon
+endgate
+} def
+
+/Hv::colon {
+% 4 0 9 11 bbox
+begingate
+1.00 0 2 14 Hv::period
+1.00 0 2 0 Hv::period
+endgate
+} def
+
+/Hv::semi {
+% 4 -4 6 23 bbox
+begingate
+1.00 0 0 16 Hv::period
+1.00 0 1 -24 Hv::apostrophe
+endgate
+} def
+
+/Hv::less {
+% 4 6 20 12 bbox
+begingate
+1 1.00 19 5 4 12 19 19 3 polygon
+endgate
+} def
+
+/Hv::equal {
+% 2 8 19 6 bbox
+begingate
+1 1.00 4 8 20 8 2 polygon
+1 1.00 4 14 20 14 2 polygon
+endgate
+} def
+
+/Hv::more {
+% 4 6 20 12 bbox
+begingate
+1 1.00 4 5 20 12 4 19 3 polygon
+endgate
+} def
+
+/Hv::question {
+% 4 0 20 26 bbox
+begingate
+1.00 0 4 0 Hv::period
+1 1.00 4 22 8 26 14 26 18 22 18 18 16 14 12 12 10 10 10 8 9 polygon
+endgate
+} def
+
+/Hv::at {
+% 4 0 30 26 bbox
+begingate
+1 1.00 26 2 18 0 14 0 10 2 6 6 4 10 4 16 6 20 10 24 14 26 20 26 24 24 28 20
+30 16 30 12 28 8 26 6 24 5 21 5 20 8 22 20 21 polygon
+1 1.00 21 16 20 19 17 20 14 19 11 15 11 10 14 7 17 6 20 7 9 polygon
+endgate
+} def
+
+/Hv::A {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 0 14 26 24 0 3 polygon
+1 1.00 8 10 20 10 2 polygon
+endgate
+} def
+
+/Hv::B {
+% 4 0 23 26 bbox
+begingate
+1 1.00 4 0 4 26 14 26 19 24 21 20 21 18 17 14 4 14 8 polygon
+1 1.00 4 0 17 0 21 2 23 6 23 8 21 12 17 14 7 polygon
+endgate
+} def
+
+/Hv::C {
+% 4 0 24 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 22 9 polygon
+1 1.00 18 0 24 4 2 polygon
+endgate
+} def
+
+/Hv::D {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 0 16 0 22 4 24 10 24 16 22 22 16 26 4 26 4 0 9 polygon
+endgate
+} def
+
+/Hv::E {
+% 4 0 22 26 bbox
+begingate
+1 1.00 22 0 4 0 4 26 22 26 4 polygon
+1 1.00 4 14 18 14 2 polygon
+endgate
+} def
+
+/Hv::F {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 0 4 26 20 26 3 polygon
+1 1.00 4 14 16 14 2 polygon
+endgate
+} def
+
+/Hv::G {
+% 4 0 26 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 22 9 polygon
+1 1.00 18 0 24 2 26 6 26 12 18 12 5 polygon
+endgate
+} def
+
+/Hv::H {
+% 4 0 27 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 23 0 23 26 2 polygon
+1 1.00 4 14 23 14 2 polygon
+endgate
+} def
+
+/Hv::I {
+% 6 0 5 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+endgate
+} def
+
+/Hv::J {
+% 4 0 21 26 bbox
+begingate
+1 1.00 4 6 6 2 10 0 12 0 16 2 18 6 18 26 7 polygon
+endgate
+} def
+
+/Hv::K {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 22 26 4 10 2 polygon
+1 1.00 22 0 10 14 2 polygon
+endgate
+} def
+
+/Hv::L {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 26 4 0 20 0 3 polygon
+endgate
+} def
+
+/Hv::M {
+% 4 0 28 26 bbox
+begingate
+1 1.00 4 0 4 26 16 0 28 26 28 0 5 polygon
+endgate
+} def
+
+/Hv::N {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 0 4 26 24 0 24 26 4 polygon
+endgate
+} def
+
+/Hv::O {
+% 4 0 26 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 22 9 polygon
+1 1.00 18 0 24 4 26 10 26 16 24 22 5 polygon
+endgate
+} def
+
+/Hv::P {
+% 4 0 21 26 bbox
+begingate
+1 1.00 4 0 4 26 17 26 21 22 21 18 17 14 4 14 7 polygon
+endgate
+} def
+
+/Hv::Q {
+% 4 0 26 26 bbox
+begingate
+1 1.00 23 0 14 6 2 polygon
+1.00 0 0 0 Hv::O
+endgate
+} def
+
+/Hv::R {
+% 4 0 23 26 bbox
+begingate
+1 1.00 4 0 4 26 17 26 21 22 21 18 17 14 4 14 7 polygon
+1 1.00 12 14 23 0 2 polygon
+endgate
+} def
+
+/Hv::S {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 6 6 2 10 0 16 0 20 2 22 6 22 8 18 12 6 18 4 20 4 22 6 24 10 26 16 26
+20 24 15 polygon
+endgate
+} def
+
+/Hv::T {
+% 4 0 22 26 bbox
+begingate
+1 1.00 13 0 13 26 2 polygon
+1 1.00 4 26 22 26 2 polygon
+endgate
+} def
+
+/Hv::U {
+% 4 0 25 26 bbox
+begingate
+1 1.00 4 26 4 8 6 4 8 2 12 0 17 0 21 2 23 4 25 8 25 26 10 polygon
+endgate
+} def
+
+/Hv::V {
+% 4 0 26 26 bbox
+begingate
+1 1.00 4 26 15 0 26 26 3 polygon
+endgate
+} def
+
+/Hv::W {
+% 4 0 36 26 bbox
+begingate
+1 1.00 4 26 12 0 20 26 28 0 36 26 5 polygon
+endgate
+} def
+
+/Hv::X {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 0 24 26 2 polygon
+1 1.00 4 26 24 0 2 polygon
+endgate
+} def
+
+/Hv::Y {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 26 14 14 14 0 3 polygon
+1 1.00 24 26 14 14 2 polygon
+endgate
+} def
+
+/Hv::Z {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 26 22 26 4 0 22 0 4 polygon
+endgate
+} def
+
+/Hv::lbracket {
+% 4 -2 5 30 bbox
+begingate
+1 1.00 10 -2 4 -2 4 28 10 28 4 polygon
+endgate
+} def
+
+/Hv::backslash {
+% 4 0 10 26 bbox
+begingate
+1 1.00 14 0 4 26 2 polygon
+endgate
+} def
+
+/Hv::rbracket {
+% 4 -2 6 30 bbox
+begingate
+1 1.00 4 -2 10 -2 10 28 4 28 4 polygon
+endgate
+} def
+
+/Hv::caret {
+% 4 20 12 6 bbox
+begingate
+1 1.00 4 20 10 26 16 20 3 polygon
+endgate
+} def
+
+/Hv::underscore {
+% 4 0 20 0 bbox
+begingate
+1 1.00 4 0 24 0 2 polygon
+endgate
+} def
+
+/Hv::a {
+% 4 0 18 16 bbox
+begingate
+1 1.00 20 0 18 2 18 12 14 16 8 16 6 14 6 polygon
+1 1.00 18 2 14 0 8 0 4 2 4 4 8 8 18 8 7 polygon
+endgate
+} def
+
+/Hv::b {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 4 2 8 0 12 0 16 2 18 6 18 10 16 14 12 16 8 16 4 14 10 polygon
+endgate
+} def
+
+/Hv::c {
+% 4 0 16 16 bbox
+begingate
+1 1.00 18 2 14 0 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 10 polygon
+endgate
+} def
+
+/Hv::d {
+% 4 0 16 26 bbox
+begingate
+1 1.00 18 2 14 0 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 10 polygon
+1 1.00 18 0 18 26 2 polygon
+endgate
+} def
+
+/Hv::e {
+% 4 0 18 16 bbox
+begingate
+1 1.00 18 2 14 0 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 10 polygon
+1 1.00 4 8 20 8 20 10 18 14 4 polygon
+endgate
+} def
+
+/Hv::f {
+% 4 0 12 26 bbox
+begingate
+1 1.00 8 0 8 24 10 26 14 26 4 polygon
+1 1.00 4 18 12 18 2 polygon
+endgate
+} def
+
+/Hv::g {
+% 4 -6 16 22 bbox
+begingate
+1 1.00 18 2 14 0 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 10 polygon
+1 1.00 6 -4 8 -6 14 -6 18 -4 18 16 5 polygon
+endgate
+} def
+
+/Hv::h {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 4 14 8 16 14 16 18 12 18 0 5 polygon
+endgate
+} def
+
+/Hv::i {
+% 6 0 2 22 bbox
+begingate
+1 1.00 6 0 6 16 2 polygon
+1 1.00 6 21 6 22 2 polygon
+endgate
+} def
+
+/Hv::j {
+% 1 -6 10 28 bbox
+begingate
+1 1.00 1 -6 4 -6 6 -4 6 16 4 polygon
+1 1.00 6 21 6 22 2 polygon
+endgate
+} def
+
+/Hv::k {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 4 8 16 16 2 polygon
+1 1.00 18 0 8 10 2 polygon
+endgate
+} def
+
+/Hv::l {
+% 3 0 6 26 bbox
+begingate
+1 1.00 3 0 3 26 2 polygon
+endgate
+} def
+
+/Hv::m {
+% 4 0 30 16 bbox
+begingate
+1 1.00 4 0 4 16 2 polygon
+1 1.00 4 14 9 16 14 16 17 14 17 0 5 polygon
+1 1.00 17 14 22 16 27 16 30 14 30 0 5 polygon
+endgate
+} def
+
+/Hv::n {
+% 4 0 16 16 bbox
+begingate
+1 1.00 4 0 4 16 2 polygon
+1 1.00 4 14 8 16 14 16 18 12 18 0 5 polygon
+endgate
+} def
+
+/Hv::o {
+% 4 0 16 16 bbox
+begingate
+1 1.00 10 0 6 2 4 6 4 10 6 14 10 16 12 16 16 14 18 10 18 6 16 2 12 0 10 0
+13 polygon
+endgate
+} def
+
+/Hv::p {
+% 4 -6 16 22 bbox
+begingate
+1 1.00 4 2 8 0 12 0 16 2 18 6 18 10 16 14 12 16 8 16 4 14 10 polygon
+1 1.00 4 16 4 -6 2 polygon
+endgate
+} def
+
+/Hv::q {
+% 4 -6 17 22 bbox
+begingate
+1 1.00 18 2 14 0 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 10 polygon
+1 1.00 18 16 18 -6 2 polygon
+endgate
+} def
+
+/Hv::r {
+% 4 0 12 16 bbox
+begingate
+1 1.00 4 0 4 16 2 polygon
+1 1.00 4 14 8 16 12 16 14 14 4 polygon
+endgate
+} def
+
+/Hv::s {
+% 4 0 16 16 bbox
+begingate
+1 1.00 4 2 8 0 14 0 18 2 18 4 16 6 6 10 4 12 4 14 8 16 14 16 18 14 12 polygon
+endgate
+} def
+
+/Hv::t {
+% 4 0 10 26 bbox
+begingate
+1 1.00 4 18 12 18 2 polygon
+1 1.00 8 26 8 2 10 0 12 0 4 polygon
+endgate
+} def
+
+/Hv::u {
+% 4 0 16 16 bbox
+begingate
+1 1.00 4 16 4 4 8 0 14 0 18 2 5 polygon
+1 1.00 18 0 18 16 2 polygon
+endgate
+} def
+
+/Hv::v {
+% 4 0 18 16 bbox
+begingate
+1 1.00 4 16 12 0 20 16 3 polygon
+endgate
+} def
+
+/Hv::w {
+% 4 0 26 16 bbox
+begingate
+1 1.00 4 16 10 0 16 16 22 0 28 16 5 polygon
+endgate
+} def
+
+/Hv::x {
+% 4 0 16 16 bbox
+begingate
+1 1.00 4 0 18 16 2 polygon
+1 1.00 4 16 18 0 2 polygon
+endgate
+} def
+
+/Hv::y {
+% 4 -6 16 22 bbox
+begingate
+1 1.00 4 16 12 1 2 polygon
+1 1.00 18 16 10 -4 8 -6 6 -6 4 polygon
+endgate
+} def
+
+/Hv::z {
+% 4 0 16 16 bbox
+begingate
+1 1.00 4 16 18 16 4 0 18 0 4 polygon
+endgate
+} def
+
+/Hv::lbrace {
+% 4 -4 11 32 bbox
+begingate
+1 1.00 10 -4 8 -4 6 -2 6 10 4 12 6 14 6 26 8 28 10 28 9 polygon
+endgate
+} def
+
+/Hv::vbar {
+% 6 -2 5 30 bbox
+begingate
+1 1.00 6 -2 6 28 2 polygon
+endgate
+} def
+
+/Hv::rbrace {
+% 4 -4 9 32 bbox
+begingate
+1 1.00 4 -4 6 -4 8 -2 8 10 10 12 8 14 8 26 6 28 4 28 9 polygon
+endgate
+} def
+
+/Hv::tilde {
+% 2 12 19 2 bbox
+begingate
+1 1.00 4 12 6 14 10 14 14 12 18 12 20 14 6 polygon
+endgate
+} def
+
+/Hv::upexclam {
+% 5 0 8 29 bbox
+begingate
+1.00 -181 0 28 Hv::exclam
+endgate
+} def
+
+/Hv::cent {
+% 4 -6 17 28 bbox
+begingate
+1 1.00 4 -6 18 22 2 polygon
+1.00 0 0 0 Hv::c
+endgate
+} def
+
+/Hv::lb {
+% 4 0 18 26 bbox
+begingate
+1 1.00 22 2 20 0 17 0 12 2 7 2 4 0 6 polygon
+1 1.00 5 14 15 14 2 polygon
+1 1.00 7 2 10 4 11 9 9 18 9 21 12 25 16 26 18 25 20 23 9 polygon
+endgate
+} def
+
+/Hv::aslash {
+% 4 0 14 26 bbox
+begingate
+1 1.00 4 0 18 26 2 polygon
+endgate
+} def
+
+/Hv::yen {
+% 2 0 20 26 bbox
+begingate
+1.00 0 -2 0 Hv::Y
+1 1.00 4 8 20 8 2 polygon
+1 1.00 4 14 20 14 2 polygon
+endgate
+} def
+
+/Hv::itf {
+% 0 -6 18 32 bbox
+begingate
+1 1.00 4 18 14 18 2 polygon
+1 1.00 0 -6 4 -6 6 -4 10 24 12 26 14 26 16 24 7 polygon
+endgate
+} def
+
+/Hv::sy1 {
+% 4 -6 12 32 bbox
+begingate
+1 1.00 4 -2 6 -6 10 -6 14 -2 14 0 6 8 4 12 4 14 8 18 9 polygon
+1 1.00 12 2 16 6 16 8 14 12 6 20 6 22 10 26 14 26 16 22 9 polygon
+endgate
+} def
+
+/Hv::sy2 {
+% 4 0 16 16 bbox
+begingate
+1 1.00 12 8 8 0.00 360.00 xcarc
+1 1.00 4 16 6 14 2 polygon
+1 1.00 18 2 20 0 2 polygon
+1 1.00 4 0 6 2 2 polygon
+1 1.00 18 14 20 16 2 polygon
+endgate
+} def
+
+/Hv::apos2 {
+% 8 24 2 8 bbox
+begingate
+240 1.00 10 32 10 28 9 24 8 28 8 32 5 polygon
+endgate
+} def
+
+/Hv::lqt {
+% 6 22 12 7 bbox
+begingate
+1.00 180 12 49 Hv::apostrophe
+1.00 180 18 49 Hv::apostrophe
+endgate
+} def
+
+/Hv::lgqt {
+% 4 4 14 14 bbox
+begingate
+1 1.00 10 4 4 11 10 18 3 polygon
+1 1.00 16 4 10 11 16 18 3 polygon
+endgate
+} def
+
+/Hv::lsang {
+% 4 4 8 14 bbox
+begingate
+1 1.00 10 4 4 11 10 18 3 polygon
+endgate
+} def
+
+/Hv::rsang {
+% 6 4 8 14 bbox
+begingate
+1 1.00 6 4 12 11 6 18 3 polygon
+endgate
+} def
+
+/Hv::fi {
+% 2 0 26 26 bbox
+begingate
+1.00 0 0 0 Hv::f
+1.00 0 10 0 Hv::i
+endgate
+} def
+
+/Hv::fl {
+% 4 0 26 26 bbox
+begingate
+1.00 0 0 0 Hv::f
+1.00 0 12 0 Hv::l
+endgate
+} def
+
+/Hv::dag {
+% 4 0 12 24 bbox
+begingate
+1 1.00 10 0 10 24 2 polygon
+1 1.00 4 18 16 18 2 polygon
+endgate
+} def
+
+/Hv::ddag {
+% 4 0 12 24 bbox
+begingate
+1 1.00 10 0 10 24 2 polygon
+1 1.00 4 18 16 18 2 polygon
+1 1.00 4 6 16 6 2 polygon
+endgate
+} def
+
+/Hv::dot {
+% 8 22 3 3 bbox
+begingate
+1.00 0 4 22 Hv::period
+endgate
+} def
+
+/Hv::para {
+% 4 0 15 26 bbox
+begingate
+1 1.00 11 0 11 26 2 polygon
+1 1.00 16 0 16 26 2 polygon
+1 1.00 11 26 19 26 2 polygon
+240 1.00 11 19 7 90.00 270.00 xcarc
+endgate
+} def
+
+/Hv::bullet {
+% 4 11 8 8 bbox
+begingate
+241 1.00 8 15 4 0.00 360.00 xcarc
+endgate
+} def
+
+/Hv::comma2 {
+% 6 -4 3 7 bbox
+begingate
+1.00 0 3 -24 Hv::apostrophe
+endgate
+} def
+
+/Hv::rqt2 {
+% 6 -4 12 7 bbox
+begingate
+1.00 0 3 -24 Hv::apostrophe
+1.00 0 9 -24 Hv::apostrophe
+endgate
+} def
+
+/Hv::rqt {
+% 7 20 12 7 bbox
+begingate
+1.00 0 1 24 Hv::rqt2
+endgate
+} def
+
+/Hv::rgqt {
+% 4 4 14 14 bbox
+begingate
+1 1.00 4 4 10 11 4 18 3 polygon
+1 1.00 10 4 16 11 10 18 3 polygon
+endgate
+} def
+
+/Hv::dots {
+% 6 0 30 3 bbox
+begingate
+1.00 0 2 0 Hv::period
+1.00 0 14 0 Hv::period
+1.00 0 26 0 Hv::period
+endgate
+} def
+
+/Hv::perzer {
+% 1 0 26 25 bbox
+begingate
+1 1.00 20 0 18 2 18 6 20 8 22 8 24 6 24 2 22 0 20 0 9 polygon
+1.00 0 -2 0 Hv::percent
+endgate
+} def
+
+/Hv::uqest {
+% 4 0 16 26 bbox
+begingate
+1.00 180 22 26 Hv::question
+endgate
+} def
+
+/Hv::grave {
+% 6 27 8 5 bbox
+begingate
+0 1.00 6 32 12 27 9 32 3 polygon
+endgate
+} def
+
+/Hv::acute {
+% 8 27 6 5 bbox
+begingate
+1.00 -1 20 0 Hv::grave
+endgate
+} def
+
+/Hv::hat {
+% 6 28 8 4 bbox
+begingate
+1 1.00 6 28 10 32 14 28 3 polygon
+endgate
+} def
+
+/Hv::tilchar {
+% 6 29 8 3 bbox
+begingate
+1 1.00 6 29 8 32 9 32 11 29 12 29 14 32 6 polygon
+endgate
+} def
+
+/Hv::bar {
+% 6 30 8 0 bbox
+begingate
+1 1.00 6 30 14 30 2 polygon
+endgate
+} def
+
+/Hv::uu {
+% 5 29 10 3 bbox
+begingate
+1 1.00 5 32 7 30 10 29 13 30 15 32 5 polygon
+endgate
+} def
+
+/Hv::umlaut {
+% 5 29 11 3 bbox
+begingate
+1.00 0 1 29 Hv::period
+1.00 0 9 29 Hv::period
+endgate
+} def
+
+/Hv::circ {
+% 6 26 8 8 bbox
+begingate
+1 1.00 10 30 4 0.00 360.00 xcarc
+endgate
+} def
+
+/Hv::cedilla {
+% 7 -6 4 6 bbox
+begingate
+1 1.00 9 0 7 -2 11 -4 9 -6 4 polygon
+endgate
+} def
+
+/Hv::uml2 {
+% 4 27 12 5 bbox
+begingate
+0 1.00 8 32 4 27 10 32 3 polygon
+0 1.00 14 32 10 27 16 32 3 polygon
+endgate
+} def
+
+/Hv::ced2 {
+% 6 -5 4 5 bbox
+begingate
+1 1.00 7 0 6 -3 8 -5 10 -4 4 polygon
+endgate
+} def
+
+/Hv::vee {
+% 6 28 8 4 bbox
+begingate
+1 1.00 6 32 10 28 14 32 3 polygon
+endgate
+} def
+
+/Hv::Oslash {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 0 24 26 2 polygon
+1.00 0 0 0 Hv::O
+endgate
+} def
+
+/Hv::osl {
+% 4 0 14 16 bbox
+begingate
+1 1.00 4 0 18 16 2 polygon
+1.00 0 0 0 Hv::o
+endgate
+} def
+
+/Hv::sset {
+% 4 0 14 26 bbox
+begingate
+1 1.00 4 0 4 20 6 25 9 26 13 26 16 24 17 21 16 18 12 15 9 polygon
+1 1.00 12 15 16 12 18 8 18 3 14 0 10 0 7 3 7 polygon
+endgate
+} def
+
+/Hv::Agrave {
+% 4 0 20 33 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 1 Hv::grave
+endgate
+} def
+
+/Hv::Aacute {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 2 Hv::acute
+endgate
+} def
+
+/Hv::Acircum {
+% 4 0 22 33 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 1 Hv::hat
+endgate
+} def
+
+/Hv::Atilde {
+% 4 0 22 33 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 1 Hv::tilchar
+endgate
+} def
+
+/Hv::Adier {
+% 4 0 22 33 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 1 Hv::umlaut
+endgate
+} def
+
+/Hv::Aring {
+% 4 0 22 36 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 2 Hv::circ
+endgate
+} def
+
+/Hv::Egrave {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 2 2 Hv::grave
+endgate
+} def
+
+/Hv::Eacute {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 1 2 Hv::acute
+endgate
+} def
+
+/Hv::Ecircum {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 3 2 Hv::hat
+endgate
+} def
+
+/Hv::Edier {
+% 4 0 20 33 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 2 1 Hv::umlaut
+endgate
+} def
+
+/Hv::Ccedil {
+% 4 -6 24 32 bbox
+begingate
+1.00 0 0 0 Hv::C
+1.00 0 6 0 Hv::cedilla
+endgate
+} def
+
+/Hv::Igrave {
+% -8 0 30 34 bbox
+begingate
+1.00 0 0 0 Hv::I
+1.00 0 -4 2 Hv::grave
+endgate
+} def
+
+/Hv::Iacute {
+% -4 0 20 34 bbox
+begingate
+1.00 0 4 0 Hv::I
+1.00 0 -1 2 Hv::acute
+endgate
+} def
+
+/Hv::Icircum {
+% -4 0 20 33 bbox
+begingate
+1.00 0 4 0 Hv::I
+1.00 0 0 1 Hv::hat
+endgate
+} def
+
+/Hv::Idier {
+% -4 0 20 33 bbox
+begingate
+1.00 0 4 0 Hv::I
+1.00 0 -1 1 Hv::umlaut
+endgate
+} def
+
+/Hv::Otilde {
+% 4 0 24 33 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 5 1 Hv::tilchar
+endgate
+} def
+
+/Hv::Ugrave {
+% 4 0 23 33 bbox
+begingate
+1.00 0 0 0 Hv::U
+1.00 0 5 1 Hv::grave
+endgate
+} def
+
+/Hv::Uacute {
+% 4 0 23 32 bbox
+begingate
+1.00 0 0 0 Hv::U
+1.00 0 4 0 Hv::acute
+endgate
+} def
+
+/Hv::Ucircum {
+% 5 0 23 33 bbox
+begingate
+1.00 0 1 0 Hv::U
+1.00 0 5 1 Hv::hat
+endgate
+} def
+
+/Hv::Udier {
+% 4 0 23 32 bbox
+begingate
+1.00 0 0 0 Hv::U
+1.00 0 4 0 Hv::umlaut
+endgate
+} def
+
+/Hv::Ograve {
+% 4 0 24 36 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 4 4 Hv::grave
+endgate
+} def
+
+/Hv::Oacute {
+% 4 0 24 36 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 4 4 Hv::acute
+endgate
+} def
+
+/Hv::Ocircum {
+% 4 0 24 34 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 4 2 Hv::hat
+endgate
+} def
+
+/Hv::Odier {
+% 4 0 24 33 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 5 1 Hv::umlaut
+endgate
+} def
+
+/Hv::Ntilde {
+% 4 0 22 32 bbox
+begingate
+1.00 0 0 0 Hv::N
+1.00 0 4 0 Hv::tilchar
+endgate
+} def
+
+/Hv::AE {
+% 4 0 36 26 bbox
+begingate
+1.00 0 16 0 Hv::E
+1 1.00 20 26 4 0 2 polygon
+1 1.00 20 10 11 10 2 polygon
+endgate
+} def
+
+/Hv::Eth {
+% 4 0 26 26 bbox
+begingate
+1.00 0 4 0 Hv::D
+1 1.00 12 12 4 12 2 polygon
+endgate
+} def
+
+/Hv::Yacute {
+% 4 0 22 32 bbox
+begingate
+1.00 0 0 0 Hv::Y
+1.00 0 4 0 Hv::acute
+endgate
+} def
+
+/Hv::agrave {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -8 Hv::grave
+endgate
+} def
+
+/Hv::aacute {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -8 Hv::acute
+endgate
+} def
+
+/Hv::acircum {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -8 Hv::hat
+endgate
+} def
+
+/Hv::atilde {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -8 Hv::tilchar
+endgate
+} def
+
+/Hv::adier {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -8 Hv::umlaut
+endgate
+} def
+
+/Hv::aring {
+% 4 0 18 28 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -6 Hv::circ
+endgate
+} def
+
+/Hv::ntilde {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::n
+1.00 0 0 -8 Hv::tilchar
+endgate
+} def
+
+/Hv::egrave {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::e
+1.00 0 2 -8 Hv::grave
+endgate
+} def
+
+/Hv::eacute {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::e
+1.00 0 2 -8 Hv::acute
+endgate
+} def
+
+/Hv::ecircum {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::e
+1.00 0 2 -8 Hv::hat
+endgate
+} def
+
+/Hv::edier {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::e
+1.00 0 2 -8 Hv::umlaut
+endgate
+} def
+
+/Hv::ae {
+% 4 0 30 16 bbox
+begingate
+1.00 0 12 0 Hv::e
+1 1.00 18 2 14 0 8 0 4 2 4 4 8 8 18 8 7 polygon
+1 1.00 6 14 8 16 14 16 17 13 4 polygon
+endgate
+} def
+
+/Hv::igrave {
+% 2 0 8 24 bbox
+begingate
+1.00 0 -4 -8 Hv::grave
+1 1.00 6 16 6 0 2 polygon
+endgate
+} def
+
+/Hv::iacute {
+% -8 -8 20 26 bbox
+begingate
+1.00 0 -8 -8 Hv::acute
+1 1.00 2 16 2 0 2 polygon
+endgate
+} def
+
+/Hv::icircum {
+% -8 -8 20 26 bbox
+begingate
+1.00 0 -8 -8 Hv::hat
+1 1.00 2 16 2 0 2 polygon
+endgate
+} def
+
+/Hv::idier {
+% -8 -8 20 26 bbox
+begingate
+1.00 0 -8 -8 Hv::umlaut
+1 1.00 2 16 2 0 2 polygon
+endgate
+} def
+
+/Hv::ydier {
+% 4 -6 16 30 bbox
+begingate
+1.00 0 0 0 Hv::y
+1.00 0 0 -8 Hv::umlaut
+endgate
+} def
+
+/Hv::yacute {
+% 4 -6 16 30 bbox
+begingate
+1.00 0 0 0 Hv::y
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::ograve {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 2 -8 Hv::grave
+endgate
+} def
+
+/Hv::oacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::ocircum {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 0 -8 Hv::hat
+endgate
+} def
+
+/Hv::otilde {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 0 -8 Hv::tilchar
+endgate
+} def
+
+/Hv::odier {
+% 4 0 16 22 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 0 -10 Hv::umlaut
+endgate
+} def
+
+/Hv::eth {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1 1.00 16 14 10 22 4 24 3 polygon
+1 1.00 12 24 6 20 2 polygon
+endgate
+} def
+
+/Hv::ugrave {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 2 -8 Hv::grave
+endgate
+} def
+
+/Hv::uacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::ucircum {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 0 -8 Hv::hat
+endgate
+} def
+
+/Hv::udier {
+% 4 0 16 22 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 0 -10 Hv::umlaut
+endgate
+} def
+
+/Hv::ccedil {
+% 4 -6 16 22 bbox
+begingate
+1.00 0 2 0 Hv::cedilla
+1.00 0 0 0 Hv::c
+endgate
+} def
+
+/Hv::ordfem {
+% 6 20 13 9 bbox
+begingate
+0.60 0 4 20 Hv::a
+endgate
+} def
+
+/Hv::Lslash {
+% 4 0 26 26 bbox
+begingate
+1.00 0 4 0 Hv::L
+1 1.00 16 20 4 12 2 polygon
+endgate
+} def
+
+/Hv::ordmasc {
+% 4 18 12 9 bbox
+begingate
+0.60 0 2 18 Hv::o
+endgate
+} def
+
+/Hv::lslash {
+% 6 0 11 26 bbox
+begingate
+1.00 0 6 0 Hv::l
+1 1.00 12 16 6 12 2 polygon
+endgate
+} def
+
+/Hv::OE {
+% 6 0 34 26 bbox
+begingate
+1 1.00 38 0 24 0 24 26 38 26 4 polygon
+1 1.00 36 14 24 14 2 polygon
+1.00 0 2 0 Hv::zero
+endgate
+} def
+
+/Hv::oe {
+% 8 0 34 16 bbox
+begingate
+1.00 0 18 0 Hv::e
+1.00 0 4 0 Hv::o
+endgate
+} def
+
+/Hv::emdash {
+% 2 10 30 0 bbox
+begingate
+1 1.00 2 10 30 10 2 polygon
+endgate
+} def
+
+/Hv::pm {
+% 6 6 14 15 bbox
+begingate
+1.00 0 2 3 Hv::plus
+1.00 0 2 -6 Hv::minus
+endgate
+} def
+
+/Hv::onesup {
+% 7 18 5 15 bbox
+begingate
+0.60 0 4 18 Hv::one
+endgate
+} def
+
+/Hv::twosup {
+% 4 18 13 15 bbox
+begingate
+0.60 0 2 18 Hv::two
+endgate
+} def
+
+/Hv::threesup {
+% 4 18 12 15 bbox
+begingate
+0.60 0 2 18 Hv::three
+endgate
+} def
+
+/Hv::quarter {
+% 5 0 24 27 bbox
+begingate
+0.60 0 12 0 Hv::four
+0.60 0 2 12 Hv::one
+1 1.00 6 0 22 24 2 polygon
+endgate
+} def
+
+/Hv::half {
+% 3 0 28 27 bbox
+begingate
+0.60 0 0 12 Hv::one
+0.60 0 14 0 Hv::two
+1 1.00 4 0 20 24 2 polygon
+endgate
+} def
+
+/Hv::threeq {
+% 4 0 27 27 bbox
+begingate
+0.60 0 2 12 Hv::three
+0.60 0 14 0 Hv::four
+1 1.00 8 0 24 24 2 polygon
+endgate
+} def
+
+/Hv::copy {
+% 4 4 26 24 bbox
+begingate
+0.60 0 7 8 Hv::C
+1 1.00 16 16 12 0.00 360.00 xcarc
+endgate
+} def
+
+/Hv::regis {
+% 4 4 26 24 bbox
+begingate
+0.55 0 9 9 Hv::R
+1 1.00 16 16 12 0.00 360.00 xcarc
+endgate
+} def
+
+/Hv::mu {
+% 6 -8 18 24 bbox
+begingate
+1.00 0 2 0 Hv::u
+1 1.00 6 -8 6 4 2 polygon
+endgate
+} def
+
+/Hv::lognot {
+% 6 8 18 8 bbox
+begingate
+1 1.00 6 16 22 16 22 8 3 polygon
+endgate
+} def
+
+/Hv::times {
+% 6 6 14 12 bbox
+begingate
+1 1.00 6 6 18 18 2 polygon
+1 1.00 6 18 18 6 2 polygon
+endgate
+} def
+
+/Hv::divide {
+% 5 5 18 14 bbox
+begingate
+1 1.00 5 12 21 12 2 polygon
+1.00 0 8 16 Hv::period
+1.00 0 8 5 Hv::period
+endgate
+} def
+
+/Hv::thorn {
+% 4 -6 18 30 bbox
+begingate
+1.00 0 0 0 Hv::p
+1 1.00 4 16 4 24 2 polygon
+endgate
+} def
+
+/Hv::Thorn {
+% 4 0 15 26 bbox
+begingate
+1.00 0 -2 0 Hv::I
+1 1.00 4 8 12 8 16 10 17 14 16 18 12 20 4 20 7 polygon
+endgate
+} def
+
+/Hv::onesmall {
+% 7 4 6 19 bbox
+begingate
+0.75 0 4 4 Hv::one
+endgate
+} def
+
+/Hv::dash {
+% 4 12 20 0 bbox
+begingate
+1 1.00 4 12 18 12 2 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/helvetica.xfe b/lib/fonts/helvetica.xfe
new file mode 100644
index 0000000..f1fa468
--- /dev/null
+++ b/lib/fonts/helvetica.xfe
@@ -0,0 +1,48 @@
+% XCircuit Font encoding (XFE) file
+name: Helvetica
+file: helvetica.lps
+family: Helvetica
+weight: normal
+shape: normal
+type: PostScript
+encoding: Standard
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar
+Hv::space Hv::exclam Hv::quote Hv::pound Hv::dollar Hv::percent Hv::ampersand
+Hv::apostrophe Hv::lparen Hv::rparen Hv::asterisk Hv::plus Hv::comma Hv::minus
+Hv::period Hv::slash Hv::zero Hv::one Hv::two Hv::three Hv::four Hv::five
+Hv::six Hv::seven Hv::eight Hv::nine Hv::colon Hv::semi
+Hv::less Hv::equal Hv::more Hv::question Hv::at Hv::A Hv::B Hv::C Hv::D
+Hv::E Hv::F Hv::G Hv::H Hv::I Hv::J Hv::K Hv::L Hv::M Hv::N Hv::O Hv::P
+Hv::Q Hv::R Hv::S Hv::T Hv::U Hv::V Hv::W Hv::X Hv::Y Hv::Z Hv::lbracket
+Hv::backslash Hv::rbracket Hv::caret Hv::underscore Hv::apostrophe Hv::a
+Hv::b Hv::c Hv::d Hv::e Hv::f Hv::g Hv::h Hv::i Hv::j Hv::k Hv::l Hv::m
+Hv::n Hv::o Hv::p Hv::q Hv::r Hv::s Hv::t Hv::u Hv::v Hv::w Hv::x
+Hv::y Hv::z Hv::lbrace Hv::vbar Hv::rbrace Hv::tilde
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::upexclam Hv::cent
+Hv::lb Hv::aslash Hv::yen Hv::itf Hv::sy1 Hv::sy2 Hv::apos2 Hv::lqt Hv::lgqt
+Hv::lsang Hv::rsang Hv::fi Hv::fl Hv::nullchar Hv::dash Hv::dag Hv::ddag Hv::dot
+Hv::nullchar Hv::para Hv::bullet Hv::comma2 Hv::rqt2 Hv::rqt Hv::rgqt Hv::dots
+Hv::perzer Hv::nullchar Hv::uqest Hv::nullchar Hv::grave Hv::acute Hv::hat Hv::tilchar
+Hv::bar Hv::uu Hv::dot Hv::umlaut Hv::nullchar Hv::circ Hv::cedilla Hv::nullchar
+Hv::uml2 Hv::ced2 Hv::vee Hv::emdash Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::AE Hv::nullchar Hv::ordfem Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::Lslash Hv::Oslash Hv::OE Hv::ordmasc Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::ae Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::onesup Hv::nullchar Hv::nullchar Hv::lslash
+Hv::osl Hv::oe Hv::sset Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+
+derived: Helvetica-Bold bold normal PostScript
+derived: Helvetica-Oblique normal italic PostScript
+derived: Helvetica-BoldOblique bold italic PostScript
diff --git a/lib/fonts/helveticaiso.xfe b/lib/fonts/helveticaiso.xfe
new file mode 100644
index 0000000..45ae4c7
--- /dev/null
+++ b/lib/fonts/helveticaiso.xfe
@@ -0,0 +1,47 @@
+% XCircuit Font encoding (XFE) file
+name: HelveticaISO
+% file: helvetica.lps
+family: Helvetica
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin1
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar
+Hv::space Hv::exclam Hv::quote Hv::pound Hv::dollar Hv::percent Hv::ampersand
+Hv::apostrophe Hv::lparen Hv::rparen Hv::asterisk Hv::plus Hv::comma Hv::minus
+Hv::period Hv::slash Hv::zero Hv::one Hv::two Hv::three Hv::four Hv::five
+Hv::six Hv::seven Hv::eight Hv::nine Hv::colon Hv::semi Hv::less Hv::equal
+Hv::more Hv::question Hv::at Hv::A Hv::B Hv::C Hv::D Hv::E Hv::F Hv::G Hv::H
+Hv::I Hv::J Hv::K Hv::L Hv::M Hv::N Hv::O Hv::P Hv::Q Hv::R Hv::S Hv::T Hv::U
+Hv::V Hv::W Hv::X Hv::Y Hv::Z Hv::lbracket Hv::backslash Hv::rbracket
+Hv::caret Hv::underscore Hv::apostrophe Hv::a Hv::b Hv::c Hv::d Hv::e
+Hv::f Hv::g Hv::h Hv::i Hv::j Hv::k Hv::l Hv::m Hv::n Hv::o Hv::p Hv::q
+Hv::r Hv::s Hv::t Hv::u Hv::v Hv::w Hv::x
+Hv::y Hv::z Hv::lbrace Hv::vbar Hv::rbrace Hv::tilde
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::onesmall Hv::grave Hv::acute Hv::hat Hv::tilde Hv::bar Hv::uu
+Hv::dot Hv::umlaut Hv::nullchar Hv::circ Hv::cedilla Hv::nullchar Hv::uml2
+Hv::ced2 Hv::vee Hv::space
+Hv::upexclam Hv::cent Hv::lb Hv::sy2 Hv::yen Hv::vbar Hv::sy1 Hv::umlaut Hv::copy
+Hv::ordfem Hv::lgqt Hv::lognot Hv::dash Hv::regis Hv::bar Hv::circ Hv::pm Hv::twosup
+Hv::threesup Hv::acute Hv::mu Hv::para Hv::dot Hv::cedilla Hv::onesup Hv::ordmasc
+Hv::rgqt Hv::quarter Hv::half Hv::threeq Hv::uqest
+Hv::Agrave Hv::Aacute Hv::Acircum Hv::Atilde Hv::Adier Hv::Aring Hv::AE Hv::Ccedil
+Hv::Egrave Hv::Eacute Hv::Ecircum Hv::Edier Hv::Igrave Hv::Iacute Hv::Icircum Hv::Idier
+Hv::Eth Hv::Ntilde Hv::Ograve Hv::Oacute Hv::Ocircum Hv::Otilde Hv::Odier Hv::times
+Hv::Oslash Hv::Ugrave Hv::Uacute Hv::Ucircum Hv::Udier Hv::Yacute Hv::Thorn Hv::sset
+Hv::agrave Hv::aacute Hv::acircum Hv::atilde Hv::adier Hv::aring Hv::ae Hv::ccedil
+Hv::egrave Hv::eacute Hv::ecircum Hv::edier Hv::igrave Hv::iacute Hv::icircum Hv::idier
+Hv::eth Hv::ntilde Hv::ograve Hv::oacute Hv::ocircum Hv::otilde Hv::odier Hv::divide
+Hv::osl Hv::ugrave Hv::uacute Hv::ucircum Hv::udier Hv::yacute Hv::thorn Hv::ydier
+
+derived: Helvetica-BoldISO bold normal PostScript
+derived: Helvetica-ObliqueISO normal italic PostScript
+derived: Helvetica-BoldObliqueISO bold italic PostScript
diff --git a/lib/fonts/helveticaiso2.lps b/lib/fonts/helveticaiso2.lps
new file mode 100644
index 0000000..1fa5f93
--- /dev/null
+++ b/lib/fonts/helveticaiso2.lps
@@ -0,0 +1,414 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Hv
+% Version: 2.0
+%
+
+% XCircuitLib font library
+/Hv::Aogonek {
+% 4 -5 24 31 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 16 0 Hv::ced2
+endgate
+} def
+
+/Hv::Lcaron {
+% 4 0 20 27 bbox
+begingate
+1.00 0 12 0 Hv::apostrophe
+1.00 0 0 0 Hv::L
+endgate
+} def
+
+/Hv::Scedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 Hv::S
+1.00 0 4 0 Hv::cedilla
+endgate
+} def
+
+/Hv::Sacute {
+% 4 0 22 36 bbox
+begingate
+1.00 0 0 0 Hv::S
+1.00 0 4 4 Hv::acute
+endgate
+} def
+
+/Hv::Scaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 Hv::S
+1.00 0 4 2 Hv::vee
+endgate
+} def
+
+/Hv::Zacute {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 Hv::Z
+1.00 0 2 2 Hv::acute
+endgate
+} def
+
+/Hv::Zcaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 4 2 Hv::vee
+1.00 0 0 0 Hv::Z
+endgate
+} def
+
+/Hv::Zdot {
+% 4 0 22 35 bbox
+begingate
+1.00 0 0 0 Hv::Z
+1.00 0 8 32 Hv::period
+endgate
+} def
+
+/Hv::aogonek {
+% 4 -5 19 21 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 13 0 Hv::ced2
+endgate
+} def
+
+/Hv::lcaron {
+% 3 0 7 27 bbox
+begingate
+1.00 0 0 0 Hv::l
+1.00 0 4 0 Hv::apostrophe
+endgate
+} def
+
+/Hv::sacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::s
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::zacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::z
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::zcaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 -8 Hv::vee
+1.00 0 0 0 Hv::z
+endgate
+} def
+
+/Hv::zdot {
+% 4 0 16 25 bbox
+begingate
+1.00 0 6 22 Hv::period
+1.00 0 0 0 Hv::z
+endgate
+} def
+
+/Hv::tcaron {
+% 4 0 14 27 bbox
+begingate
+1.00 0 0 0 Hv::t
+1.00 0 12 0 Hv::apostrophe
+endgate
+} def
+
+/Hv::scedil {
+% 4 -6 16 22 bbox
+begingate
+1.00 0 2 0 Hv::cedilla
+1.00 0 0 0 Hv::s
+endgate
+} def
+
+/Hv::Rcaron {
+% 4 0 23 34 bbox
+begingate
+1.00 0 0 0 Hv::R
+1.00 0 2 2 Hv::vee
+endgate
+} def
+
+/Hv::Racute {
+% 4 0 23 36 bbox
+begingate
+1.00 0 0 0 Hv::R
+1.00 0 0 4 Hv::acute
+endgate
+} def
+
+/Hv::Abreve {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 Hv::A
+1.00 0 4 0 Hv::uu
+endgate
+} def
+
+/Hv::Lacute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 Hv::L
+1.00 0 -4 4 Hv::acute
+endgate
+} def
+
+/Hv::Cacute {
+% 4 0 24 36 bbox
+begingate
+1.00 0 0 0 Hv::C
+1.00 0 8 4 Hv::acute
+endgate
+} def
+
+/Hv::Ccaron {
+% 4 0 24 34 bbox
+begingate
+1.00 0 0 0 Hv::C
+1.00 0 4 2 Hv::vee
+endgate
+} def
+
+/Hv::Eogonek {
+% 4 -5 22 31 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 14 0 Hv::ced2
+endgate
+} def
+
+/Hv::Ecaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 Hv::E
+1.00 0 4 2 Hv::vee
+endgate
+} def
+
+/Hv::Dcaron {
+% 4 0 24 34 bbox
+begingate
+1.00 0 0 0 Hv::D
+1.00 0 2 2 Hv::vee
+endgate
+} def
+
+/Hv::Ncaron {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 Hv::N
+1.00 0 4 0 Hv::vee
+endgate
+} def
+
+/Hv::Nacute {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 Hv::N
+1.00 0 4 0 Hv::acute
+endgate
+} def
+
+/Hv::Ouml2 {
+% 4 0 26 34 bbox
+begingate
+1.00 0 0 0 Hv::O
+1.00 0 8 2 Hv::uml2
+endgate
+} def
+
+/Hv::Ucirc {
+% 4 0 25 38 bbox
+begingate
+1.00 0 0 0 Hv::U
+1.00 0 4 4 Hv::circ
+endgate
+} def
+
+/Hv::Uuml2 {
+% 4 0 25 34 bbox
+begingate
+1.00 0 0 0 Hv::U
+1.00 0 6 2 Hv::uml2
+endgate
+} def
+
+/Hv::Tcedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 Hv::T
+1.00 0 4 0 Hv::cedilla
+endgate
+} def
+
+/Hv::racute {
+% 4 0 12 24 bbox
+begingate
+1.00 0 0 0 Hv::r
+1.00 0 0 -8 Hv::acute
+endgate
+} def
+
+/Hv::rcaron {
+% 4 0 12 24 bbox
+begingate
+1.00 0 0 0 Hv::r
+1.00 0 0 -8 Hv::vee
+endgate
+} def
+
+/Hv::abreve {
+% 4 0 18 23 bbox
+begingate
+1.00 0 0 0 Hv::a
+1.00 0 2 -9 Hv::uu
+endgate
+} def
+
+/Hv::lacute {
+% 3 0 7 36 bbox
+begingate
+1.00 0 0 0 Hv::l
+1.00 0 -4 4 Hv::acute
+endgate
+} def
+
+/Hv::cacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::c
+1.00 0 4 -8 Hv::acute
+endgate
+} def
+
+/Hv::ccaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::c
+1.00 0 2 -8 Hv::vee
+endgate
+} def
+
+/Hv::eogonek {
+% 4 -5 18 21 bbox
+begingate
+1.00 0 6 0 Hv::ced2
+1.00 0 0 0 Hv::e
+endgate
+} def
+
+/Hv::ecaron {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 Hv::e
+1.00 0 2 -8 Hv::vee
+endgate
+} def
+
+/Hv::dcaron {
+% 4 0 22 27 bbox
+begingate
+1.00 0 0 0 Hv::d
+1.00 0 20 0 Hv::apostrophe
+endgate
+} def
+
+/Hv::dbar {
+% 4 0 18 26 bbox
+begingate
+1.00 0 0 0 Hv::d
+1.00 0 8 -8 Hv::bar
+endgate
+} def
+
+/Hv::ncaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::n
+1.00 0 0 -8 Hv::vee
+endgate
+} def
+
+/Hv::nacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::n
+1.00 0 2 -8 Hv::acute
+endgate
+} def
+
+/Hv::ucirc {
+% 4 0 16 26 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 2 -8 Hv::circ
+endgate
+} def
+
+/Hv::uuml2 {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::u
+1.00 0 4 -8 Hv::uml2
+endgate
+} def
+
+/Hv::tcedil {
+% 4 -6 11 32 bbox
+begingate
+1.00 0 0 0 Hv::t
+1.00 0 4 0 Hv::cedilla
+endgate
+} def
+
+/Hv::togonek {
+% 4 -5 11 31 bbox
+begingate
+1.00 0 0 0 Hv::t
+1.00 0 5 0 Hv::ced2
+endgate
+} def
+
+/Hv::ouml2 {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::o
+1.00 0 4 -8 Hv::uml2
+endgate
+} def
+
+/Hv::scaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 Hv::s
+1.00 0 0 -8 Hv::vee
+endgate
+} def
+
+/Hv::Tcaron {
+% 4 0 22 33 bbox
+begingate
+1.00 0 0 0 Hv::T
+1.00 0 3 1 Hv::vee
+endgate
+} def
+
+/Hv::dotacc {
+% 8 30 3 3 bbox
+begingate
+1.00 0 4 30 Hv::period
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/helveticaiso2.xfe b/lib/fonts/helveticaiso2.xfe
new file mode 100644
index 0000000..e14e47e
--- /dev/null
+++ b/lib/fonts/helveticaiso2.xfe
@@ -0,0 +1,48 @@
+% XCircuit Font encoding (XFE) file
+name: HelveticaISO2
+% file: helvetica.lps
+file: helveticaiso2.lps
+family: Helvetica
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin2
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar
+Hv::space Hv::exclam Hv::quote Hv::pound Hv::dollar Hv::percent Hv::ampersand
+Hv::apostrophe Hv::lparen Hv::rparen Hv::asterisk Hv::plus Hv::comma Hv::minus
+Hv::period Hv::slash Hv::zero Hv::one Hv::two Hv::three Hv::four Hv::five
+Hv::six Hv::seven Hv::eight Hv::nine Hv::colon Hv::semi Hv::less Hv::equal
+Hv::more Hv::question Hv::at Hv::A Hv::B Hv::C Hv::D Hv::E Hv::F Hv::G Hv::H
+Hv::I Hv::J Hv::K Hv::L Hv::M Hv::N Hv::O Hv::P Hv::Q Hv::R Hv::S Hv::T Hv::U
+Hv::V Hv::W Hv::X Hv::Y Hv::Z Hv::lbracket Hv::backslash Hv::rbracket
+Hv::caret Hv::underscore Hv::apostrophe Hv::a Hv::b Hv::c Hv::d Hv::e
+Hv::f Hv::g Hv::h Hv::i Hv::j Hv::k Hv::l Hv::m Hv::n Hv::o Hv::p Hv::q
+Hv::r Hv::s Hv::t Hv::u Hv::v Hv::w Hv::x Hv::y Hv::z Hv::lbrace Hv::vbar
+Hv::rbrace Hv::tilde Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::Aogonek Hv::uu Hv::Lslash Hv::sy2 Hv::Lcaron Hv::Sacute Hv::sy1
+Hv::umlaut Hv::Scaron Hv::Scedil Hv::Tcaron Hv::Zacute Hv::dash Hv::Zcaron
+Hv::Zdot Hv::circ Hv::aogonek Hv::ced2 Hv::lslash Hv::acute Hv::lcaron
+Hv::sacute Hv::vee Hv::cedilla
+Hv::scaron Hv::scedil Hv::tcaron Hv::zacute Hv::uml2 Hv::zcaron Hv::zdot
+Hv::Racute Hv::Aacute Hv::Acircum Hv::Abreve Hv::Adier Hv::Lacute Hv::Cacute Hv::Ccedil
+Hv::Ccaron Hv::Eacute Hv::Eogonek Hv::Edier Hv::Ecaron Hv::Iacute Hv::Icircum Hv::Dcaron
+Hv::Eth Hv::Nacute Hv::Ncaron Hv::Oacute Hv::Ocircum Hv::Ouml2 Hv::Odier Hv::times
+Hv::Rcaron Hv::Ucirc Hv::Uacute Hv::Uuml2 Hv::Udier Hv::Yacute Hv::Tcedil Hv::sset
+Hv::racute Hv::aacute Hv::acircum Hv::abreve Hv::adier Hv::lacute Hv::cacute Hv::ccedil
+Hv::ecaron Hv::eacute Hv::eogonek Hv::edier Hv::ecaron Hv::iacute Hv::icircum Hv::dcaron
+Hv::dbar Hv::nacute Hv::ncaron Hv::oacute Hv::ocircum Hv::ouml2 Hv::odier Hv::divide
+Hv::rcaron Hv::ucirc Hv::uacute Hv::uuml2 Hv::udier Hv::yacute Hv::togonek Hv::dotacc
+
+derived: Helvetica-BoldISO2 bold normal PostScript
+derived: Helvetica-ObliqueISO2 normal italic PostScript
+derived: Helvetica-BoldObliqueISO2 bold italic PostScript
diff --git a/lib/fonts/helveticaiso5.lps b/lib/fonts/helveticaiso5.lps
new file mode 100644
index 0000000..33d3e05
--- /dev/null
+++ b/lib/fonts/helveticaiso5.lps
@@ -0,0 +1,55 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Hv
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/Hv::Guu {
+% 4 0 26 34 bbox
+begingate
+1.00 0 0 0 Hv::G
+1.00 0 4 2 Hv::uu
+endgate
+} def
+
+/Hv::Idot {
+% 4 0 7 37 bbox
+begingate
+1.00 0 0 0 Hv::I
+1.00 0 -4 12 Hv::dot
+endgate
+} def
+
+/Hv::Scedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 Hv::S
+1.00 0 4 0 Hv::cedilla
+endgate
+} def
+
+/Hv::scedil {
+% 4 -6 16 22 bbox
+begingate
+1.00 0 0 0 Hv::s
+1.00 0 4 0 Hv::cedilla
+endgate
+} def
+
+/Hv::guu {
+% 4 -6 16 30 bbox
+begingate
+1.00 0 0 0 Hv::g
+1.00 0 2 -8 Hv::uu
+endgate
+} def
+
+/Hv::dotlessi {
+% 6 0 4 16 bbox
+begingate
+1 1.00 6 0 6 16 2 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/helveticaiso5.xfe b/lib/fonts/helveticaiso5.xfe
new file mode 100644
index 0000000..a779423
--- /dev/null
+++ b/lib/fonts/helveticaiso5.xfe
@@ -0,0 +1,48 @@
+% XCircuit Font encoding (XFE) file
+name: HelveticaISO5
+% file: helvetica.lps
+file: helveticaiso5.lps
+family: Helvetica
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin5
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar
+Hv::space Hv::exclam Hv::quote Hv::pound Hv::dollar Hv::percent Hv::ampersand
+Hv::apostrophe Hv::lparen Hv::rparen Hv::asterisk Hv::plus Hv::comma Hv::minus
+Hv::period Hv::slash Hv::zero Hv::one Hv::two Hv::three Hv::four Hv::five
+Hv::six Hv::seven Hv::eight Hv::nine Hv::colon Hv::semi Hv::less Hv::equal
+Hv::more Hv::question Hv::at Hv::A Hv::B Hv::C Hv::D Hv::E Hv::F Hv::G Hv::H
+Hv::I Hv::J Hv::K Hv::L Hv::M Hv::N Hv::O Hv::P Hv::Q Hv::R Hv::S Hv::T Hv::U
+Hv::V Hv::W Hv::X Hv::Y Hv::Z Hv::lbracket
+Hv::backslash Hv::rbracket Hv::caret Hv::underscore Hv::apostrophe Hv::a Hv::b
+Hv::c Hv::d Hv::e Hv::f Hv::g Hv::h Hv::i Hv::j Hv::k Hv::l Hv::m Hv::n Hv::o
+Hv::p Hv::q Hv::r Hv::s Hv::t Hv::u Hv::v Hv::w Hv::x
+Hv::y Hv::z Hv::lbrace Hv::vbar Hv::rbrace Hv::tilde
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar
+Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::nullchar Hv::onesmall
+Hv::grave Hv::acute
+Hv::hat Hv::tilde Hv::bar Hv::uu Hv::dot Hv::umlaut Hv::nullchar Hv::circ
+Hv::cedilla Hv::nullchar Hv::uml2 Hv::ced2 Hv::vee Hv::space
+Hv::upexclam Hv::cent Hv::lb Hv::sy2 Hv::yen Hv::vbar Hv::sy1 Hv::umlaut Hv::copy
+Hv::ordfem Hv::lgqt Hv::lognot Hv::dash Hv::regis Hv::bar Hv::circ Hv::pm Hv::twosup
+Hv::threesup Hv::acute Hv::mu Hv::para Hv::dot Hv::cedilla Hv::onesup Hv::ordmasc
+Hv::rgqt Hv::quarter Hv::half Hv::threeq Hv::uqest
+Hv::Agrave Hv::Aacute Hv::Acircum Hv::Atilde Hv::Adier Hv::Aring Hv::AE Hv::Ccedil
+Hv::Egrave Hv::Eacute Hv::Ecircum Hv::Edier Hv::Igrave Hv::Iacute Hv::Icircum Hv::Idier
+Hv::Guu Hv::Ntilde Hv::Ograve Hv::Oacute Hv::Ocircum Hv::Otilde Hv::Odier Hv::times
+Hv::Oslash Hv::Ugrave Hv::Uacute Hv::Ucircum Hv::Udier Hv::Idot Hv::Scedil Hv::sset
+Hv::agrave Hv::aacute Hv::acircum Hv::atilde Hv::adier Hv::aring Hv::ae Hv::ccedil
+Hv::egrave Hv::eacute Hv::ecircum Hv::edier Hv::igrave Hv::iacute Hv::icircum Hv::idier
+Hv::guu Hv::ntilde Hv::ograve Hv::oacute Hv::ocircum Hv::otilde Hv::odier Hv::divide
+Hv::osl Hv::ugrave Hv::uacute Hv::ucircum Hv::udier Hv::dotlessi Hv::scedil Hv::ydier
+
+derived: Helvetica-BoldISO5 bold normal PostScript
+derived: Helvetica-ObliqueISO5 normal italic PostScript
+derived: Helvetica-BoldObliqueISO5 bold italic PostScript
diff --git a/lib/fonts/letters.ps b/lib/fonts/letters.ps
new file mode 100644
index 0000000..a2cb594
--- /dev/null
+++ b/lib/fonts/letters.ps
@@ -0,0 +1,790 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: examples/letters
+%%Creator: Xcircuit v2.0
+%%CreationDate: Tue Nov 17 21:28:11 1998
+%%Pages: 1
+%%BoundingBox: 68 68 826 1150
+%%DocumentNeededResources:
+%%EndComments
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 2.0
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--8/8/97 (tim@bach.ece.jhu.edu)
+% The Johns Hopkins University
+%
+%%BeginResource: procset XCIRCproc 2.0 2
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def
+ findfont fscale scalefont setfont } def
+/Ss { gsave 0.67 dup scale gsave mty neg rmoveto
+ glevel 1 add /glevel exch def } def
+/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto
+ glevel 1 add /glevel exch def } def
+/ns { currentpoint transform % preserve x position!
+ glevel {grestore} repeat /glevel 0 def
+ itransform pop currentpoint pop sub 0 rmoveto } def
+/ul { showflag 1 eq { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { showflag 1 eq { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave true charpath flattenpath pathbbox pop exch pop sub
+ grestore } def
+/bs { stW 0 rmoveto } def
+/pspc 0 def
+/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def
+/hS { qS qS } def
+/textx { dup 2 mul 1 add copy 0 exch
+ { exch exec exch stringwidth pop add } repeat neg ns } def
+/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch
+ pop exch sub exch pop neg grestore } def
+/texty { gsave 2 copy pop exec mty } def
+/tcenter { textx grestore 0.5 mul 0 rmoveto } def
+/tright { textx grestore fspc sub 0 rmoveto } def
+/tmiddle { texty 0.5 mul rmoveto } def
+/ttop { texty fspc sub rmoveto } def
+/tshow { { exec show } repeat ns } def
+
+/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt
+ {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore
+ 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore
+ dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse
+ {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt
+ {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if
+ /glevel 0 def /showflag 0 def /fspc pspc def
+ just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse}
+ {fspc 0 rmoveto} ifelse
+ just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse}
+ {0 fspc rmoveto} ifelse
+/showflag 1 def tshow grestore } def
+/pinlabel { /pspc 20 def label /pspc 0 def } def
+/pinglobal { pinlabel } def
+
+/begingate { gsave translate 0 0 moveto dup 0 lt {neg 1 sub -1 1 scale} if
+ rotate dup scale /pinlabel { pop pop pop pop 2 mul {pop} repeat}
+ def } bind def
+/beginparm { -1 1 {1 add -1 roll def} for begingate } bind def
+/endgate { grestore /pinlabel { /pspc 20 def
+ label /pspc 0 def } def } bind def
+
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def
+ style 1 and 0 gt not {closepath} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if
+ style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt
+ {gar exch get ppaint} { pop eofill } ifelse grestore } if
+ style 8 and 0 gt { newpath } { stroke } ifelse grestore } def
+/scb { gsave setrgbcolor } bind def /sce { grestore } bind def
+
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
+% XCircuit output starts here.
+
+/myA {
+% 0 0 256 320 bbox
+begingate
+240 1.00 0 0 112 320 144 320 32 0 4 polygon
+240 1.00 256 0 144 320 112 320 224 0 4 polygon
+240 1.00 48 80 48 112 208 112 208 80 4 polygon
+endgate
+} def
+
+/myB {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+80 160 beginpath
+80 240 80 270.00 450.00 arc
+80 288 1 polyc
+80 240 48 450.00 270.00 arcn
+80 160 1 polyc
+241 1.00 endpath
+96 0 beginpath
+96 96 96 270.00 450.00 arc
+96 160 1 polyc
+96 96 65 450.00 270.00 arcn
+96 0 1 polyc
+241 1.00 endpath
+240 1.00 32 160 32 192 96 192 96 160 4 polygon
+240 1.00 32 288 32 320 80 320 80 288 4 polygon
+240 1.00 32 0 32 32 96 32 96 0 4 polygon
+endgate
+} def
+
+/myC {
+% 0 0 259 320 bbox
+begingate
+241 61 beginpath
+160 160 128 309.81 50.19 arcn
+259 284 1 polyc
+160 160 160 51.34 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/myD {
+% 0 0 256 320 bbox
+begingate
+96 0 beginpath
+96 160 160 270.00 450.00 arc
+96 288 1 polyc
+96 160 128 450.00 270.00 arcn
+96 0 1 polyc
+241 1.00 endpath
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 32 288 32 320 96 320 96 288 4 polygon
+240 1.00 32 0 32 32 96 32 96 0 4 polygon
+endgate
+} def
+
+/myE {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 32 288 32 320 192 320 192 288 4 polygon
+240 1.00 32 0 32 32 192 32 192 0 4 polygon
+240 1.00 32 144 32 176 160 176 160 144 4 polygon
+endgate
+} def
+
+/myF {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 32 288 32 320 192 320 192 288 4 polygon
+240 1.00 32 144 32 176 160 176 160 144 4 polygon
+endgate
+} def
+
+/myG {
+% 0 0 274 320 bbox
+begingate
+240 1.00 162 144 162 176 274 176 274 144 4 polygon
+240 1.00 240 48 240 144 274 144 274 48 4 polygon
+241 61 beginpath
+160 160 128 309.81 50.19 arcn
+259 284 1 polyc
+160 160 160 51.34 315.00 arc
+240 1.00 endpath
+endgate
+} def
+
+/myH {
+% 0 0 224 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 192 0 192 320 224 320 224 0 4 polygon
+240 1.00 32 144 32 176 192 176 192 144 4 polygon
+endgate
+} def
+
+/myI {
+% 0 0 32 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+endgate
+} def
+
+/myJ {
+% -4 0 132 320 bbox
+begingate
+240 1.00 96 80 96 320 128 320 128 80 4 polygon
+128 80 beginpath
+48 80 80 360.00 229.40 arcn
+14 47 1 polyc
+48 80 48 225.00 360.00 arc
+240 1.00 endpath
+endgate
+} def
+
+/myK {
+% 0 0 224 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 8 176 160 320 200 320 48 176 4 polygon
+240 1.00 184 0 8 176 48 176 224 0 4 polygon
+endgate
+} def
+
+/myL {
+% 0 0 160 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 32 0 32 32 160 32 160 0 4 polygon
+endgate
+} def
+
+/myM {
+% 0 0 320 320 bbox
+begingate
+240 1.00 144 0 288 320 320 320 176 0 4 polygon
+240 1.00 176 0 32 320 0 320 144 0 4 polygon
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 288 0 288 320 320 320 320 0 4 polygon
+endgate
+} def
+
+/myN {
+% 0 0 224 320 bbox
+begingate
+240 1.00 224 0 32 320 0 320 192 0 4 polygon
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 192 0 192 320 224 320 224 0 4 polygon
+endgate
+} def
+
+/myO {
+% 0 0 320 320 bbox
+begingate
+288 160 beginpath
+160 160 128 0.00 360.00 arc
+320 160 1 polyc
+160 160 160 0.00 360.00 arc
+241 1.00 endpath
+endgate
+} def
+
+/myP {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+96 128 beginpath
+96 224 96 270.00 450.00 arc
+96 288 1 polyc
+96 224 65 450.00 270.00 arcn
+96 128 1 polyc
+241 1.00 endpath
+240 1.00 32 128 32 160 96 160 96 128 4 polygon
+240 1.00 32 288 32 320 96 320 96 288 4 polygon
+endgate
+} def
+
+/myQ {
+% 0 0 320 320 bbox
+begingate
+288 160 beginpath
+160 160 128 0.00 360.00 arc
+320 160 1 polyc
+160 160 160 0.00 360.00 arc
+241 1.00 endpath
+240 1.00 280 0 184 96 224 96 320 0 4 polygon
+endgate
+} def
+
+/myR {
+% 0 0 208 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+96 128 beginpath
+96 224 96 270.00 450.00 arc
+96 288 1 polyc
+96 224 65 450.00 270.00 arcn
+96 128 1 polyc
+241 1.00 endpath
+240 1.00 32 128 32 160 96 160 96 128 4 polygon
+240 1.00 32 288 32 320 96 320 96 288 4 polygon
+240 1.00 168 0 80 144 120 144 208 0 4 polygon
+endgate
+} def
+
+/myS {
+% -1 -1 169 320 bbox
+begingate
+13 29 beginpath
+80 87 88 -139.33 65.80 arc
+55 197 1 polyc
+80 239 49 239.81 36.45 arcn
+142 290 1 polyc
+80 239 80 40.16 240.45 arc
+102 139 1 polyc
+80 87 56 66.80 -138.37 arcn
+22 66 1 polyc
+-1 44 1 polyc
+15 28 1 polyc
+241 1.00 endpath
+endgate
+} def
+
+/myT {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 288 0 320 192 320 192 288 4 polygon
+240 1.00 80 0 80 320 112 320 112 0 4 polygon
+endgate
+} def
+
+/myU {
+% 0 0 256 320 bbox
+begingate
+240 1.00 0 128 0 320 32 320 32 128 4 polygon
+240 1.00 224 128 224 320 256 320 256 128 4 polygon
+32 127 beginpath
+128 128 96 180.00 360.00 arc
+256 128 1 polyc
+128 128 128 360.00 180.00 arcn
+240 1.00 endpath
+endgate
+} def
+
+/myV {
+% 0 0 256 320 bbox
+begingate
+240 1.00 112 0 224 320 256 320 144 0 4 polygon
+240 1.00 144 0 32 320 0 320 112 0 4 polygon
+endgate
+} def
+
+/myW {
+% 0 0 352 320 bbox
+begingate
+240 1.00 80 0 160 320 192 320 112 0 4 polygon
+240 1.00 112 0 32 320 0 320 80 0 4 polygon
+240 1.00 240 0 320 320 352 320 272 0 4 polygon
+240 1.00 272 0 192 320 160 320 240 0 4 polygon
+endgate
+} def
+
+/myX {
+% 0 0 232 320 bbox
+begingate
+240 1.00 0 0 192 320 232 320 40 0 4 polygon
+240 1.00 192 0 0 320 40 320 232 0 4 polygon
+endgate
+} def
+
+/myY {
+% 0 0 256 320 bbox
+begingate
+240 1.00 112 0 112 176 144 176 144 0 4 polygon
+240 1.00 128 136 0 320 40 320 128 192 4 polygon
+240 1.00 128 136 256 320 216 320 128 192 4 polygon
+endgate
+} def
+
+/myZ {
+% 0 0 192 320 bbox
+begingate
+240 1.00 0 288 0 320 192 320 192 288 4 polygon
+240 1.00 0 0 0 32 192 32 192 0 4 polygon
+240 1.00 0 32 152 288 192 288 40 32 4 polygon
+endgate
+} def
+
+/mya {
+% 0 0 176 192 bbox
+begingate
+240 1.00 144 0 144 192 176 192 176 0 4 polygon
+153 67 beginpath
+96 96 64 333.43 26.57 arcn
+164 164 1 polyc
+96 96 96 45.00 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/myb {
+% 0 0 176 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+22 67 beginpath
+80 96 64 -153.43 153.43 arc
+12 164 1 polyc
+80 96 96 135.00 -128.66 arcn
+240 1.00 endpath
+endgate
+} def
+
+/myc {
+% 0 0 156 192 bbox
+begingate
+136 46 beginpath
+96 96 64 309.81 50.19 arcn
+156 171 1 polyc
+96 96 96 51.34 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/myd {
+% 0 0 176 320 bbox
+begingate
+240 1.00 144 0 144 320 176 320 176 0 4 polygon
+153 67 beginpath
+96 96 64 333.43 26.57 arcn
+164 164 1 polyc
+96 96 96 45.00 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/mye {
+% 0 0 192 192 bbox
+begingate
+240 1.00 16 80 16 112 160 112 192 96 192 80 5 polygon
+147 57 beginpath
+96 96 64 323.13 0.00 arcn
+192 96 1 polyc
+96 96 96 0.00 324.46 arc
+240 1.00 endpath
+endgate
+} def
+
+/myf {
+% 0 0 164 320 bbox
+begingate
+240 1.00 80 256 80 0 48 0 48 256 4 polygon
+240 1.00 0 176 0 208 128 208 128 176 4 polygon
+138 273 beginpath
+112 256 32 33.69 180.00 arc
+48 256 1 polyc
+112 256 64 180.00 35.54 arcn
+240 1.00 endpath
+endgate
+} def
+
+/myg {
+% 0 -112 176 304 bbox
+begingate
+153 67 beginpath
+96 96 64 333.43 26.57 arcn
+164 164 1 polyc
+96 96 96 45.00 308.66 arc
+240 1.00 endpath
+240 1.00 144 -16 144 192 176 192 176 -16 4 polygon
+36 -63 beginpath
+80 -16 64 227.73 360.00 arc
+176 -16 1 polyc
+80 -16 96 360.00 225.00 arcn
+240 1.00 endpath
+endgate
+} def
+
+/myh {
+% 0 0 160 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 128 0 128 112 160 112 160 0 4 polygon
+3 133 beginpath
+80 112 80 164.05 0.00 arcn
+128 112 1 polyc
+80 112 48 0.00 165.96 arc
+240 1.00 endpath
+endgate
+} def
+
+/myi {
+% 0 0 32 256 bbox
+begingate
+240 1.00 0 0 0 192 32 192 32 0 4 polygon
+240 1.00 16 240 16 0.00 360.00 xcarc
+endgate
+} def
+
+/myj {
+% -84 -112 116 368 bbox
+begingate
+240 1.00 0 -48 0 192 32 192 32 -48 4 polygon
+-58 -65 beginpath
+-32 -48 32 213.69 360.00 arc
+32 -48 1 polyc
+-32 -48 64 360.00 215.54 arcn
+240 1.00 endpath
+240 1.00 16 240 16 0.00 360.00 xcarc
+endgate
+} def
+
+/myk {
+% 0 0 160 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+240 1.00 16 96 104 192 144 192 56 96 4 polygon
+240 1.00 160 0 48 112 8 112 120 0 4 polygon
+endgate
+} def
+
+/myl {
+% 0 0 32 320 bbox
+begingate
+240 1.00 0 0 0 320 32 320 32 0 4 polygon
+endgate
+} def
+
+/mym {
+% 0 0 288 192 bbox
+begingate
+240 1.00 256 0 256 112 288 112 288 0 4 polygon
+240 1.00 128 0 128 112 160 112 160 0 4 polygon
+240 1.00 0 0 0 192 32 192 32 0 4 polygon
+3 133 beginpath
+80 112 80 164.05 0.00 arcn
+128 112 1 polyc
+80 112 48 0.00 165.96 arc
+240 1.00 endpath
+131 133 beginpath
+208 112 80 164.05 0.00 arcn
+256 112 1 polyc
+208 112 48 0.00 165.96 arc
+240 1.00 endpath
+endgate
+} def
+
+/myn {
+% 0 0 160 192 bbox
+begingate
+240 1.00 0 0 0 192 32 192 32 0 4 polygon
+3 133 beginpath
+80 112 80 164.05 0.00 arcn
+128 112 1 polyc
+80 112 48 0.00 165.96 arc
+240 1.00 endpath
+240 1.00 128 0 128 112 160 112 160 0 4 polygon
+endgate
+} def
+
+/myo {
+% 0 0 192 192 bbox
+begingate
+192 96 beginpath
+96 96 96 0.00 360.00 arc
+160 96 1 polyc
+96 96 64 0.00 360.00 arc
+241 1.00 endpath
+endgate
+} def
+
+/myp {
+% 0 -112 176 304 bbox
+begingate
+22 67 beginpath
+80 96 64 -153.43 153.43 arc
+12 164 1 polyc
+80 96 96 135.00 -128.66 arcn
+240 1.00 endpath
+240 1.00 0 -112 0 192 32 192 32 -112 4 polygon
+endgate
+} def
+
+/myq {
+% 0 -112 176 304 bbox
+begingate
+153 67 beginpath
+96 96 64 333.43 26.57 arcn
+164 164 1 polyc
+96 96 96 45.00 308.66 arc
+240 1.00 endpath
+240 1.00 144 -112 144 192 176 192 176 -112 4 polygon
+endgate
+} def
+
+/myr {
+% 0 0 136 192 bbox
+begingate
+136 168 beginpath
+80 112 80 45.00 180.00 arc
+32 112 1 polyc
+80 112 48 180.00 26.57 arcn
+240 1.00 endpath
+240 1.00 0 0 0 192 32 192 32 0 4 polygon
+endgate
+} def
+
+/mys {
+% 0 -1 113 193 bbox
+begingate
+106 161 beginpath
+56 136 56 26.57 253.30 arc
+62 79 1 polyc
+56 56 24 433.30 198.43 arcn
+4 34 1 polyc
+56 56 57 -155.56 73.30 arc
+49 114 1 polyc
+56 136 24 253.30 18.43 arcn
+240 1.00 endpath
+endgate
+} def
+
+/myt {
+% 0 0 164 320 bbox
+begingate
+240 1.00 80 64 80 320 48 320 48 64 4 polygon
+240 1.00 0 240 0 208 128 208 128 240 4 polygon
+138 46 beginpath
+112 64 32 326.31 180.00 arcn
+48 64 1 polyc
+112 64 64 180.00 324.46 arc
+240 1.00 endpath
+endgate
+} def
+
+/myu {
+% 0 0 160 192 bbox
+begingate
+240 1.00 160 192 160 0 128 0 128 192 4 polygon
+156 58 beginpath
+80 80 80 344.05 180.00 arcn
+32 80 1 polyc
+80 80 48 180.00 345.96 arc
+240 1.00 endpath
+240 1.00 32 192 32 80 0 80 0 192 4 polygon
+endgate
+} def
+
+/myv {
+% 0 0 192 192 bbox
+begingate
+240 1.00 32 192 112 0 80 0 0 192 4 polygon
+240 1.00 160 192 80 0 112 0 192 192 4 polygon
+endgate
+} def
+
+/myw {
+% 0 0 288 192 bbox
+begingate
+240 1.00 32 192 96 0 64 0 0 192 4 polygon
+240 1.00 128 192 64 0 96 0 160 192 4 polygon
+240 1.00 160 192 224 0 192 0 128 192 4 polygon
+240 1.00 256 192 192 0 224 0 288 192 4 polygon
+endgate
+} def
+
+/myx {
+% 0 0 200 192 bbox
+begingate
+240 1.00 200 0 40 192 0 192 160 0 4 polygon
+240 1.00 0 0 160 192 200 192 40 0 4 polygon
+endgate
+} def
+
+/myy {
+% 0 -112 192 304 bbox
+begingate
+240 1.00 32 192 112 0 80 0 0 192 4 polygon
+240 1.00 160 192 32 -112 64 -112 192 192 4 polygon
+endgate
+} def
+
+/myz {
+% 0 0 160 192 bbox
+begingate
+240 1.00 0 32 120 160 160 160 40 32 4 polygon
+240 1.00 0 192 0 160 160 160 160 192 4 polygon
+240 1.00 0 32 0 0 160 0 160 32 4 polygon
+endgate
+} def
+
+%%Page: 1 1
+%%PageOrientation: Portrait
+/pgsave save def bop
+% 768 2544 offsets
+1.0000 inchscale
+2.6000 setlinewidth
+
+1.00 0 192 2736 myA
+1.00 0 512 2736 myB
+1.00 0 768 2736 myC
+1.00 0 1088 2736 myD
+1.00 0 1408 2736 myE
+1.00 0 1664 2736 myF
+1.00 0 1920 2736 myG
+1.00 0 192 2352 myH
+1.00 0 512 2352 myI
+1.00 0 576 2352 myJ
+1.00 0 768 2352 myK
+1.00 0 1024 2352 myL
+1.00 0 1216 2352 myM
+1.00 0 1600 2352 myN
+1.00 0 1856 2352 myO
+1.00 0 192 1968 myP
+1.00 0 448 1968 myQ
+1.00 0 832 1968 myR
+1.00 0 1088 1968 myS
+1.00 0 1280 1968 myT
+1.00 0 1536 1968 myU
+1.00 0 1856 1968 myV
+1.00 0 192 1520 myW
+1.00 0 576 1520 myX
+1.00 0 832 1520 myY
+1.00 0 1152 1520 myZ
+1.00 0 1408 1520 mya
+1.00 0 1632 1520 myb
+1.00 0 1856 1520 myc
+1.00 0 192 1072 myd
+1.00 0 416 1072 mye
+1.00 0 608 1072 myf
+1.00 0 736 1072 myg
+1.00 0 960 1072 myh
+1.00 0 1184 1072 myi
+1.00 0 1312 1072 myj
+1.00 0 1408 1072 myk
+1.00 0 1600 1072 myl
+1.00 0 1728 1072 mym
+1.00 0 192 688 myn
+1.00 0 384 688 myo
+1.00 0 640 688 myp
+1.00 0 864 688 myq
+1.00 0 1088 688 myr
+1.00 0 1280 688 mys
+1.00 0 1408 688 myt
+1.00 0 1600 688 myu
+1.00 0 1824 688 myv
+1.00 0 192 304 myw
+1.00 0 512 304 myx
+1.00 0 768 304 myy
+1.00 0 1024 304 myz
+pgsave restore showpage
+
+%%Trailer
+XCIRCsave restore
+%%EOF
diff --git a/lib/fonts/myfont.lps b/lib/fonts/myfont.lps
new file mode 100644
index 0000000..3037de5
--- /dev/null
+++ b/lib/fonts/myfont.lps
@@ -0,0 +1,614 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: my
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/my::nullchar {
+% 0 0 256 320 bbox
+begingate
+0 1.00 0 0 0 320 256 320 256 0 4 polygon
+endgate
+} def
+
+/my::space {
+% 0 0 256 320 bbox
+begingate
+endgate
+} def
+
+/my::A {
+% 32 0 256 320 bbox
+begingate
+240 1.00 32 0 144 320 176 320 64 0 4 polygon
+240 1.00 288 0 176 320 144 320 256 0 4 polygon
+240 1.00 80 80 80 112 240 112 240 80 4 polygon
+endgate
+} def
+
+/my::B {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+112 160 beginpath
+112 240 80 270.00 450.00 arc
+112 288 1 polyc
+112 240 48 450.00 270.00 arcn
+112 160 1 polyc
+241 1.00 endpath
+128 0 beginpath
+128 96 96 270.00 450.00 arc
+128 160 1 polyc
+128 96 65 450.00 270.00 arcn
+128 0 1 polyc
+241 1.00 endpath
+240 1.00 64 160 64 192 128 192 128 160 4 polygon
+240 1.00 64 288 64 320 112 320 112 288 4 polygon
+240 1.00 64 0 64 32 128 32 128 0 4 polygon
+endgate
+} def
+
+/my::C {
+% 32 0 259 320 bbox
+begingate
+273 61 beginpath
+192 160 128 309.81 50.19 arcn
+291 284 1 polyc
+192 160 160 51.34 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::D {
+% 32 0 256 320 bbox
+begingate
+128 0 beginpath
+128 160 160 270.00 450.00 arc
+128 288 1 polyc
+128 160 128 450.00 270.00 arcn
+128 0 1 polyc
+241 1.00 endpath
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 64 288 64 320 128 320 128 288 4 polygon
+240 1.00 64 0 64 32 128 32 128 0 4 polygon
+endgate
+} def
+
+/my::E {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 64 288 64 320 224 320 224 288 4 polygon
+240 1.00 64 0 64 32 224 32 224 0 4 polygon
+240 1.00 64 144 64 176 192 176 192 144 4 polygon
+endgate
+} def
+
+/my::F {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 64 288 64 320 224 320 224 288 4 polygon
+240 1.00 64 144 64 176 192 176 192 144 4 polygon
+endgate
+} def
+
+/my::G {
+% 32 0 274 320 bbox
+begingate
+240 1.00 194 144 194 176 306 176 306 144 4 polygon
+240 1.00 272 48 272 144 306 144 306 48 4 polygon
+273 61 beginpath
+192 160 128 309.81 50.19 arcn
+291 284 1 polyc
+192 160 160 51.34 315.00 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::H {
+% 32 0 224 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 224 0 224 320 256 320 256 0 4 polygon
+240 1.00 64 144 64 176 224 176 224 144 4 polygon
+endgate
+} def
+
+/my::I {
+% 64 0 32 320 bbox
+begingate
+240 1.00 64 0 64 320 96 320 96 0 4 polygon
+endgate
+} def
+
+/my::J {
+% 43 0 133 320 bbox
+begingate
+240 1.00 144 80 144 320 176 320 176 80 4 polygon
+176 80 beginpath
+96 80 80 360.00 229.40 arcn
+62 47 1 polyc
+96 80 48 225.00 360.00 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::K {
+% 32 0 224 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 40 176 192 320 232 320 80 176 4 polygon
+240 1.00 216 0 40 176 80 176 256 0 4 polygon
+endgate
+} def
+
+/my::L {
+% 32 0 160 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 64 0 64 32 192 32 192 0 4 polygon
+endgate
+} def
+
+/my::M {
+% 32 0 320 320 bbox
+begingate
+240 1.00 176 0 320 320 352 320 208 0 4 polygon
+240 1.00 208 0 64 320 32 320 176 0 4 polygon
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 320 0 320 320 352 320 352 0 4 polygon
+endgate
+} def
+
+/my::N {
+% 32 0 224 320 bbox
+begingate
+240 1.00 256 0 64 320 32 320 224 0 4 polygon
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 224 0 224 320 256 320 256 0 4 polygon
+endgate
+} def
+
+/my::O {
+% 32 0 320 320 bbox
+begingate
+320 160 beginpath
+192 160 128 0.00 360.00 arc
+352 160 1 polyc
+192 160 160 0.00 360.00 arc
+241 1.00 endpath
+endgate
+} def
+
+/my::P {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+128 128 beginpath
+128 224 96 270.00 450.00 arc
+128 288 1 polyc
+128 224 65 450.00 270.00 arcn
+128 128 1 polyc
+241 1.00 endpath
+240 1.00 64 128 64 160 128 160 128 128 4 polygon
+240 1.00 64 288 64 320 128 320 128 288 4 polygon
+endgate
+} def
+
+/my::Q {
+% 32 0 320 320 bbox
+begingate
+320 160 beginpath
+192 160 128 0.00 360.00 arc
+352 160 1 polyc
+192 160 160 0.00 360.00 arc
+241 1.00 endpath
+240 1.00 312 0 216 96 256 96 352 0 4 polygon
+endgate
+} def
+
+/my::R {
+% 32 0 208 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+128 128 beginpath
+128 224 96 270.00 450.00 arc
+128 288 1 polyc
+128 224 65 450.00 270.00 arcn
+128 128 1 polyc
+241 1.00 endpath
+240 1.00 64 128 64 160 128 160 128 128 4 polygon
+240 1.00 64 288 64 320 128 320 128 288 4 polygon
+240 1.00 200 0 112 144 152 144 240 0 4 polygon
+endgate
+} def
+
+/my::S {
+% 31 -1 169 320 bbox
+begingate
+45 29 beginpath
+112 87 88 -139.33 65.80 arc
+87 197 1 polyc
+112 239 49 239.81 36.45 arcn
+174 290 1 polyc
+112 239 80 40.16 240.45 arc
+134 139 1 polyc
+112 87 56 66.80 -138.37 arcn
+54 66 1 polyc
+31 44 1 polyc
+47 28 1 polyc
+241 1.00 endpath
+endgate
+} def
+
+/my::T {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 288 32 320 224 320 224 288 4 polygon
+240 1.00 112 0 112 320 144 320 144 0 4 polygon
+endgate
+} def
+
+/my::U {
+% 32 0 256 320 bbox
+begingate
+240 1.00 32 128 32 320 64 320 64 128 4 polygon
+240 1.00 256 128 256 320 288 320 288 128 4 polygon
+64 127 beginpath
+160 128 96 180.00 360.00 arc
+288 128 1 polyc
+160 128 128 360.00 180.00 arcn
+240 1.00 endpath
+endgate
+} def
+
+/my::V {
+% 32 0 256 320 bbox
+begingate
+240 1.00 144 0 256 320 288 320 176 0 4 polygon
+240 1.00 176 0 64 320 32 320 144 0 4 polygon
+endgate
+} def
+
+/my::W {
+% 32 0 352 320 bbox
+begingate
+240 1.00 112 0 192 320 224 320 144 0 4 polygon
+240 1.00 144 0 64 320 32 320 112 0 4 polygon
+240 1.00 272 0 352 320 384 320 304 0 4 polygon
+240 1.00 304 0 224 320 192 320 272 0 4 polygon
+endgate
+} def
+
+/my::X {
+% 32 0 232 320 bbox
+begingate
+240 1.00 32 0 224 320 264 320 72 0 4 polygon
+240 1.00 224 0 32 320 72 320 264 0 4 polygon
+endgate
+} def
+
+/my::Y {
+% 32 0 256 320 bbox
+begingate
+240 1.00 144 0 144 176 176 176 176 0 4 polygon
+240 1.00 160 136 32 320 72 320 160 192 4 polygon
+240 1.00 160 136 288 320 248 320 160 192 4 polygon
+endgate
+} def
+
+/my::Z {
+% 32 0 192 320 bbox
+begingate
+240 1.00 32 288 32 320 224 320 224 288 4 polygon
+240 1.00 32 0 32 32 224 32 224 0 4 polygon
+240 1.00 32 32 184 288 224 288 72 32 4 polygon
+endgate
+} def
+
+/my::a {
+% 32 0 176 192 bbox
+begingate
+240 1.00 176 0 176 192 208 192 208 0 4 polygon
+185 67 beginpath
+128 96 64 333.43 26.57 arcn
+196 164 1 polyc
+128 96 96 45.00 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::b {
+% 32 0 176 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+54 67 beginpath
+112 96 64 -153.43 153.43 arc
+44 164 1 polyc
+112 96 96 135.00 -128.66 arcn
+240 1.00 endpath
+endgate
+} def
+
+/my::c {
+% 32 0 156 192 bbox
+begingate
+168 46 beginpath
+128 96 64 309.81 50.19 arcn
+188 171 1 polyc
+128 96 96 51.34 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::d {
+% 32 0 176 320 bbox
+begingate
+240 1.00 176 0 176 320 208 320 208 0 4 polygon
+185 67 beginpath
+128 96 64 333.43 26.57 arcn
+196 164 1 polyc
+128 96 96 45.00 308.66 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::e {
+% 32 0 192 192 bbox
+begingate
+240 1.00 48 80 48 112 192 112 224 96 224 80 5 polygon
+179 57 beginpath
+128 96 64 323.13 0.00 arcn
+224 96 1 polyc
+128 96 96 0.00 324.46 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::f {
+% 32 0 164 320 bbox
+begingate
+240 1.00 112 256 112 0 80 0 80 256 4 polygon
+240 1.00 32 176 32 208 160 208 160 176 4 polygon
+170 273 beginpath
+144 256 32 33.69 180.00 arc
+80 256 1 polyc
+144 256 64 180.00 35.54 arcn
+240 1.00 endpath
+endgate
+} def
+
+/my::g {
+% 32 -112 176 304 bbox
+begingate
+185 67 beginpath
+128 96 64 333.43 26.57 arcn
+196 164 1 polyc
+128 96 96 45.00 308.66 arc
+240 1.00 endpath
+240 1.00 176 -16 176 192 208 192 208 -16 4 polygon
+68 -63 beginpath
+112 -16 64 227.73 360.00 arc
+208 -16 1 polyc
+112 -16 96 360.00 225.00 arcn
+240 1.00 endpath
+endgate
+} def
+
+/my::h {
+% 32 0 160 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 160 0 160 112 192 112 192 0 4 polygon
+35 133 beginpath
+112 112 80 164.05 0.00 arcn
+160 112 1 polyc
+112 112 48 0.00 165.96 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::i {
+% 64 0 32 256 bbox
+begingate
+240 1.00 64 0 64 192 96 192 96 0 4 polygon
+240 1.00 80 240 16 0.00 360.00 xcarc
+endgate
+} def
+
+/my::j {
+% -4 -112 116 368 bbox
+begingate
+240 1.00 80 -48 80 192 112 192 112 -48 4 polygon
+21 -65 beginpath
+48 -48 32 213.69 360.00 arc
+112 -48 1 polyc
+48 -48 64 360.00 215.54 arcn
+240 1.00 endpath
+240 1.00 96 240 16 0.00 360.00 xcarc
+endgate
+} def
+
+/my::k {
+% 32 0 160 320 bbox
+begingate
+240 1.00 32 0 32 320 64 320 64 0 4 polygon
+240 1.00 48 96 136 192 176 192 88 96 4 polygon
+240 1.00 192 0 80 112 40 112 152 0 4 polygon
+endgate
+} def
+
+/my::l {
+% 64 0 32 320 bbox
+begingate
+240 1.00 64 0 64 320 96 320 96 0 4 polygon
+endgate
+} def
+
+/my::m {
+% 32 0 288 192 bbox
+begingate
+240 1.00 288 0 288 112 320 112 320 0 4 polygon
+240 1.00 160 0 160 112 192 112 192 0 4 polygon
+240 1.00 32 0 32 192 64 192 64 0 4 polygon
+35 133 beginpath
+112 112 80 164.05 0.00 arcn
+160 112 1 polyc
+112 112 48 0.00 165.96 arc
+240 1.00 endpath
+163 133 beginpath
+240 112 80 164.05 0.00 arcn
+288 112 1 polyc
+240 112 48 0.00 165.96 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::n {
+% 32 0 160 192 bbox
+begingate
+240 1.00 32 0 32 192 64 192 64 0 4 polygon
+35 133 beginpath
+112 112 80 164.05 0.00 arcn
+160 112 1 polyc
+112 112 48 0.00 165.96 arc
+240 1.00 endpath
+240 1.00 160 0 160 112 192 112 192 0 4 polygon
+endgate
+} def
+
+/my::o {
+% 32 0 192 192 bbox
+begingate
+224 96 beginpath
+128 96 96 0.00 360.00 arc
+192 96 1 polyc
+128 96 64 0.00 360.00 arc
+241 1.00 endpath
+endgate
+} def
+
+/my::p {
+% 32 -112 176 304 bbox
+begingate
+54 67 beginpath
+112 96 64 -153.43 153.43 arc
+44 164 1 polyc
+112 96 96 135.00 -128.66 arcn
+240 1.00 endpath
+240 1.00 32 -112 32 192 64 192 64 -112 4 polygon
+endgate
+} def
+
+/my::q {
+% 32 -112 176 304 bbox
+begingate
+185 67 beginpath
+128 96 64 333.43 26.57 arcn
+196 164 1 polyc
+128 96 96 45.00 308.66 arc
+240 1.00 endpath
+240 1.00 176 -112 176 192 208 192 208 -112 4 polygon
+endgate
+} def
+
+/my::r {
+% 32 0 136 192 bbox
+begingate
+168 168 beginpath
+112 112 80 45.00 180.00 arc
+64 112 1 polyc
+112 112 48 180.00 26.57 arcn
+240 1.00 endpath
+240 1.00 32 0 32 192 64 192 64 0 4 polygon
+endgate
+} def
+
+/my::s {
+% 32 -1 113 193 bbox
+begingate
+138 161 beginpath
+88 136 56 26.57 253.30 arc
+94 79 1 polyc
+88 56 24 433.30 198.43 arcn
+36 34 1 polyc
+88 56 57 -155.56 73.30 arc
+81 114 1 polyc
+88 136 24 253.30 18.43 arcn
+240 1.00 endpath
+endgate
+} def
+
+/my::t {
+% 32 0 164 320 bbox
+begingate
+240 1.00 112 64 112 320 80 320 80 64 4 polygon
+240 1.00 32 240 32 208 160 208 160 240 4 polygon
+170 46 beginpath
+144 64 32 326.31 180.00 arcn
+80 64 1 polyc
+144 64 64 180.00 324.46 arc
+240 1.00 endpath
+endgate
+} def
+
+/my::u {
+% 32 0 160 192 bbox
+begingate
+240 1.00 192 192 192 0 160 0 160 192 4 polygon
+188 58 beginpath
+112 80 80 344.05 180.00 arcn
+64 80 1 polyc
+112 80 48 180.00 345.96 arc
+240 1.00 endpath
+240 1.00 64 192 64 80 32 80 32 192 4 polygon
+endgate
+} def
+
+/my::v {
+% 32 0 192 192 bbox
+begingate
+240 1.00 64 192 144 0 112 0 32 192 4 polygon
+240 1.00 192 192 112 0 144 0 224 192 4 polygon
+endgate
+} def
+
+/my::w {
+% 32 0 288 192 bbox
+begingate
+240 1.00 64 192 128 0 96 0 32 192 4 polygon
+240 1.00 160 192 96 0 128 0 192 192 4 polygon
+240 1.00 192 192 256 0 224 0 160 192 4 polygon
+240 1.00 288 192 224 0 256 0 320 192 4 polygon
+endgate
+} def
+
+/my::x {
+% 32 0 200 192 bbox
+begingate
+240 1.00 232 0 72 192 32 192 192 0 4 polygon
+240 1.00 32 0 192 192 232 192 72 0 4 polygon
+endgate
+} def
+
+/my::y {
+% 32 -112 192 304 bbox
+begingate
+240 1.00 64 192 144 0 112 0 32 192 4 polygon
+240 1.00 192 192 64 -112 96 -112 224 192 4 polygon
+endgate
+} def
+
+/my::z {
+% 32 0 160 192 bbox
+begingate
+240 1.00 32 32 152 160 192 160 72 32 4 polygon
+240 1.00 32 192 32 160 192 160 192 192 4 polygon
+240 1.00 32 32 32 0 192 0 192 32 4 polygon
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/fonts/myfont.xfe b/lib/fonts/myfont.xfe
new file mode 100644
index 0000000..e3cf650
--- /dev/null
+++ b/lib/fonts/myfont.xfe
@@ -0,0 +1,54 @@
+% XCircuit Font encoding (XFE) file
+name: MyFont % Font name
+file: myfont.lps % Font object file
+family: MyFont
+weight: normal
+shape: normal
+scale: 0.085
+type: vectored % Font type (PostScript or vectored)
+encoding: special % Encoding (Standard, ISOLatin1, or special)
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::space my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::A
+my::B my::C my::D my::E my::F my::G
+my::H my::I my::J my::K my::L my::M
+my::N my::O my::P my::Q my::R my::S
+my::T my::U my::V my::W my::X my::Y
+my::Z my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::a my::b my::c my::d my::e
+my::f my::g my::h my::i my::j my::k
+my::l my::m my::n my::o my::p my::q
+my::r my::s my::t my::u my::v my::w
+my::x my::y my::z my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar my::nullchar
+my::nullchar my::nullchar my::nullchar my::nullchar
+
+derived: MyFont-Slant normal italic Special
diff --git a/lib/fonts/symbol.lps b/lib/fonts/symbol.lps
new file mode 100644
index 0000000..0423ba9
--- /dev/null
+++ b/lib/fonts/symbol.lps
@@ -0,0 +1,1506 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: Sy
+% Version: 2.0
+%
+
+% XCircuitLib library built-in objects
+/Sy::nullchar {
+% 0 0 26 32 bbox
+begingate
+0 1.00 0 0 0 32 24 32 24 0 4 polygon
+endgate
+} def
+
+/Sy::space {
+% 0 0 16 26 bbox
+begingate
+endgate
+} def
+
+/Sy::exclam {
+% 4 1 5 25 bbox
+begingate
+1 1.00 5 2 1 0.00 360.00 xcarc
+241 1.00 7 25 5 7 4 25 5 26 6 26 7 25 6 polygon
+endgate
+} def
+
+/Sy::forall {
+% 3 0 24 26 bbox
+begingate
+1 1.00 3 26 14 0 25 26 3 polygon
+1 1.00 8 16 20 16 2 polygon
+endgate
+} def
+
+/Sy::pound {
+% 3 0 19 26 bbox
+begingate
+1 1.00 4 17 20 17 2 polygon
+1 1.00 13 0 17 26 2 polygon
+1 1.00 6 0 10 26 2 polygon
+1 1.00 3 9 19 9 2 polygon
+endgate
+} def
+
+/Sy::every {
+% 3 0 20 26 bbox
+begingate
+1 1.00 3 0 21 0 21 26 3 26 4 polygon
+1 1.00 5 14 21 14 2 polygon
+endgate
+} def
+
+/Sy::percent {
+% 3 0 17 26 bbox
+begingate
+1 1.00 10 24 8 26 6 26 4 24 3 20 5 18 7 18 9 20 10 24 13 24 17 26 3 0
+12 polygon
+1 1.00 13 0 11 2 12 6 14 8 16 8 18 6 17 2 15 0 13 0 9 polygon
+endgate
+} def
+
+/Sy::ampersand {
+% 3 0 22 26 bbox
+begingate
+1 1.00 13 6 7 20 8 24 11 26 14 26 16 24 16 20 14 18 6 14 3 10 3 4 6 1 11 0
+14 1 18 4 20 8 21 12 17 polygon
+1 1.00 23 12 19 12 2 polygon
+1 1.00 13 6 16 2 19 0 21 0 23 2 5 polygon
+endgate
+} def
+
+/Sy::backe {
+% 3 0 16 18 bbox
+begingate
+1 1.00 5 10 17 10 2 polygon
+1 1.00 3 1 6 0 11 0 15 2 17 6 17 12 15 16 11 18 6 18 3 17 10 polygon
+endgate
+} def
+
+/Sy::lparen {
+% 4 -5 8 32 bbox
+begingate
+1 1.00 10 -5 6 0 4 6 4 16 6 22 10 27 6 polygon
+endgate
+} def
+
+/Sy::rparen {
+% 4 -5 8 32 bbox
+begingate
+1 1.00 4 -5 8 0 10 6 10 16 8 22 4 27 6 polygon
+endgate
+} def
+
+/Sy::asterisk {
+% 4 8 10 8 bbox
+begingate
+1 1.00 8 8 8 16 2 polygon
+1 1.00 4 10 12 14 2 polygon
+1 1.00 4 14 12 10 2 polygon
+endgate
+} def
+
+/Sy::plus {
+% 4 4 18 16 bbox
+begingate
+1 1.00 12 4 12 20 2 polygon
+1 1.00 4 12 20 12 2 polygon
+endgate
+} def
+
+/Sy::comma {
+% 4 -4 6 8 bbox
+% hidden
+begingate
+241 1.00 6 2 2 0.00 360.00 xcarc
+1 1.00 8 2 8 0 7 -2 5 -4 4 polygon
+endgate
+} def
+
+/Sy::minus {
+% 4 12 20 0 bbox
+begingate
+1 1.00 4 12 22 12 2 polygon
+endgate
+} def
+
+/Sy::period {
+% 4 0 6 4 bbox
+begingate
+241 1.00 6 2 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::slash {
+% 4 0 12 26 bbox
+begingate
+1 1.00 4 0 14 26 2 polygon
+endgate
+} def
+
+/Sy::zero {
+% 4 0 20 26 bbox
+begingate
+1 1.00 10 0 6 4 4 10 4 16 6 22 10 26 16 26 20 22 22 16 22 10 20 4 16 0 10 0
+13 polygon
+endgate
+} def
+
+/Sy::one {
+% 4 0 10 28 bbox
+begingate
+1 1.00 8 0 8 28 4 24 3 polygon
+1 1.00 4 0 12 0 2 polygon
+endgate
+} def
+
+/Sy::two {
+% 4 0 22 26 bbox
+begingate
+1 1.00 22 0 4 0 20 12 22 16 22 20 20 24 16 26 12 26 8 24 6 22 10 polygon
+1 1.00 22 0 24 4 2 polygon
+endgate
+} def
+
+/Sy::three {
+% 4 0 18 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 14 0 18 2 20 6 20 10 16 15 12 14 9 polygon
+1 1.00 16 15 18 16 20 20 18 24 14 26 10 26 6 24 7 polygon
+endgate
+} def
+
+/Sy::four {
+% 4 0 20 26 bbox
+begingate
+1 1.00 18 0 18 26 4 8 4 6 22 6 5 polygon
+endgate
+} def
+
+/Sy::five {
+% 4 0 19 26 bbox
+begingate
+1 1.00 4 2 8 0 13 0 17 2 19 6 19 10 17 14 13 16 9 17 5 17 7 26 21 26
+12 polygon
+endgate
+} def
+
+/Sy::six {
+% 4 0 18 26 bbox
+begingate
+1 1.00 18 26 14 26 10 24 6 20 4 14 4 6 6 2 10 0 14 0 18 2 20 6 20 12 18 16
+14 18 10 18 6 16 4 14 17 polygon
+endgate
+} def
+
+/Sy::seven {
+% 3 0 17 26 bbox
+begingate
+1 1.00 8 0 18 26 4 26 3 24 4 polygon
+endgate
+} def
+
+/Sy::eight {
+% 4 0 20 26 bbox
+% hidden
+begingate
+1 1.00 10 0 6 2 4 4 4 8 8 12 18 16 20 20 20 22 16 26 10 26 6 22 6 20 8 16
+18 12 22 8 22 4 20 2 16 0 10 0 19 polygon
+endgate
+} def
+
+/Sy::nine {
+% 4 0 20 26 bbox
+begingate
+1 1.00 8 0 13 1 18 4 21 8 22 12 22 18 20 24 16 26 10 26 6 24 4 20 4 14 6 10
+10 8 16 8 20 10 22 14 17 polygon
+endgate
+} def
+
+/Sy::colon {
+% 6 4 6 18 bbox
+begingate
+241 1.00 8 20 2 0.00 360.00 xcarc
+241 1.00 8 6 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::semi {
+% 6 -6 6 24 bbox
+begingate
+241 1.00 8 16 2 0.00 360.00 xcarc
+1.00 0 2 -2 Sy::comma
+endgate
+} def
+
+/Sy::less {
+% 4 6 18 12 bbox
+begingate
+1 1.00 20 6 4 12 20 18 3 polygon
+endgate
+} def
+
+/Sy::equal {
+% 6 10 18 4 bbox
+begingate
+1 1.00 6 10 22 10 2 polygon
+1 1.00 6 14 22 14 2 polygon
+endgate
+} def
+
+/Sy::more {
+% 4 6 18 12 bbox
+begingate
+1 1.00 4 6 20 12 4 18 3 polygon
+endgate
+} def
+
+/Sy::question {
+% 5 0 15 28 bbox
+begingate
+1 1.00 5 25 8 28 14 28 18 24 18 20 12 14 10 10 10 8 8 polygon
+241 1.00 10 2 2 0.00 360.00 xcarc
+1 1.00 6 24 1 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::approx {
+% 4 10 18 10 bbox
+begingate
+1 1.00 4 10 20 10 2 polygon
+1 1.00 4 14 20 14 2 polygon
+1 1.00 4 18 6 20 10 20 14 18 18 18 20 20 6 polygon
+endgate
+} def
+
+/Sy::Alpha {
+% 2 0 26 26 bbox
+begingate
+1 1.00 4 0 14 26 24 0 3 polygon
+1 1.00 8 8 20 8 2 polygon
+1 1.00 2 0 6 0 2 polygon
+1 1.00 20 0 26 0 2 polygon
+endgate
+} def
+
+/Sy::Beta {
+% 4 0 21 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 0 17 0 21 2 23 6 23 8 21 12 17 14 7 polygon
+1 1.00 4 26 14 26 19 24 21 20 21 18 17 14 6 14 7 polygon
+endgate
+} def
+
+/Sy::Xi {
+% 2 0 26 26 bbox
+begingate
+1 1.00 4 0 24 26 2 polygon
+1 1.00 4 26 24 0 2 polygon
+1 1.00 2 26 8 26 2 polygon
+1 1.00 20 0 26 0 2 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 20 26 26 26 2 polygon
+endgate
+} def
+
+/Sy::Delta {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 0 24 0 2 polygon
+1 1.00 4 0 14 26 24 0 3 polygon
+endgate
+} def
+
+/Sy::Epsilon {
+% 4 0 20 26 bbox
+begingate
+1 1.00 20 0 4 0 2 polygon
+1 1.00 6 13 18 13 2 polygon
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 26 20 26 2 polygon
+1 1.00 20 26 21 22 2 polygon
+1 1.00 20 0 22 4 2 polygon
+1 1.00 18 17 18 10 2 polygon
+endgate
+} def
+
+/Sy::Phi {
+% 4 0 26 26 bbox
+begingate
+1 1.00 16 0 16 26 2 polygon
+1 1.00 12 4 8 6 6 8 4 12 4 14 6 18 8 20 12 22 20 22 24 20 26 18 28 14 28 12
+26 8 24 6 20 4 12 4 17 polygon
+1 1.00 12 0 20 0 2 polygon
+1 1.00 12 26 20 26 2 polygon
+endgate
+} def
+
+/Sy::Gamma {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 26 20 26 2 polygon
+1 1.00 20 26 22 22 2 polygon
+1 1.00 4 0 10 0 2 polygon
+endgate
+} def
+
+/Sy::Eta {
+% 4 0 22 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 22 0 22 26 2 polygon
+1 1.00 6 14 22 14 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 24 26 18 26 2 polygon
+1 1.00 24 0 18 0 2 polygon
+endgate
+} def
+
+/Sy::Iota {
+% 4 0 6 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 0 8 0 2 polygon
+1 1.00 4 26 8 26 2 polygon
+endgate
+} def
+
+/Sy::altTheta {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 18 6 16 6 8 8 4 12 0 16 0 20 2 22 8 22 20 20 24 16 26 12 26 10 24
+10 22 12 20 18 20 22 18 24 16 18 polygon
+endgate
+} def
+
+/Sy::Kappa {
+% 2 0 24 26 bbox
+begingate
+1 1.00 4 0 4 26 2 polygon
+1 1.00 22 26 4 12 2 polygon
+1 1.00 22 0 7 14 2 polygon
+1 1.00 2 26 8 26 2 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 24 0 18 0 2 polygon
+1 1.00 24 26 18 26 2 polygon
+endgate
+} def
+
+/Sy::Lambda {
+% 2 0 26 26 bbox
+begingate
+1 1.00 4 0 14 26 24 0 3 polygon
+1 1.00 20 0 26 0 2 polygon
+1 1.00 2 0 8 0 2 polygon
+endgate
+} def
+
+/Sy::Mu {
+% 2 0 30 26 bbox
+begingate
+1 1.00 4 0 4 26 16 0 28 26 28 0 5 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 30 0 24 0 2 polygon
+1 1.00 28 26 30 26 2 polygon
+1 1.00 2 26 4 26 2 polygon
+endgate
+} def
+
+/Sy::Nu {
+% 2 0 26 26 bbox
+begingate
+1 1.00 4 0 4 26 24 0 24 26 4 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 26 26 20 26 2 polygon
+1 1.00 2 26 4 26 2 polygon
+endgate
+} def
+
+/Sy::Omicron {
+% 4 0 28 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 22 9 polygon
+1 1.00 18 0 24 4 26 10 26 16 24 22 5 polygon
+endgate
+} def
+
+/Sy::Pi {
+% 4 0 24 26 bbox
+begingate
+1 1.00 8 0 8 26 2 polygon
+1 1.00 22 0 22 26 2 polygon
+1 1.00 4 26 26 26 2 polygon
+1 1.00 6 0 10 0 2 polygon
+1 1.00 20 0 24 0 2 polygon
+endgate
+} def
+
+/Sy::Theta {
+% 4 0 33 26 bbox
+begingate
+1 1.00 13 13 25 13 2 polygon
+1.00 0 4 0 Sy::Omicron
+1 1.00 13 15 13 11 2 polygon
+1 1.00 25 15 25 11 2 polygon
+endgate
+} def
+
+/Sy::Rho {
+% 4 0 19 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 26 17 26 21 22 21 18 17 14 6 14 6 polygon
+1 1.00 4 0 10 0 2 polygon
+endgate
+} def
+
+/Sy::Sigma {
+% 4 0 22 26 bbox
+begingate
+1 1.00 24 4 24 0 4 0 16 14 4 26 24 26 24 22 7 polygon
+endgate
+} def
+
+/Sy::Tau {
+% 4 0 20 26 bbox
+begingate
+1 1.00 13 0 13 26 2 polygon
+1 1.00 4 22 4 26 22 26 22 22 4 polygon
+1 1.00 10 0 16 0 2 polygon
+endgate
+} def
+
+/Sy::GrY {
+% 2 0 26 26 bbox
+begingate
+1 1.00 4 26 14 14 14 0 3 polygon
+1 1.00 24 26 14 14 2 polygon
+1 1.00 2 26 8 26 2 polygon
+1 1.00 20 26 26 26 2 polygon
+1 1.00 12 0 16 0 2 polygon
+endgate
+} def
+
+/Sy::altSigma {
+% 4 -6 18 24 bbox
+begingate
+1 1.00 8 -4 12 -6 16 -6 18 -4 18 -2 16 0 10 0 6 2 4 6 4 10 6 14 10 16 16 16
+20 18 14 polygon
+endgate
+} def
+
+/Sy::Omega {
+% 4 0 28 26 bbox
+begingate
+1 1.00 6 2 7 0 14 0 14 3 10 4 6 8 4 12 4 16 6 20 10 24 14 26 20 26 24 24 28 20
+30 16 30 12 28 8 24 4 20 3 20 0 27 0 28 2 22 polygon
+endgate
+} def
+
+/Sy::Chi {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 0 24 0 2 polygon
+1 1.00 4 26 24 26 2 polygon
+1 1.00 8 14 20 14 2 polygon
+1 1.00 8 16 8 12 2 polygon
+1 1.00 20 16 20 12 2 polygon
+1 1.00 4 4 4 0 2 polygon
+1 1.00 24 4 24 0 2 polygon
+1 1.00 24 26 24 22 2 polygon
+1 1.00 4 26 4 22 2 polygon
+endgate
+} def
+
+/Sy::Psi {
+% 4 0 26 26 bbox
+begingate
+1 1.00 16 0 16 26 2 polygon
+1 1.00 4 26 6 24 6 20 4 16 4 14 6 10 10 8 22 8 26 10 28 14 28 16 26 20 26 24
+28 26 14 polygon
+1 1.00 14 26 18 26 2 polygon
+1 1.00 14 0 18 0 2 polygon
+endgate
+} def
+
+/Sy::Zeta {
+% 4 0 20 26 bbox
+begingate
+1 1.00 4 22 4 26 22 26 4 0 21 0 22 4 6 polygon
+endgate
+} def
+
+/Sy::lbracket {
+% 4 -2 8 30 bbox
+begingate
+1 1.00 10 -2 4 -2 4 28 10 28 4 polygon
+endgate
+} def
+
+/Sy::therefore {
+% 3 7 16 12 bbox
+begingate
+1 1.00 4 8 1 0.00 360.00 xcarc
+1 1.00 16 8 1 0.00 360.00 xcarc
+1 1.00 10 18 1 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::rbracket {
+% 4 -2 8 30 bbox
+begingate
+1 1.00 4 -2 10 -2 10 28 4 28 4 polygon
+endgate
+} def
+
+/Sy::perp {
+% 4 8 18 14 bbox
+begingate
+1 1.00 4 8 20 8 2 polygon
+1 1.00 12 8 12 22 2 polygon
+endgate
+} def
+
+/Sy::underscore {
+% 2 0 24 0 bbox
+begingate
+1 1.00 2 0 24 0 2 polygon
+endgate
+} def
+
+/Sy::upneg {
+% 22 32 20 0 bbox
+begingate
+1 1.00 22 32 40 32 2 polygon
+endgate
+} def
+
+/Sy::alpha {
+% 4 0 21 16 bbox
+begingate
+1 1.00 23 0 21 2 18 13 14 16 10 16 6 14 4 10 4 6 6 2 10 0 14 0 17 3 21 15
+13 polygon
+endgate
+} def
+
+/Sy::beta {
+% 3 -6 17 32 bbox
+begingate
+1 1.00 3 0 3 21 5 24 9 26 13 26 15 24 16 20 14 17 11 15 7 15 10 polygon
+1 1.00 11 15 15 14 18 9 17 3 13 0 9 0 5 2 7 polygon
+1 1.00 3 -6 3 0 2 polygon
+endgate
+} def
+
+/Sy::chi {
+% 0 -5 17 21 bbox
+begingate
+1 1.00 0 -5 14 16 2 polygon
+1 1.00 0 14 2 16 4 14 12 -4 14 -4 15 -2 6 polygon
+endgate
+} def
+
+/Sy::delta {
+% 3 0 17 26 bbox
+begingate
+1 1.00 12 17 9 16 5 14 3 10 3 6 5 2 9 0 13 0 17 3 18 7 17 11 15 14 7 22 7 24
+9 26 11 26 13 24 17 polygon
+endgate
+} def
+
+/Sy::epsilon {
+% 4 0 13 16 bbox
+begingate
+1 1.00 15 3 14 2 11 0 7 0 4 2 4 6 6 8 11 8 6 9 4 12 4 14 7 16 11 16 14 14
+14 polygon
+endgate
+} def
+
+/Sy::phi {
+% 4 -6 18 28 bbox
+begingate
+1 1.00 12 -6 12 22 2 polygon
+1 1.00 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 20 10 20 6 18 2 14 0 10 0
+13 polygon
+endgate
+} def
+
+/Sy::gamma {
+% 4 -6 16 22 bbox
+begingate
+1 1.00 4 14 6 16 8 16 10 12 14 0 14 -4 12 -6 12 -2 16 6 18 12 18 16 11 polygon
+endgate
+} def
+
+/Sy::eta {
+% 4 -6 17 22 bbox
+begingate
+1 1.00 4 14 6 16 8 14 8 0 4 polygon
+1 1.00 8 12 12 15 15 16 18 15 19 12 19 -6 6 polygon
+endgate
+} def
+
+/Sy::iota {
+% 4 0 6 16 bbox
+begingate
+1 1.00 4 16 4 2 6 0 8 2 4 polygon
+endgate
+} def
+
+/Sy::altphi {
+% 6 -6 19 22 bbox
+begingate
+1 1.00 14 -6 14 12 16 16 18 16 21 15 23 12 23 6 21 2 17 0 12 0 8 2 6 6 6 12
+8 16 10 16 15 polygon
+endgate
+} def
+
+/Sy::kappa {
+% 3 0 18 16 bbox
+begingate
+1 1.00 8 10 17 0 2 polygon
+1 1.00 14 0 19 0 2 polygon
+1 1.00 5 8 13 14 17 16 18 16 4 polygon
+1 1.00 5 0 5 16 3 16 3 polygon
+endgate
+} def
+
+/Sy::lambda {
+% 4 0 19 26 bbox
+begingate
+1 1.00 4 0 12 15 2 polygon
+1 1.00 5 24 7 26 10 24 17 2 19 0 21 2 6 polygon
+endgate
+} def
+
+/Sy::mu {
+% 4 -6 18 22 bbox
+begingate
+1 1.00 4 -6 4 16 2 polygon
+1 1.00 4 2 8 0 12 0 16 4 4 polygon
+1 1.00 16 16 16 2 18 0 20 2 4 polygon
+endgate
+} def
+
+/Sy::nu {
+% 4 0 18 16 bbox
+begingate
+1 1.00 4 14 6 16 8 14 12 0 18 10 20 14 20 16 7 polygon
+endgate
+} def
+
+/Sy::omicron {
+% 4 0 18 16 bbox
+begingate
+1 1.00 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 20 10 20 6 18 2 14 0 10 0
+13 polygon
+endgate
+} def
+
+/Sy::pi {
+% 4 0 19 17 bbox
+begingate
+1 1.00 16 16 16 2 18 0 20 2 4 polygon
+1 1.00 4 1 6 0 8 4 8 16 4 polygon
+1 1.00 4 15 5 16 20 16 21 17 4 polygon
+endgate
+} def
+
+/Sy::theta {
+% 4 0 18 26 bbox
+begingate
+1 1.00 10 0 6 3 4 8 4 18 6 23 10 26 14 26 18 23 20 18 20 8 18 3 14 0 10 0
+13 polygon
+1 1.00 4 14 20 14 2 polygon
+endgate
+} def
+
+/Sy::rho {
+% 4 -6 16 22 bbox
+begingate
+1 1.00 4 -6 4 10 6 14 10 16 14 16 16 14 18 10 18 6 16 2 12 0 8 0 4 4
+12 polygon
+endgate
+} def
+
+/Sy::sigma {
+% 4 0 20 16 bbox
+begingate
+1 1.00 10 0 6 2 4 6 4 10 6 14 10 16 14 16 18 14 20 10 20 6 18 2 14 0 10 0
+13 polygon
+1 1.00 14 16 19 15 2 polygon
+1 1.00 20 15 22 16 2 polygon
+endgate
+} def
+
+/Sy::tau {
+% 4 0 16 17 bbox
+begingate
+1 1.00 4 14 6 16 16 16 18 17 4 polygon
+1 1.00 10 16 10 2 12 0 14 0 16 2 5 polygon
+endgate
+} def
+
+/Sy::upsilon {
+% 4 0 18 16 bbox
+begingate
+1 1.00 4 14 6 16 8 14 8 4 10 0 16 0 18 2 20 6 20 12 18 16 10 polygon
+endgate
+} def
+
+/Sy::altomega {
+% 4 0 24 16 bbox
+begingate
+1 1.00 4 14 6 16 26 16 3 polygon
+1 1.00 10 16 6 10 6 6 8 2 10 0 14 0 16 4 16 8 8 polygon
+1 1.00 16 4 20 0 24 0 26 4 26 10 24 16 6 polygon
+endgate
+} def
+
+/Sy::omega {
+% 4 0 22 16 bbox
+begingate
+1 1.00 8 16 6 14 4 10 4 6 6 2 8 0 12 0 14 4 15 10 14 12 13 10 14 4 16 0 20 0
+22 2 24 6 24 10 22 14 20 16 19 polygon
+endgate
+} def
+
+/Sy::xi {
+% 6 -6 16 32 bbox
+begingate
+1 1.00 10 26 8 26 6 24 8 22 13 21 17 22 14 23 9 21 6 17 7 14 14 11 18 12 14 13
+10 12 6 8 6 2 10 0 18 0 20 -2 20 -4 16 -6 10 -6 22 polygon
+endgate
+} def
+
+/Sy::psi {
+% 4 -6 21 28 bbox
+begingate
+1 1.00 14 -6 14 22 2 polygon
+1 1.00 4 14 6 16 8 14 8 12 6 8 6 4 10 0 18 0 21 2 23 6 22 12 20 15 12 polygon
+endgate
+} def
+
+/Sy::zeta {
+% 4 -6 16 32 bbox
+begingate
+1 1.00 8 26 6 26 4 24 6 22 12 21 17 22 13 23 9 20 6 16 4 10 4 2 8 0 16 0 18 -2
+18 -4 14 -6 8 -6 17 polygon
+endgate
+} def
+
+/Sy::lbrace {
+% 4 -4 8 32 bbox
+begingate
+1 1.00 10 -4 8 -4 6 -2 6 10 4 12 6 14 6 26 8 28 10 28 9 polygon
+endgate
+} def
+
+/Sy::vbar {
+% 6 -2 0 30 bbox
+begingate
+1 1.00 6 -2 6 28 2 polygon
+endgate
+} def
+
+/Sy::rbrace {
+% 4 -4 8 32 bbox
+begingate
+1 1.00 4 -4 6 -4 8 -2 8 10 10 12 8 14 8 26 6 28 4 28 9 polygon
+endgate
+} def
+
+/Sy::tilde {
+% 4 12 18 2 bbox
+begingate
+1 1.00 4 12 6 14 10 14 14 12 18 12 20 14 6 polygon
+endgate
+} def
+
+/Sy::Upsilon {
+% 4 0 22 26 bbox
+begingate
+1 1.00 14 0 14 12 12 18 10 22 6 26 4 26 6 polygon
+1 1.00 14 12 20 24 22 26 24 24 4 polygon
+1 1.00 12 0 16 0 2 polygon
+endgate
+} def
+
+/Sy::prime {
+% 6 22 6 10 bbox
+begingate
+0 1.00 10 32 6 22 8 32 3 polygon
+endgate
+} def
+
+/Sy::leq {
+% 4 4 18 14 bbox
+begingate
+1 1.00 20 8 4 13 20 18 3 polygon
+1 1.00 4 4 20 4 2 polygon
+endgate
+} def
+
+/Sy::aslash {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 0 18 26 2 polygon
+endgate
+} def
+
+/Sy::infty {
+% 4 6 20 10 bbox
+begingate
+1 1.00 20 6 16 6 10 16 6 16 4 12 4 10 6 6 10 6 16 16 20 16 10 polygon
+1 1.00 20 16 22 12 22 10 20 6 4 polygon
+endgate
+} def
+
+/Sy::itf {
+% 2 -6 14 32 bbox
+begingate
+1 1.00 2 -4 4 -6 6 -4 10 24 12 26 14 24 6 polygon
+1 1.00 4 18 14 18 2 polygon
+endgate
+} def
+
+/Sy::rarrow {
+% 6 8 30 8 bbox
+begingate
+1 1.00 6 12 34 12 2 polygon
+1 1.00 24 8 34 12 24 16 3 polygon
+endgate
+} def
+
+/Sy::larrow {
+% 6 10 30 8 bbox
+begingate
+1.00 -1 40 2 Sy::rarrow
+endgate
+} def
+
+/Sy::uarrow {
+% 6 2 10 28 bbox
+begingate
+1.00 90 22 -4 Sy::rarrow
+endgate
+} def
+
+/Sy::lrarrow {
+% 6 12 34 8 bbox
+begingate
+1.00 0 4 4 Sy::rarrow
+1.00 -1 40 4 Sy::rarrow
+endgate
+} def
+
+/Sy::darrow {
+% 8 -2 10 28 bbox
+begingate
+1.00 270 0 32 Sy::rarrow
+endgate
+} def
+
+/Sy::degree {
+% 8 20 10 8 bbox
+begingate
+1 1.00 12 24 4 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::pm {
+% 4 6 18 10 bbox
+begingate
+1 1.00 12 8 12 16 2 polygon
+1 1.00 4 12 20 12 2 polygon
+1 1.00 4 6 20 6 2 polygon
+endgate
+} def
+
+/Sy::dprime {
+% 5 22 12 10 bbox
+begingate
+1.00 0 5 0 Sy::prime
+1.00 0 -1 0 Sy::prime
+endgate
+} def
+
+/Sy::geq {
+% 8 6 18 14 bbox
+begingate
+1.00 -1 28 2 Sy::leq
+endgate
+} def
+
+/Sy::times {
+% 4 6 14 12 bbox
+begingate
+1 1.00 4 6 16 18 2 polygon
+1 1.00 4 18 16 6 2 polygon
+endgate
+} def
+
+/Sy::prop {
+% 4 6 18 10 bbox
+begingate
+1 1.00 20 6 16 6 10 16 6 16 4 12 4 10 6 6 10 6 16 16 20 16 10 polygon
+endgate
+} def
+
+/Sy::deriv {
+% 5 0 17 26 bbox
+begingate
+1 1.00 9 24 12 26 16 25 19 22 20 16 20 6 18 2 14 0 11 0 7 2 5 6 5 10 8 14
+12 16 15 16 18 14 20 10 17 polygon
+endgate
+} def
+
+/Sy::bullet {
+% 5 8 10 8 bbox
+begingate
+241 1.00 9 12 4 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::div {
+% 4 4 18 16 bbox
+begingate
+1 1.00 4 12 20 12 2 polygon
+241 1.00 12 18 2 0.00 360.00 xcarc
+241 1.00 12 6 2 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::neq {
+% 4 8 18 12 bbox
+begingate
+1 1.00 4 8 20 20 2 polygon
+1.00 0 -2 2 Sy::equal
+endgate
+} def
+
+/Sy::teq {
+% 4 6 18 8 bbox
+begingate
+1 1.00 4 10 20 10 2 polygon
+1 1.00 4 14 20 14 2 polygon
+1 1.00 4 6 20 6 2 polygon
+endgate
+} def
+
+/Sy::sim {
+% 6 8 18 6 bbox
+begingate
+1.00 0 2 0 Sy::tilde
+1.00 0 2 -4 Sy::tilde
+endgate
+} def
+
+/Sy::dots {
+% 6 1 34 4 bbox
+begingate
+1.00 0 2 1 Sy::period
+1.00 0 16 1 Sy::period
+1.00 0 30 1 Sy::period
+endgate
+} def
+
+/Sy::longvbar {
+% 10 -8 2 36 bbox
+begingate
+1 1.00 10 -8 10 28 2 polygon
+endgate
+} def
+
+/Sy::lang {
+% 8 -4 10 30 bbox
+begingate
+1 1.00 16 -4 8 11 16 26 3 polygon
+endgate
+} def
+
+/Sy::rang {
+% 8 -4 10 30 bbox
+begingate
+1 1.00 8 -4 16 11 8 26 3 polygon
+endgate
+} def
+
+/Sy::int {
+% 8 -4 18 36 bbox
+begingate
+1 1.00 8 0 8 -2 10 -4 12 -4 14 -2 16 0 16 26 18 30 20 32 22 32 24 30 24 28
+12 polygon
+endgate
+} def
+
+/Sy::diamond {
+% 3 0 20 26 bbox
+begingate
+241 1.00 12 0 3 13 12 26 21 13 12 0 5 polygon
+endgate
+} def
+
+/Sy::heart {
+% 4 0 26 24 bbox
+begingate
+26 14 beginpath
+22 18 6 -38.66 168.69 arc
+10 18 6 11.31 219.81 arc
+26 13 16 0 2 polyc
+241 1.00 endpath
+endgate
+} def
+
+/Sy::club {
+% 5 0 27 25 bbox
+begingate
+22 4 beginpath
+25 9 5 -120.96 120.96 arc
+21 17 18 11 2 polyc
+17 20 5 -30.96 210.96 arc
+13 13 17 11 2 polyc
+10 9 5 59.04 300.96 arc
+22 5 17 8 20 0 15 0 18 8 5 polyc
+241 1.00 endpath
+endgate
+} def
+
+/Sy::spade {
+% 4 0 24 25 bbox
+begingate
+5 12 beginpath
+9 9 5 140.19 348.69 arc
+16 8 15 8 17 0 13 0 15 8 5 polyc
+21 9 5 191.31 398.66 arc
+5 12 15 25 2 polyc
+241 1.00 endpath
+endgate
+} def
+
+/Sy::del {
+% 6 0 22 26 bbox
+begingate
+1.00 -181 2 26 Sy::Delta
+endgate
+} def
+
+/Sy::hbar {
+% 0 16 44 0 bbox
+begingate
+1 1.00 0 16 44 16 2 polygon
+endgate
+} def
+
+/Sy::return {
+% 2 4 18 24 bbox
+begingate
+1 1.00 20 28 20 8 2 8 3 polygon
+1 1.00 2 8 12 12 2 polygon
+1 1.00 2 8 12 4 2 polygon
+endgate
+} def
+
+/Sy::aleph {
+% 4 0 26 26 bbox
+begingate
+1 1.00 4 26 6 22 22 5 24 0 4 polygon
+1 1.00 4 0 8 1 6 4 5 8 5 11 7 14 10 16 7 polygon
+1 1.00 14 14 19 18 21 20 3 polygon
+1 1.00 18 26 19 23 23 19 3 polygon
+endgate
+} def
+
+/Sy::Ifraktur {
+% 3 0 22 27 bbox
+begingate
+1 1.00 4 4 7 3 10 0 14 0 18 1 21 3 23 7 23 12 19 19 22 27 18 26 12 26 9 27
+5 26 3 22 5 19 9 18 17 polygon
+endgate
+} def
+
+/Sy::Rfraktur {
+% 3 0 25 27 bbox
+begingate
+1 1.00 4 2 5 0 7 0 9 2 10 13 9 23 7 27 5 27 3 24 3 21 5 19 6 17 12 polygon
+1 1.00 9 23 14 27 17 26 22 21 10 13 5 polygon
+1 1.00 13 15 16 13 18 8 21 2 23 0 26 2 6 polygon
+endgate
+} def
+
+/Sy::weiers {
+% 4 0 26 21 bbox
+begingate
+1 1.00 12 21 7 18 5 14 5 11 8 4 8 1 6 0 4 2 4 4 6 8 10 15 15 18 20 20 23 19
+24 16 22 11 16 6 12 5 10 6 10 8 11 10 21 polygon
+endgate
+} def
+
+/Sy::circmult {
+% 3 3 26 26 bbox
+begingate
+1 1.00 16 16 13 0.00 360.00 xcarc
+1.00 0 6 4 Sy::times
+endgate
+} def
+
+/Sy::circplus {
+% 3 3 26 26 bbox
+begingate
+1 1.00 16 16 13 0.00 360.00 xcarc
+1.00 0 4 4 Sy::plus
+endgate
+} def
+
+/Sy::circslash {
+% 3 3 26 26 bbox
+begingate
+1 1.00 16 16 13 0.00 360.00 xcarc
+1 1.00 3 3 29 29 2 polygon
+endgate
+} def
+
+/Sy::intersect {
+% 3 2 26 27 bbox
+begingate
+1 1.00 16 16 13 0.00 180.00 xcarc
+1 1.00 3 16 3 2 2 polygon
+1 1.00 29 16 29 2 2 polygon
+endgate
+} def
+
+/Sy::union {
+% 3 2 26 27 bbox
+begingate
+1.00 -181 0 31 Sy::intersect
+endgate
+} def
+
+/Sy::propsup {
+% 3 3 27 26 bbox
+begingate
+1.00 270 1 32 Sy::intersect
+endgate
+} def
+
+/Sy::reflsup {
+% 3 0 27 30 bbox
+begingate
+1 1.00 3 0 30 0 2 polygon
+1.00 0 0 1 Sy::propsup
+endgate
+} def
+
+/Sy::notsub {
+% 2 0 27 32 bbox
+begingate
+1.00 90 31 0 Sy::intersect
+1 1.00 25 32 7 0 2 polygon
+endgate
+} def
+
+/Sy::propsub {
+% 2 3 27 26 bbox
+begingate
+1.00 90 31 0 Sy::intersect
+endgate
+} def
+
+/Sy::reflsub {
+% 2 0 27 30 bbox
+begingate
+1.00 0 0 1 Sy::propsub
+1 1.00 2 0 29 0 2 polygon
+endgate
+} def
+
+/Sy::element {
+% 2 3 27 26 bbox
+begingate
+1.00 0 0 0 Sy::propsub
+1 1.00 2 16 29 16 2 polygon
+endgate
+} def
+
+/Sy::notelement {
+% 2 0 27 32 bbox
+begingate
+1.00 0 0 0 Sy::element
+1 1.00 23 32 10 0 2 polygon
+endgate
+} def
+
+/Sy::angle {
+% 2 0 23 23 bbox
+begingate
+1 1.00 3 0 25 0 2 polygon
+1 1.00 2 0 24 23 2 polygon
+endgate
+} def
+
+/Sy::copy {
+% 3 3 26 26 bbox
+begingate
+1 1.00 16 16 13 0.00 360.00 xcarc
+1 1.00 16 16 9 49.40 315.00 xcarc
+endgate
+} def
+
+/Sy::rights {
+% 3 3 26 26 bbox
+begingate
+1 1.00 16 16 13 0.00 360.00 xcarc
+1 1.00 11 8 11 25 15 25 3 polygon
+1 1.00 11 15 16 15 21 8 3 polygon
+1 1.00 15 20 5 270.00 450.00 xcarc
+endgate
+} def
+
+/Sy::trade {
+% 2 21 17 7 bbox
+begingate
+1 1.00 2 28 8 28 2 polygon
+1 1.00 5 28 5 21 2 polygon
+1 1.00 11 28 11 21 2 polygon
+1 1.00 11 28 15 21 19 28 19 21 4 polygon
+endgate
+} def
+
+/Sy::product {
+% 3 0 26 29 bbox
+begingate
+1 1.00 3 29 29 29 2 polygon
+1 1.00 6 28 6 0 2 polygon
+1 1.00 3 0 9 0 2 polygon
+1 1.00 26 29 26 0 2 polygon
+1 1.00 23 0 29 0 2 polygon
+endgate
+} def
+
+/Sy::sqrt {
+% 2 0 20 30 bbox
+begingate
+1 1.00 2 12 4 13 7 0 19 30 22 30 5 polygon
+endgate
+} def
+
+/Sy::sum {
+% 4 0 23 29 bbox
+begingate
+1 1.00 27 4 25 0 4 0 14 14 4 29 25 29 27 25 7 polygon
+endgate
+} def
+
+/Sy::lozenge {
+% 4 0 18 30 bbox
+begingate
+1.00 0 4 4 Sy::rang
+1.00 0 -4 4 Sy::lang
+endgate
+} def
+
+/Sy::cdot {
+% 5 11 6 4 bbox
+begingate
+1.00 0 1 11 Sy::period
+endgate
+} def
+
+/Sy::up {
+% 5 5 12 18 bbox
+begingate
+1.00 270 -1 27 Sy::less
+endgate
+} def
+
+/Sy::down {
+% 5 5 12 18 bbox
+begingate
+1.00 90 23 1 Sy::less
+endgate
+} def
+
+/Sy::lognot {
+% 4 11 16 5 bbox
+begingate
+1 1.00 4 16 20 16 20 11 3 polygon
+endgate
+} def
+
+/Sy::dlarrow {
+% 3 9 24 10 bbox
+begingate
+1 1.00 13 19 3 14 13 9 3 polygon
+1 1.00 7 16 27 16 2 polygon
+1 1.00 7 12 27 12 2 polygon
+endgate
+} def
+
+/Sy::drarrow {
+% 3 8 24 10 bbox
+begingate
+1.00 -1 30 -1 Sy::dlarrow
+endgate
+} def
+
+/Sy::duparrow {
+% 4 2 10 24 bbox
+begingate
+1.00 270 -5 29 Sy::dlarrow
+endgate
+} def
+
+/Sy::ddownarrow {
+% 4 2 10 24 bbox
+begingate
+1.00 90 23 -1 Sy::dlarrow
+endgate
+} def
+
+/Sy::dlrarrow {
+% 2 11 28 10 bbox
+begingate
+1 1.00 20 21 30 16 20 11 3 polygon
+1.00 0 -1 2 Sy::dlarrow
+endgate
+} def
+
+/Sy::lparentop {
+% 6 -4 8 29 bbox
+begingate
+1 1.00 6 -4 6 11 7 19 10 25 14 29 5 polygon
+endgate
+} def
+
+/Sy::lparenbot {
+% 6 3 8 29 bbox
+begingate
+1.00 -181 0 32 Sy::lparentop
+endgate
+} def
+
+/Sy::lbracktop {
+% 6 -4 8 29 bbox
+begingate
+1 1.00 6 -4 6 29 14 29 3 polygon
+endgate
+} def
+
+/Sy::lbrackbot {
+% 6 3 8 29 bbox
+begingate
+1.00 -181 0 32 Sy::lbracktop
+endgate
+} def
+
+/Sy::lbracetop {
+% 6 -6 8 29 bbox
+begingate
+1 1.00 6 -6 6 24 7 27 10 29 14 29 5 polygon
+endgate
+} def
+
+/Sy::lvbrace {
+% 2 -8 4 36 bbox
+begingate
+1 1.00 6 36 6 15 4 13 2 12 4 11 6 9 6 -8 7 polygon
+endgate
+} def
+
+/Sy::lbracebot {
+% 6 3 8 36 bbox
+begingate
+1.00 -181 0 26 Sy::lbracetop
+endgate
+} def
+
+/Sy::inttop {
+% 9 -4 10 30 bbox
+begingate
+1 1.00 12 29 11 24 11 -4 9 -4 10 24 12 29 15 30 18 29 19 27 9 polygon
+1 1.00 18 26 1 0.00 360.00 xcarc
+endgate
+} def
+
+/Sy::vint {
+% 9 -4 2 36 bbox
+begingate
+240 1.00 9 -4 9 36 11 36 11 -4 4 polygon
+endgate
+} def
+
+/Sy::intbot {
+% 1 2 10 30 bbox
+begingate
+1.00 180 20 32 Sy::inttop
+endgate
+} def
+
+/Sy::lvbar {
+% 6 -8 0 36 bbox
+begingate
+1 1.00 6 -8 6 36 2 polygon
+endgate
+} def
+
+/Sy::rvbar {
+% -3 -4 28 36 bbox
+begingate
+1.00 0 5 0 Sy::lvbar
+endgate
+} def
+
+/Sy::rbracktop {
+% 3 -2 8 29 bbox
+begingate
+1.00 -1 17 0 Sy::lbracktop
+endgate
+} def
+
+/Sy::rbrackbot {
+% 3 3 8 29 bbox
+begingate
+1.00 180 17 32 Sy::lbracktop
+endgate
+} def
+
+/Sy::rbracetop {
+% 3 0 8 29 bbox
+begingate
+1.00 -1 12 0 Sy::lbracetop
+endgate
+} def
+
+/Sy::rvbrace {
+% -3 0 28 32 bbox
+begingate
+1.00 -1 12 0 Sy::lvbrace
+endgate
+} def
+
+/Sy::rbracebot {
+% 3 3 8 29 bbox
+begingate
+1.00 180 12 36 Sy::lbracetop
+endgate
+} def
+
+/Sy::rparentop {
+% 3 0 8 29 bbox
+begingate
+1.00 -1 17 0 Sy::lparentop
+endgate
+} def
+
+/Sy::rparenbot {
+% 3 3 8 29 bbox
+begingate
+1.00 180 17 32 Sy::lparentop
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/symbol.xfe b/lib/fonts/symbol.xfe
new file mode 100644
index 0000000..c8b22cd
--- /dev/null
+++ b/lib/fonts/symbol.xfe
@@ -0,0 +1,50 @@
+% XCircuit Font encoding (XFE) file
+name: Symbol
+file: symbol.lps
+family: Symbol
+weight: normal
+shape: normal
+type: PostScript
+encoding: Standard
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar
+Sy::space Sy::exclam Sy::forall Sy::pound Sy::every Sy::percent Sy::ampersand
+Sy::backe Sy::lparen Sy::rparen Sy::asterisk Sy::plus Sy::comma Sy::minus
+Sy::period Sy::slash Sy::zero Sy::one Sy::two Sy::three Sy::four Sy::five
+Sy::six Sy::seven Sy::eight Sy::nine Sy::colon Sy::semi Sy::less Sy::equal
+Sy::more Sy::question Sy::approx Sy::Alpha Sy::Beta Sy::Xi Sy::Delta
+Sy::Epsilon Sy::Phi Sy::Gamma Sy::Eta Sy::Iota Sy::altTheta Sy::Kappa
+Sy::Lambda Sy::Mu Sy::Nu Sy::Omicron Sy::Pi Sy::Theta Sy::Rho Sy::Sigma
+Sy::Tau Sy::GrY Sy::altSigma Sy::Omega Sy::Chi Sy::Psi Sy::Zeta Sy::lbracket
+Sy::therefore Sy::rbracket Sy::perp Sy::underscore Sy::upneg Sy::alpha
+Sy::beta Sy::chi Sy::delta Sy::epsilon Sy::phi Sy::gamma Sy::eta Sy::iota
+Sy::altphi Sy::kappa Sy::lambda Sy::mu Sy::nu Sy::omicron Sy::pi Sy::theta
+Sy::rho Sy::sigma Sy::tau Sy::upsilon Sy::altomega Sy::omega Sy::xi Sy::psi
+Sy::zeta Sy::lbrace Sy::vbar Sy::rbrace Sy::tilde
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::nullchar Sy::nullchar Sy::nullchar Sy::nullchar
+Sy::Upsilon Sy::prime Sy::leq Sy::aslash Sy::infty Sy::itf Sy::club
+Sy::diamond Sy::heart Sy::spade Sy::lrarrow Sy::larrow Sy::uarrow Sy::rarrow
+Sy::darrow Sy::degree Sy::pm Sy::dprime Sy::geq Sy::times Sy::prop Sy::deriv
+Sy::bullet Sy::div Sy::neq Sy::teq Sy::sim Sy::dots Sy::lvbar Sy::hbar
+Sy::return Sy::aleph Sy::Ifraktur Sy::Rfraktur Sy::weiers Sy::circmult
+Sy::circplus Sy::circslash Sy::intersect Sy::union Sy::propsup
+Sy::reflsup Sy::notsub Sy::propsub Sy::reflsub Sy::element Sy::notelement
+Sy::angle Sy::del Sy::rights Sy::copy Sy::trade Sy::product Sy::sqrt
+Sy::cdot Sy::lognot Sy::up Sy::down Sy::dlrarrow Sy::dlarrow Sy::duparrow
+Sy::drarrow Sy::ddownarrow Sy::lozenge Sy::lang Sy::rights Sy::copy
+Sy::trade Sy::sum Sy::lparentop Sy::lvbar Sy::lparenbot Sy::lbracktop
+Sy::lvbar Sy::lbrackbot Sy::lbracetop Sy::lvbrace Sy::lbracebot
+Sy::lvbar Sy::nullchar Sy::rang Sy::int Sy::inttop Sy::vint Sy::intbot
+Sy::rparentop Sy::rvbar Sy::rparenbot Sy::rbracktop Sy::rvbar Sy::rbrackbot
+Sy::rbracetop Sy::rvbrace Sy::rbracebot Sy::nullchar
+
+derived: Symbol-Oblique normal italic Special
diff --git a/lib/fonts/times_roman.lps b/lib/fonts/times_roman.lps
new file mode 100644
index 0000000..371f2ae
--- /dev/null
+++ b/lib/fonts/times_roman.lps
@@ -0,0 +1,1833 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: TR
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/TR::nullchar {
+% 0 0 24 32 bbox
+begingate
+0 1.00 0 0 0 32 24 32 24 0 4 polygon
+endgate
+} def
+
+/TR::space {
+% 0 0 14 26 bbox
+begingate
+endgate
+} def
+
+/TR::exclam {
+% 5 1 6 24 bbox
+begingate
+1 1.00 6 2 1 0.00 360.00 xcarc
+1 1.00 6 6 7 24 6 25 5 24 6 6 5 polygon
+endgate
+} def
+
+/TR::quote {
+% 6 23 9 7 bbox
+begingate
+0 1.00 8 30 8 28 8 23 7 28 6 30 5 polygon
+0 1.00 13 30 13 28 13 23 12 28 11 30 5 polygon
+endgate
+} def
+
+/TR::pound {
+% 5 0 18 26 bbox
+begingate
+1 1.00 5 18 21 18 2 polygon
+1 1.00 15 0 19 26 2 polygon
+1 1.00 7 0 11 26 2 polygon
+1 1.00 5 7 21 7 2 polygon
+endgate
+} def
+
+/TR::dollar {
+% 0 0 19 26 bbox
+begingate
+1 1.00 8 0 8 26 2 polygon
+1 1.00 0 8 0 5 5 2 10 2 14 4 16 6 16 8 14 10 2 16 0 18 0 20 2 22 6 24 11 24
+16 21 16 18 16 polygon
+endgate
+} def
+
+/TR::percent {
+% 4 0 22 26 bbox
+begingate
+1 1.00 18 0 16 2 16 6 18 8 20 8 22 6 22 2 20 0 18 0 9 polygon
+1 1.00 6 0 20 26 2 polygon
+1 1.00 6 18 4 20 4 24 6 26 8 26 10 24 10 20 8 18 6 18 9 polygon
+endgate
+} def
+
+/TR::ampersand {
+% 0 0 22 26 bbox
+begingate
+1 1.00 9 7 3 19 3 24 5 26 9 26 11 24 12 21 10 18 5 15 1 12 0 8 0 4 4 0 8 0
+12 3 14 6 16 10 17 polygon
+1 1.00 9 7 14 0 16 0 18 2 4 polygon
+1 1.00 13 10 18 10 2 polygon
+endgate
+} def
+
+/TR::apostrophe {
+% 6 24 8 8 bbox
+begingate
+241 1.00 9 28 7 28 6 30 7 32 9 32 10 30 9 28 7 polygon
+1 1.00 7 24 9 26 10 30 3 polygon
+endgate
+} def
+
+/TR::lparen {
+% 4 -5 7 32 bbox
+begingate
+1 1.00 10 -5 6 0 4 6 4 16 6 22 10 27 6 polygon
+endgate
+} def
+
+/TR::rparen {
+% 4 -5 8 32 bbox
+begingate
+1 1.00 4 -5 8 0 10 6 10 16 8 22 4 27 6 polygon
+endgate
+} def
+
+/TR::asterisk {
+% 4 12 14 12 bbox
+begingate
+1 1.00 8 12 8 20 2 polygon
+1 1.00 4 14 12 18 2 polygon
+1 1.00 4 18 12 14 2 polygon
+endgate
+} def
+
+/TR::plus {
+% 4 4 16 16 bbox
+begingate
+1 1.00 12 4 12 20 2 polygon
+1 1.00 4 12 20 12 2 polygon
+endgate
+} def
+
+/TR::comma {
+% 6 -4 4 8 bbox
+begingate
+1.00 0 0 -28 TR::apostrophe
+endgate
+} def
+
+/TR::minus {
+% 6 12 12 0 bbox
+begingate
+1 1.00 6 12 18 12 2 polygon
+endgate
+} def
+
+/TR::period {
+% 5 0 5 2 bbox
+begingate
+1 1.00 6 0 7 0 8 1 7 2 6 2 5 1 6 0 7 polygon
+endgate
+} def
+
+/TR::slash {
+% 4 0 10 26 bbox
+begingate
+1 1.00 4 0 14 26 2 polygon
+endgate
+} def
+
+/TR::zero {
+% 4 0 22 26 bbox
+begingate
+1 1.00 10 0 6 4 4 10 4 16 6 22 10 26 16 26 20 22 22 16 22 10 20 4 16 0 10 0
+13 polygon
+endgate
+} def
+
+/TR::one {
+% 4 0 12 26 bbox
+begingate
+1 1.00 8 0 8 26 4 22 3 polygon
+1 1.00 4 0 12 0 2 polygon
+endgate
+} def
+
+/TR::two {
+% 4 0 22 26 bbox
+begingate
+1 1.00 22 0 4 0 20 12 22 16 22 20 20 24 16 26 12 26 8 24 6 20 10 polygon
+1 1.00 22 0 24 4 2 polygon
+endgate
+} def
+
+/TR::three {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 3 7 1 10 0 14 0 18 2 20 6 19 11 16 14 13 13 9 polygon
+1 1.00 16 14 19 16 20 20 18 24 14 26 11 26 8 25 6 23 8 polygon
+endgate
+} def
+
+/TR::four {
+% 6 0 16 26 bbox
+begingate
+1 1.00 20 0 20 26 6 10 6 8 22 8 5 polygon
+endgate
+} def
+
+/TR::five {
+% 4 0 18 26 bbox
+begingate
+1 1.00 4 2 8 0 14 0 18 2 20 6 20 10 18 14 14 16 10 17 5 18 8 26 20 26
+12 polygon
+endgate
+} def
+
+/TR::six {
+% 4 0 20 26 bbox
+begingate
+1 1.00 18 26 14 26 10 24 6 20 4 16 4 8 5 4 10 0 15 0 19 2 22 6 22 11 20 15
+15 18 10 18 6 16 4 13 17 polygon
+endgate
+} def
+
+/TR::seven {
+% 4 0 18 26 bbox
+begingate
+1 1.00 8 0 20 26 6 26 3 polygon
+1 1.00 6 26 4 22 2 polygon
+endgate
+} def
+
+/TR::eight {
+% 5 0 19 26 bbox
+begingate
+1 1.00 10 0 7 1 5 4 5 8 8 12 18 16 20 19 20 22 16 26 10 26 6 22 6 19 8 16
+18 12 21 8 21 4 19 1 16 0 10 0 19 polygon
+endgate
+} def
+
+/TR::nine {
+% 0 0 20 26 bbox
+begingate
+1 1.00 6 0 10 1 13 3 16 6 17 10 18 18 16 24 12 26 6 26 2 24 0 20 0 15 2 11 6 9
+11 9 15 11 17 12 17 polygon
+endgate
+} def
+
+/TR::colon {
+% 9 0 4 14 bbox
+begingate
+1.00 0 4 14 TR::period
+1.00 0 4 0 TR::period
+endgate
+} def
+
+/TR::semi {
+% 8 -4 7 21 bbox
+begingate
+1.00 0 3 13 TR::period
+1.00 0 2 -28 TR::apostrophe
+endgate
+} def
+
+/TR::less {
+% 4 6 20 12 bbox
+begingate
+1 1.00 22 5 4 12 22 19 3 polygon
+endgate
+} def
+
+/TR::equal {
+% 4 10 16 4 bbox
+begingate
+1 1.00 4 9 18 9 2 polygon
+1 1.00 4 15 18 15 2 polygon
+endgate
+} def
+
+/TR::more {
+% 6 6 20 12 bbox
+begingate
+1 1.00 6 5 24 12 6 19 3 polygon
+endgate
+} def
+
+/TR::question {
+% 6 0 20 28 bbox
+begingate
+1 1.00 6 24 10 28 16 28 20 24 20 20 18 16 14 14 12 11 12 8 9 polygon
+1.00 0 5 0 TR::period
+endgate
+} def
+
+/TR::at {
+% 4 0 26 26 bbox
+begingate
+1 1.00 24 2 17 0 12 0 8 2 5 6 4 10 4 16 6 20 10 24 14 26 19 26 24 24 27 20
+28 16 27 12 25 8 23 6 20 5 18 8 22 20 20 polygon
+1 1.00 21 17 18 20 14 20 11 18 8 14 9 8 12 6 16 6 18 8 9 polygon
+endgate
+} def
+
+/TR::A {
+% 2 0 24 26 bbox
+begingate
+1 1.00 4 0 14 26 24 0 3 polygon
+1 1.00 8 8 20 8 2 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 20 0 26 0 2 polygon
+endgate
+} def
+
+/TR::B {
+% 4 0 23 26 bbox
+begingate
+1 1.00 8 0 8 26 2 polygon
+1 1.00 4 0 19 0 23 2 25 6 25 8 23 12 19 14 7 polygon
+1 1.00 4 26 16 26 21 24 23 20 23 18 19 14 8 14 7 polygon
+endgate
+} def
+
+/TR::C {
+% 4 0 22 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 23 23 9 polygon
+1 1.00 18 0 24 4 2 polygon
+1 1.00 23 26 24 21 2 polygon
+endgate
+} def
+
+/TR::D {
+% 4 0 24 26 bbox
+begingate
+1 1.00 4 0 18 0 24 4 26 10 26 16 24 22 18 26 4 26 8 polygon
+1 1.00 8 26 8 0 2 polygon
+endgate
+} def
+
+/TR::E {
+% 4 0 22 26 bbox
+begingate
+1 1.00 8 14 18 14 2 polygon
+1 1.00 8 0 8 26 2 polygon
+1 1.00 18 17 18 11 2 polygon
+1 1.00 24 4 22 0 4 0 3 polygon
+1 1.00 4 26 22 26 24 24 3 polygon
+endgate
+} def
+
+/TR::F {
+% 6 0 19 26 bbox
+begingate
+1 1.00 10 0 10 26 2 polygon
+1 1.00 10 14 18 14 2 polygon
+1 1.00 6 26 22 26 2 polygon
+1 1.00 18 17 18 11 2 polygon
+1 1.00 6 0 14 0 2 polygon
+1 1.00 22 26 23 23 2 polygon
+endgate
+} def
+
+/TR::G {
+% 4 0 25 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 23 9 polygon
+1 1.00 24 26 25 20 2 polygon
+1 1.00 27 12 21 12 2 polygon
+1 1.00 18 0 24 4 2 polygon
+1 1.00 24 4 24 12 2 polygon
+endgate
+} def
+
+/TR::H {
+% 4 0 20 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 20 0 20 26 2 polygon
+1 1.00 6 14 20 14 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 16 26 22 26 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 16 0 22 0 2 polygon
+endgate
+} def
+
+/TR::I {
+% 4 0 6 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 0 8 0 2 polygon
+1 1.00 4 26 8 26 2 polygon
+endgate
+} def
+
+/TR::J {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 4 5 2 8 0 11 0 13 2 15 6 15 26 7 polygon
+1 1.00 12 26 18 26 2 polygon
+endgate
+} def
+
+/TR::K {
+% 4 0 22 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 22 26 6 10 2 polygon
+1 1.00 22 0 9 13 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 18 26 24 26 2 polygon
+1 1.00 18 0 24 0 2 polygon
+endgate
+} def
+
+/TR::L {
+% 4 0 16 26 bbox
+begingate
+1 1.00 6 26 6 0 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 4 0 18 0 2 polygon
+1 1.00 18 0 20 4 2 polygon
+endgate
+} def
+
+/TR::M {
+% 4 0 30 26 bbox
+begingate
+1 1.00 6 0 6 26 18 0 30 26 30 0 5 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 26 0 32 0 2 polygon
+1 1.00 30 26 32 26 2 polygon
+1 1.00 6 26 4 26 2 polygon
+endgate
+} def
+
+/TR::N {
+% 4 0 26 26 bbox
+begingate
+1 1.00 6 0 6 26 26 0 26 26 4 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 28 26 22 26 2 polygon
+1 1.00 6 26 4 26 2 polygon
+endgate
+} def
+
+/TR::O {
+% 4 0 24 26 bbox
+begingate
+1 1.00 18 0 12 0 6 4 4 10 4 16 6 22 12 26 18 26 24 22 9 polygon
+1 1.00 18 0 24 4 26 10 26 16 24 22 5 polygon
+endgate
+} def
+
+/TR::P {
+% 4 0 18 26 bbox
+begingate
+1 1.00 6 0 6 26 2 polygon
+1 1.00 4 26 16 26 20 24 22 21 22 17 20 14 16 12 6 12 8 polygon
+1 1.00 4 0 10 0 2 polygon
+endgate
+} def
+
+/TR::Q {
+% 6 -4 24 30 bbox
+begingate
+1 1.00 19 0 23 -3 27 -4 3 polygon
+1.00 0 2 0 TR::O
+endgate
+} def
+
+/TR::R {
+% 4 0 23 26 bbox
+begingate
+1.00 0 0 0 TR::P
+1 1.00 14 12 24 0 26 0 3 polygon
+endgate
+} def
+
+/TR::S {
+% 3 0 20 26 bbox
+begingate
+1 1.00 4 4 6 2 10 0 16 0 20 2 22 5 22 8 18 12 7 16 4 19 4 22 6 24 10 26 16 26
+20 24 15 polygon
+1 1.00 20 26 21 22 2 polygon
+1 1.00 3 7 4 1 2 polygon
+endgate
+} def
+
+/TR::T {
+% 5 0 20 26 bbox
+begingate
+1 1.00 14 0 14 26 2 polygon
+1 1.00 5 23 6 26 22 26 23 23 4 polygon
+1 1.00 11 0 17 0 2 polygon
+endgate
+} def
+
+/TR::U {
+% 4 0 26 26 bbox
+begingate
+1 1.00 6 26 6 8 8 4 10 2 14 0 19 0 23 2 25 4 27 8 27 26 10 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 24 26 30 26 2 polygon
+endgate
+} def
+
+/TR::V {
+% 4 0 28 26 bbox
+begingate
+1 1.00 6 26 17 0 28 26 3 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 30 26 24 26 2 polygon
+endgate
+} def
+
+/TR::W {
+% 4 0 36 26 bbox
+begingate
+1 1.00 6 26 14 0 21 22 3 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 38 26 32 26 2 polygon
+1 1.00 20 26 28 0 36 26 3 polygon
+1 1.00 16 26 24 26 2 polygon
+endgate
+} def
+
+/TR::X {
+% 4 0 26 26 bbox
+begingate
+1 1.00 6 0 26 26 2 polygon
+1 1.00 6 26 26 0 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 22 26 28 26 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 22 0 28 0 2 polygon
+endgate
+} def
+
+/TR::Y {
+% 4 0 26 26 bbox
+begingate
+1 1.00 6 26 16 12 16 0 3 polygon
+1 1.00 26 26 16 12 2 polygon
+1 1.00 4 26 10 26 2 polygon
+1 1.00 22 26 28 26 2 polygon
+1 1.00 13 0 19 0 2 polygon
+endgate
+} def
+
+/TR::Z {
+% 5 0 20 26 bbox
+begingate
+1 1.00 7 26 24 26 6 0 23 0 4 polygon
+1 1.00 23 0 25 4 2 polygon
+1 1.00 7 26 5 22 2 polygon
+endgate
+} def
+
+/TR::lbracket {
+% 4 -2 6 30 bbox
+begingate
+1 1.00 10 -2 4 -2 4 28 10 28 4 polygon
+endgate
+} def
+
+/TR::backslash {
+% 4 0 10 26 bbox
+begingate
+1 1.00 14 0 4 26 2 polygon
+endgate
+} def
+
+/TR::rbracket {
+% 4 -2 9 30 bbox
+begingate
+1 1.00 4 -2 10 -2 10 28 4 28 4 polygon
+endgate
+} def
+
+/TR::caret {
+% 4 20 12 6 bbox
+begingate
+1 1.00 4 20 10 26 16 20 3 polygon
+endgate
+} def
+
+/TR::underscore {
+% 4 0 20 0 bbox
+begingate
+1 1.00 4 0 24 0 2 polygon
+endgate
+} def
+
+/TR::a {
+% 2 0 15 16 bbox
+begingate
+1 1.00 16 0 14 2 14 14 11 16 7 16 4 14 6 polygon
+1 1.00 14 2 12 0 6 0 3 2 2 6 6 9 14 11 7 polygon
+1 1.00 16 0 18 1 2 polygon
+endgate
+} def
+
+/TR::b {
+% 2 0 19 26 bbox
+begingate
+1 1.00 5 2 5 26 2 polygon
+1 1.00 5 2 9 0 13 0 16 2 18 6 18 10 16 14 13 16 9 16 5 14 10 polygon
+1 1.00 2 25 5 26 2 polygon
+endgate
+} def
+
+/TR::c {
+% 3 0 15 16 bbox
+begingate
+1 1.00 17 2 13 0 9 0 5 2 3 6 3 10 5 14 9 16 13 16 16 13 15 12 11 polygon
+endgate
+} def
+
+/TR::d {
+% 3 0 17 26 bbox
+begingate
+1 1.00 16 2 12 0 8 0 5 2 3 6 3 10 5 14 8 16 12 16 16 12 10 polygon
+1 1.00 19 1 16 0 16 26 13 25 4 polygon
+endgate
+} def
+
+/TR::e {
+% 3 0 16 16 bbox
+begingate
+1 1.00 18 5 16 2 13 0 9 0 5 2 3 6 3 10 5 14 9 16 12 16 16 14 18 10 4 10
+13 polygon
+endgate
+} def
+
+/TR::f {
+% 2 0 12 26 bbox
+begingate
+1 1.00 6 0 6 23 8 26 11 26 13 24 5 polygon
+1 1.00 2 18 10 18 2 polygon
+1 1.00 4 0 8 0 2 polygon
+endgate
+} def
+
+/TR::g {
+% 3 -8 18 24 bbox
+begingate
+1 1.00 8 5 13 5 16 7 16 11 13 15 9 16 6 15 3 12 3 8 8 5 6 3 15 1 20 -1 20 -5
+13 -8 7 -8 3 -5 3 -2 4 0 8 2 20 polygon
+1 1.00 15 13 17 13 20 15 3 polygon
+endgate
+} def
+
+/TR::h {
+% 2 0 18 26 bbox
+begingate
+1 1.00 5 0 5 26 2 polygon
+1 1.00 5 13 9 16 13 16 16 14 17 10 17 0 6 polygon
+1 1.00 2 24 5 26 2 polygon
+1 1.00 3 0 8 0 2 polygon
+1 1.00 14 0 19 0 2 polygon
+endgate
+} def
+
+/TR::i {
+% 3 0 7 22 bbox
+begingate
+1 1.00 5 0 5 16 3 14 3 polygon
+1 1.00 5 21 5 22 2 polygon
+1 1.00 3 0 7 0 2 polygon
+endgate
+} def
+
+/TR::j {
+% 0 -6 7 28 bbox
+begingate
+1 1.00 0 -5 2 -6 4 -6 6 -4 6 16 4 14 6 polygon
+1 1.00 6 21 6 22 2 polygon
+endgate
+} def
+
+/TR::k {
+% 2 0 18 26 bbox
+begingate
+1 1.00 5 0 5 26 2 polygon
+1 1.00 5 8 16 16 2 polygon
+1 1.00 17 0 9 10 2 polygon
+1 1.00 2 24 5 26 2 polygon
+1 1.00 3 0 8 0 2 polygon
+1 1.00 14 0 19 0 2 polygon
+1 1.00 13 16 19 16 2 polygon
+endgate
+} def
+
+/TR::l {
+% 4 0 5 26 bbox
+begingate
+1 1.00 6 0 6 26 4 24 3 polygon
+1 1.00 4 0 8 0 2 polygon
+endgate
+} def
+
+/TR::m {
+% 2 0 26 16 bbox
+begingate
+1 1.00 5 0 5 16 2 polygon
+1 1.00 5 14 8 16 12 16 15 13 15 0 5 polygon
+1 1.00 15 14 18 16 22 16 25 13 25 0 5 polygon
+1 1.00 2 14 5 16 2 polygon
+1 1.00 3 0 8 0 2 polygon
+1 1.00 12 0 18 0 2 polygon
+1 1.00 22 0 27 0 2 polygon
+endgate
+} def
+
+/TR::n {
+% 2 0 17 16 bbox
+begingate
+1 1.00 5 0 5 16 2 polygon
+1 1.00 5 13 8 15 11 16 14 15 16 12 16 0 6 polygon
+1 1.00 2 14 5 16 2 polygon
+1 1.00 3 0 8 0 2 polygon
+1 1.00 13 0 18 0 2 polygon
+endgate
+} def
+
+/TR::o {
+% 2 0 15 16 bbox
+begingate
+1 1.00 8 0 4 2 2 6 2 10 4 14 8 16 10 16 14 14 16 10 16 6 14 2 10 0 8 0
+13 polygon
+endgate
+} def
+
+/TR::p {
+% 2 -6 19 22 bbox
+begingate
+1 1.00 5 2 9 0 13 0 16 2 18 6 18 11 16 14 13 16 9 16 5 14 10 polygon
+1 1.00 5 16 5 -6 2 polygon
+1 1.00 2 14 5 16 2 polygon
+1 1.00 3 -6 8 -6 2 polygon
+endgate
+} def
+
+/TR::q {
+% 2 -6 16 22 bbox
+begingate
+1 1.00 15 2 11 0 7 0 4 2 2 6 2 10 4 14 7 16 11 16 15 14 10 polygon
+1 1.00 15 16 15 -6 2 polygon
+1 1.00 17 -6 12 -6 2 polygon
+endgate
+} def
+
+/TR::r {
+% 2 0 14 16 bbox
+begingate
+1 1.00 5 0 5 16 2 polygon
+1 1.00 5 14 9 16 13 16 15 14 4 polygon
+1 1.00 2 14 5 16 2 polygon
+1 1.00 3 0 8 0 2 polygon
+endgate
+} def
+
+/TR::s {
+% 2 0 15 16 bbox
+begingate
+1 1.00 3 2 6 0 12 0 16 2 16 5 13 8 5 9 3 11 3 14 6 16 12 16 15 14 12 polygon
+1 1.00 15 16 16 13 2 polygon
+1 1.00 2 4 3 0 2 polygon
+endgate
+} def
+
+/TR::t {
+% 2 0 10 24 bbox
+begingate
+1 1.00 2 18 10 18 2 polygon
+1 1.00 6 24 6 2 8 0 11 2 4 polygon
+1 1.00 2 18 4 19 6 21 3 polygon
+endgate
+} def
+
+/TR::u {
+% 2 0 18 16 bbox
+begingate
+1 1.00 5 16 5 4 7 1 10 0 13 0 16 2 6 polygon
+1 1.00 16 0 16 16 2 polygon
+1 1.00 16 0 19 2 2 polygon
+1 1.00 16 16 13 16 2 polygon
+1 1.00 5 16 2 16 2 polygon
+endgate
+} def
+
+/TR::v {
+% 2 0 20 16 bbox
+begingate
+1 1.00 4 16 11 0 19 16 3 polygon
+1 1.00 2 16 8 16 2 polygon
+1 1.00 15 16 21 16 2 polygon
+endgate
+} def
+
+/TR::w {
+% 2 0 27 16 bbox
+begingate
+1 1.00 4 16 10 0 15 12 3 polygon
+1 1.00 2 16 8 16 2 polygon
+1 1.00 14 16 20 0 26 16 3 polygon
+1 1.00 28 16 22 16 2 polygon
+1 1.00 12 16 18 16 2 polygon
+endgate
+} def
+
+/TR::x {
+% 2 0 19 16 bbox
+begingate
+1 1.00 4 0 18 16 2 polygon
+1 1.00 4 16 18 0 2 polygon
+1 1.00 2 16 8 16 2 polygon
+1 1.00 14 16 20 16 2 polygon
+1 1.00 2 0 8 0 2 polygon
+1 1.00 14 0 20 0 2 polygon
+endgate
+} def
+
+/TR::y {
+% 2 -6 19 22 bbox
+begingate
+1 1.00 4 16 12 1 2 polygon
+1 1.00 18 16 10 -4 7 -6 4 -6 4 polygon
+1 1.00 2 16 8 16 2 polygon
+1 1.00 14 16 20 16 2 polygon
+endgate
+} def
+
+/TR::z {
+% 2 0 15 16 bbox
+begingate
+1 1.00 3 16 16 16 2 0 15 0 4 polygon
+1 1.00 3 16 2 13 2 polygon
+1 1.00 15 0 16 3 2 polygon
+endgate
+} def
+
+/TR::lbrace {
+% 6 -4 9 32 bbox
+begingate
+1 1.00 12 -4 10 -3 8 0 8 10 6 12 8 14 8 24 10 27 12 28 9 polygon
+endgate
+} def
+
+/TR::vbar {
+% 6 -2 5 30 bbox
+begingate
+1 1.00 6 -2 6 28 2 polygon
+endgate
+} def
+
+/TR::rbrace {
+% 4 -4 9 32 bbox
+begingate
+1 1.00 4 -4 6 -3 8 0 8 10 10 12 8 14 8 24 6 27 4 28 9 polygon
+endgate
+} def
+
+/TR::tilde {
+% 4 12 18 2 bbox
+begingate
+1 1.00 4 12 6 14 10 14 14 12 18 12 20 14 6 polygon
+endgate
+} def
+
+/TR::upexclam {
+% 7 1 6 24 bbox
+begingate
+1.00 -181 2 26 TR::exclam
+endgate
+} def
+
+/TR::cent {
+% 6 -6 16 28 bbox
+begingate
+1 1.00 6 -6 20 22 2 polygon
+1.00 0 2 0 TR::c
+endgate
+} def
+
+/TR::lb {
+% 4 0 18 26 bbox
+begingate
+1 1.00 22 2 20 0 18 0 8 4 6 4 4 2 6 0 8 0 12 6 12 10 10 20 10 22 12 26 16 26
+20 24 15 polygon
+1 1.00 5 14 17 14 2 polygon
+endgate
+} def
+
+/TR::aslash {
+% 4 0 14 26 bbox
+begingate
+1 1.00 4 0 18 26 2 polygon
+endgate
+} def
+
+/TR::yen {
+% 6 0 24 26 bbox
+begingate
+1.00 0 2 0 TR::Y
+1 1.00 9 13 27 13 2 polygon
+1 1.00 9 18 27 18 2 polygon
+endgate
+} def
+
+/TR::itf {
+% 2 -6 16 32 bbox
+begingate
+1 1.00 2 -5 6 -6 8 -4 12 24 14 26 16 25 6 polygon
+1 1.00 8 18 14 18 2 polygon
+endgate
+} def
+
+/TR::sy1 {
+% 4 -6 15 32 bbox
+begingate
+1 1.00 4 -2 6 -6 10 -6 14 -3 14 0 6 7 4 11 4 14 8 18 9 polygon
+1 1.00 12 2 16 6 16 9 14 13 6 20 6 23 10 26 14 26 16 22 9 polygon
+endgate
+} def
+
+/TR::sy2 {
+% 5 0 16 16 bbox
+begingate
+1 1.00 13 8 8 0.00 360.00 xcarc
+1 1.00 5 0 7 2 2 polygon
+1 1.00 19 14 21 16 2 polygon
+1 1.00 5 16 7 14 2 polygon
+1 1.00 19 2 21 0 2 polygon
+endgate
+} def
+
+/TR::apos2 {
+% 9 24 2 8 bbox
+begingate
+0 1.00 9 32 9 28 10 24 11 28 11 32 5 polygon
+endgate
+} def
+
+/TR::lqt {
+% 7 22 14 8 bbox
+begingate
+1.00 180 17 54 TR::apostrophe
+1.00 180 24 54 TR::apostrophe
+endgate
+} def
+
+/TR::lgqt {
+% 4 4 16 14 bbox
+begingate
+1 1.00 10 4 4 11 10 18 3 polygon
+1 1.00 16 4 10 11 16 18 3 polygon
+endgate
+} def
+
+/TR::lsang {
+% 4 4 10 14 bbox
+begingate
+1 1.00 10 4 4 11 10 18 3 polygon
+endgate
+} def
+
+/TR::rsang {
+% 6 4 10 14 bbox
+begingate
+1 1.00 6 4 12 11 6 18 3 polygon
+endgate
+} def
+
+/TR::fi {
+% 4 0 17 26 bbox
+begingate
+1 1.00 8 0 8 24 10 26 14 26 4 polygon
+1 1.00 4 18 16 18 16 0 3 polygon
+1 1.00 14 26 18 24 2 polygon
+1 1.00 4 0 10 0 2 polygon
+1 1.00 14 0 18 0 2 polygon
+endgate
+} def
+
+/TR::fl {
+% 4 0 19 26 bbox
+begingate
+1 1.00 4 18 18 18 2 polygon
+1 1.00 8 0 8 24 10 26 14 26 18 24 5 polygon
+1 1.00 6 0 12 0 2 polygon
+1 1.00 18 26 18 0 2 polygon
+1 1.00 16 0 20 0 2 polygon
+endgate
+} def
+
+/TR::dag {
+% 5 2 11 22 bbox
+begingate
+241 1.00 9 24 10 23 9 22 9 20 11 20 12 21 13 20 12 19 11 20 9 20 9 18 10 17
+9 16 8 17 9 18 9 20 7 20 6 19 5 20 6 21 7 20 9 20 9 22 8 23 9 24 25 polygon
+1 1.00 9 17 9 2 2 polygon
+endgate
+} def
+
+/TR::ddag {
+% 5 0 13 24 bbox
+begingate
+1 1.00 7 4 6 5 5 4 6 3 7 4 10 4 10 2 9 1 10 0 11 1 10 2 10 4 13 4 14 3 15 4
+14 5 13 4 10 4 10 11 19 polygon
+1 1.00 7 20 6 19 5 20 6 21 7 20 10 20 10 22 9 23 10 24 11 23 10 22 10 20 13 20
+14 21 15 20 14 19 13 20 10 20 10 13 19 polygon
+endgate
+} def
+
+/TR::dot {
+% 8 25 2 2 bbox
+begingate
+1 1.00 9 25 10 26 9 27 8 26 9 25 5 polygon
+endgate
+} def
+
+/TR::para {
+% 5 0 15 26 bbox
+begingate
+1 1.00 14 0 14 26 2 polygon
+1 1.00 18 0 18 26 2 polygon
+240 1.00 11 20 6 90.00 270.00 xcarc
+1 1.00 14 26 20 26 2 polygon
+240 1.00 11 14 11 26 14 26 14 14 4 polygon
+endgate
+} def
+
+/TR::bullet {
+% 5 6 8 8 bbox
+begingate
+241 1.00 9 10 4 0.00 360.00 xcarc
+endgate
+} def
+
+/TR::comma2 {
+% 6 -4 7 8 bbox
+begingate
+1.00 0 0 -28 TR::apostrophe
+endgate
+} def
+
+/TR::rqt2 {
+% 5 -3 15 8 bbox
+begingate
+1.00 0 -1 -27 TR::apostrophe
+1.00 0 6 -27 TR::apostrophe
+endgate
+} def
+
+/TR::rqt {
+% 5 20 15 8 bbox
+begingate
+1.00 0 -1 -4 TR::apostrophe
+1.00 0 6 -4 TR::apostrophe
+endgate
+} def
+
+/TR::rgqt {
+% 6 4 16 14 bbox
+begingate
+1 1.00 6 4 12 11 6 18 3 polygon
+1 1.00 12 4 18 11 12 18 3 polygon
+endgate
+} def
+
+/TR::dots {
+% 5 0 30 2 bbox
+begingate
+1.00 0 0 0 TR::period
+1.00 0 12 0 TR::period
+1.00 0 24 0 TR::period
+endgate
+} def
+
+/TR::perzer {
+% 8 0 32 26 bbox
+begingate
+1 1.00 31 0 29 2 29 6 31 8 33 8 35 6 35 2 33 0 31 0 9 polygon
+1.00 0 4 0 TR::percent
+endgate
+} def
+
+/TR::uqest {
+% 8 0 16 28 bbox
+begingate
+1.00 180 28 28 TR::question
+endgate
+} def
+
+/TR::grave {
+% 8 26 4 6 bbox
+begingate
+0 1.00 8 32 12 26 10 32 3 polygon
+endgate
+} def
+
+/TR::acute {
+% 10 26 4 6 bbox
+begingate
+1.00 -1 22 0 TR::grave
+endgate
+} def
+
+/TR::hat {
+% 6 28 8 4 bbox
+begingate
+1 1.00 6 28 10 32 14 28 3 polygon
+endgate
+} def
+
+/TR::tilchar {
+% 6 29 8 3 bbox
+begingate
+1 1.00 6 29 8 32 9 32 11 29 12 29 14 32 6 polygon
+endgate
+} def
+
+/TR::bar {
+% 6 30 8 0 bbox
+begingate
+1 1.00 6 30 14 30 2 polygon
+endgate
+} def
+
+/TR::uu {
+% 6 29 10 3 bbox
+begingate
+1 1.00 6 32 7 30 10 29 12 29 15 30 16 32 6 polygon
+endgate
+} def
+
+/TR::umlaut {
+% 5 29 10 2 bbox
+begingate
+1.00 0 0 29 TR::period
+1.00 0 7 29 TR::period
+endgate
+} def
+
+/TR::circ {
+% 7 25 6 6 bbox
+begingate
+1 1.00 10 28 3 0.00 360.00 xcarc
+endgate
+} def
+
+/TR::cedilla {
+% 8 -6 4 6 bbox
+begingate
+1 1.00 10 0 8 -2 12 -4 10 -6 4 polygon
+endgate
+} def
+
+/TR::uml2 {
+% 6 26 10 6 bbox
+begingate
+1.00 0 -4 0 TR::acute
+1.00 0 2 0 TR::acute
+endgate
+} def
+
+/TR::ced2 {
+% 7 -5 5 5 bbox
+begingate
+1 1.00 8 0 7 -3 10 -5 12 -4 4 polygon
+endgate
+} def
+
+/TR::vee {
+% 6 28 8 4 bbox
+begingate
+1 1.00 6 32 10 28 14 32 3 polygon
+endgate
+} def
+
+/TR::Oslash {
+% 4 0 22 26 bbox
+begingate
+1 1.00 4 0 24 26 2 polygon
+1.00 0 0 0 TR::O
+endgate
+} def
+
+/TR::osl {
+% 4 0 14 16 bbox
+begingate
+1 1.00 4 0 18 16 2 polygon
+1.00 0 0 0 TR::o
+endgate
+} def
+
+/TR::sset {
+% 4 0 16 26 bbox
+begingate
+1 1.00 4 0 6 0 6 22 8 25 12 26 15 26 18 23 18 20 16 18 12 16 16 14 19 11 20 8
+20 3 16 0 11 0 9 2 17 polygon
+endgate
+} def
+
+/TR::Agrave {
+% 4 0 24 34 bbox
+begingate
+1.00 0 2 0 TR::A
+1.00 0 6 2 TR::grave
+endgate
+} def
+
+/TR::Aacute {
+% 4 0 24 34 bbox
+begingate
+1.00 0 2 0 TR::A
+1.00 0 4 2 TR::acute
+endgate
+} def
+
+/TR::Acircum {
+% 4 0 24 32 bbox
+begingate
+1.00 0 2 0 TR::A
+1.00 0 6 0 TR::hat
+endgate
+} def
+
+/TR::Atilde {
+% 6 0 24 32 bbox
+begingate
+1.00 0 4 0 TR::A
+1.00 0 8 0 TR::tilchar
+endgate
+} def
+
+/TR::Adier {
+% 4 0 24 31 bbox
+begingate
+1.00 0 2 0 TR::A
+1.00 0 6 0 TR::umlaut
+endgate
+} def
+
+/TR::Aring {
+% 2 0 24 34 bbox
+begingate
+1.00 0 0 0 TR::A
+1.00 0 4 3 TR::circ
+endgate
+} def
+
+/TR::Egrave {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 2 2 TR::grave
+endgate
+} def
+
+/TR::Eacute {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 2 2 TR::acute
+endgate
+} def
+
+/TR::Ecircum {
+% 4 0 20 34 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 4 2 TR::hat
+endgate
+} def
+
+/TR::Edier {
+% 4 0 20 31 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 4 0 TR::umlaut
+endgate
+} def
+
+/TR::Ccedil {
+% 4 -6 20 32 bbox
+begingate
+1.00 0 0 0 TR::C
+1.00 0 3 0 TR::cedilla
+endgate
+} def
+
+/TR::Igrave {
+% 6 0 4 34 bbox
+begingate
+1.00 0 2 0 TR::I
+1.00 0 -2 2 TR::grave
+endgate
+} def
+
+/TR::Iacute {
+% 6 0 4 34 bbox
+begingate
+1.00 0 2 0 TR::I
+1.00 0 -4 2 TR::acute
+endgate
+} def
+
+/TR::Icircum {
+% 4 0 8 34 bbox
+begingate
+1.00 0 2 0 TR::I
+1.00 0 -2 2 TR::hat
+endgate
+} def
+
+/TR::Idier {
+% 3 0 10 31 bbox
+begingate
+1.00 0 2 0 TR::I
+1.00 0 -2 0 TR::umlaut
+endgate
+} def
+
+/TR::Otilde {
+% 4 0 22 32 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 6 0 TR::tilchar
+endgate
+} def
+
+/TR::Ugrave {
+% 4 0 26 32 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 6 0 TR::grave
+endgate
+} def
+
+/TR::Uacute {
+% 4 0 26 32 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 6 0 TR::acute
+endgate
+} def
+
+/TR::Ucircum {
+% 4 0 26 33 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 7 1 TR::hat
+endgate
+} def
+
+/TR::Udier {
+% 4 0 26 31 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 7 0 TR::umlaut
+endgate
+} def
+
+/TR::Ograve {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 4 2 TR::grave
+endgate
+} def
+
+/TR::Oacute {
+% 4 0 22 35 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 3 3 TR::acute
+endgate
+} def
+
+/TR::Ocircum {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 5 2 TR::hat
+endgate
+} def
+
+/TR::Odier {
+% 4 0 22 32 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 5 1 TR::umlaut
+endgate
+} def
+
+/TR::Ntilde {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 TR::N
+1.00 0 4 0 TR::tilchar
+endgate
+} def
+
+/TR::AE {
+% 4 0 36 26 bbox
+begingate
+1.00 0 16 0 TR::E
+1 1.00 24 26 8 0 2 polygon
+1 1.00 24 10 15 10 2 polygon
+1 1.00 4 0 12 0 2 polygon
+endgate
+} def
+
+/TR::Eth {
+% 4 0 22 26 bbox
+begingate
+1.00 0 0 0 TR::D
+1 1.00 12 14 4 14 2 polygon
+endgate
+} def
+
+/TR::Yacute {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 TR::Y
+1.00 0 4 0 TR::acute
+endgate
+} def
+
+/TR::agrave {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 0 -8 TR::grave
+endgate
+} def
+
+/TR::aacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 -2 -8 TR::acute
+endgate
+} def
+
+/TR::acircum {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 0 -8 TR::hat
+endgate
+} def
+
+/TR::atilde {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 0 -8 TR::tilchar
+endgate
+} def
+
+/TR::adier {
+% 4 0 16 23 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 0 -8 TR::umlaut
+endgate
+} def
+
+/TR::aring {
+% 4 0 16 27 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 0 -4 TR::circ
+endgate
+} def
+
+/TR::ntilde {
+% 3 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::n
+1.00 0 0 -8 TR::tilchar
+endgate
+} def
+
+/TR::egrave {
+% 4 0 15 24 bbox
+begingate
+1.00 0 0 0 TR::e
+1.00 0 0 -8 TR::grave
+endgate
+} def
+
+/TR::eacute {
+% 4 0 15 24 bbox
+begingate
+1.00 0 0 0 TR::e
+1.00 0 -2 -8 TR::acute
+endgate
+} def
+
+/TR::ecircum {
+% 4 0 15 24 bbox
+begingate
+1.00 0 0 0 TR::e
+1.00 0 0 -8 TR::hat
+endgate
+} def
+
+/TR::edier {
+% 4 0 15 23 bbox
+begingate
+1.00 0 0 0 TR::e
+1.00 0 0 -8 TR::umlaut
+endgate
+} def
+
+/TR::ae {
+% 5 0 26 16 bbox
+begingate
+1.00 0 12 0 TR::e
+1 1.00 18 2 14 0 8 0 5 2 5 6 8 9 16 10 7 polygon
+1 1.00 6 14 8 16 14 16 17 13 4 polygon
+endgate
+} def
+
+/TR::igrave {
+% 4 0 6 26 bbox
+begingate
+1.00 0 -4 -6 TR::grave
+1 1.00 6 0 10 0 2 polygon
+1 1.00 6 14 8 16 8 0 3 polygon
+endgate
+} def
+
+/TR::iacute {
+% 6 0 6 26 bbox
+begingate
+1.00 0 -2 -6 TR::acute
+1 1.00 8 0 8 16 6 14 3 polygon
+1 1.00 6 0 10 0 2 polygon
+endgate
+} def
+
+/TR::icircum {
+% 4 0 8 24 bbox
+begingate
+1.00 0 -2 -8 TR::hat
+1 1.00 6 14 8 16 8 0 3 polygon
+1 1.00 6 0 10 0 2 polygon
+endgate
+} def
+
+/TR::idier {
+% 5 0 10 23 bbox
+begingate
+1.00 0 0 -8 TR::umlaut
+1 1.00 8 14 10 16 10 0 3 polygon
+1 1.00 8 0 12 0 2 polygon
+endgate
+} def
+
+/TR::ydier {
+% 6 -6 18 29 bbox
+begingate
+1.00 0 0 0 TR::y
+1.00 0 2 -8 TR::umlaut
+endgate
+} def
+
+/TR::yacute {
+% 6 -6 18 30 bbox
+begingate
+1.00 0 0 0 TR::y
+1.00 0 2 -8 TR::acute
+endgate
+} def
+
+/TR::ograve {
+% 4 0 14 24 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 -2 -8 TR::grave
+endgate
+} def
+
+/TR::oacute {
+% 4 0 14 24 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 -2 -8 TR::acute
+endgate
+} def
+
+/TR::ocircum {
+% 4 0 14 24 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 -1 -8 TR::hat
+endgate
+} def
+
+/TR::otilde {
+% 4 0 14 23 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 -1 -9 TR::tilchar
+endgate
+} def
+
+/TR::odier {
+% 4 0 14 21 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 -1 -10 TR::umlaut
+endgate
+} def
+
+/TR::eth {
+% 4 0 14 24 bbox
+begingate
+1.00 0 0 0 TR::o
+1 1.00 14 14 8 22 2 24 3 polygon
+1 1.00 10 24 4 20 2 polygon
+endgate
+} def
+
+/TR::ugrave {
+% 4 0 17 24 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 -2 -8 TR::grave
+endgate
+} def
+
+/TR::uacute {
+% 4 0 17 24 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 -2 -8 TR::acute
+endgate
+} def
+
+/TR::ucircum {
+% 4 0 17 24 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 0 -8 TR::hat
+endgate
+} def
+
+/TR::udier {
+% 4 0 17 23 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 0 -8 TR::umlaut
+endgate
+} def
+
+/TR::ccedil {
+% 4 -6 14 22 bbox
+begingate
+1.00 0 0 0 TR::cedilla
+1.00 0 0 0 TR::c
+endgate
+} def
+
+/TR::ordfem {
+% 6 20 11 9 bbox
+begingate
+0.60 0 4 20 TR::a
+endgate
+} def
+
+/TR::Lslash {
+% 4 0 24 26 bbox
+begingate
+1.00 0 4 0 TR::L
+1 1.00 16 20 4 12 2 polygon
+endgate
+} def
+
+/TR::ordmasc {
+% 4 18 10 9 bbox
+begingate
+0.60 0 2 18 TR::o
+endgate
+} def
+
+/TR::lslash {
+% 9 0 9 26 bbox
+begingate
+1.00 0 6 0 TR::l
+1 1.00 15 16 9 12 2 polygon
+endgate
+} def
+
+/TR::OE {
+% 6 0 32 26 bbox
+begingate
+1 1.00 38 0 24 0 24 26 38 26 4 polygon
+1 1.00 36 14 24 14 2 polygon
+1.00 0 2 0 TR::zero
+endgate
+} def
+
+/TR::oe {
+% 8 0 32 16 bbox
+begingate
+1.00 0 18 0 TR::e
+1.00 0 4 0 TR::o
+endgate
+} def
+
+/TR::emdash {
+% 2 10 32 0 bbox
+begingate
+1 1.00 2 10 34 10 2 polygon
+endgate
+} def
+
+/TR::pm {
+% 6 6 12 15 bbox
+begingate
+1.00 0 2 3 TR::plus
+1.00 0 2 -6 TR::minus
+endgate
+} def
+
+/TR::onesup {
+% 7 18 3 15 bbox
+begingate
+0.60 0 4 18 TR::one
+endgate
+} def
+
+/TR::twosup {
+% 4 18 11 15 bbox
+begingate
+0.60 0 2 18 TR::two
+endgate
+} def
+
+/TR::threesup {
+% 4 18 10 15 bbox
+begingate
+0.60 0 2 18 TR::three
+endgate
+} def
+
+/TR::quarter {
+% 5 0 20 27 bbox
+begingate
+0.60 0 12 0 TR::four
+0.60 0 2 12 TR::one
+1 1.00 6 0 22 24 2 polygon
+endgate
+} def
+
+/TR::half {
+% 3 0 24 27 bbox
+begingate
+0.60 0 0 12 TR::one
+0.60 0 14 0 TR::two
+1 1.00 4 0 20 24 2 polygon
+endgate
+} def
+
+/TR::threeq {
+% 4 0 23 27 bbox
+begingate
+0.60 0 2 12 TR::three
+0.60 0 14 0 TR::four
+1 1.00 8 0 24 24 2 polygon
+endgate
+} def
+
+/TR::copy {
+% 4 4 24 24 bbox
+begingate
+0.60 0 7 8 TR::C
+1 1.00 16 16 12 0.00 360.00 xcarc
+endgate
+} def
+
+/TR::regis {
+% 4 4 24 24 bbox
+begingate
+0.55 0 9 9 TR::R
+1 1.00 16 16 12 0.00 360.00 xcarc
+endgate
+} def
+
+/TR::mu {
+% 6 -8 16 24 bbox
+begingate
+1.00 0 2 0 TR::u
+1 1.00 7 -8 7 4 2 polygon
+endgate
+} def
+
+/TR::lognot {
+% 6 8 16 8 bbox
+begingate
+1 1.00 6 16 22 16 22 8 3 polygon
+endgate
+} def
+
+/TR::times {
+% 6 6 12 12 bbox
+begingate
+1 1.00 6 6 18 18 2 polygon
+1 1.00 6 18 18 6 2 polygon
+endgate
+} def
+
+/TR::divide {
+% 5 5 15 13 bbox
+begingate
+1 1.00 5 12 20 12 2 polygon
+1.00 0 6 16 TR::period
+1.00 0 6 5 TR::period
+endgate
+} def
+
+/TR::thorn {
+% 2 -6 19 30 bbox
+begingate
+1.00 0 0 0 TR::p
+1 1.00 5 16 5 24 2 polygon
+1 1.00 5 24 2 22 2 polygon
+endgate
+} def
+
+/TR::Thorn {
+% 4 0 13 26 bbox
+begingate
+1.00 0 -2 0 TR::I
+1 1.00 4 8 12 8 16 10 17 14 16 18 12 20 4 20 7 polygon
+endgate
+} def
+
+/TR::onesmall {
+% 7 4 4 19 bbox
+begingate
+0.75 0 4 4 TR::one
+endgate
+} def
+
+/TR::dash {
+% 4 12 8 0 bbox
+begingate
+1 1.00 4 12 12 12 2 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/times_roman.xfe b/lib/fonts/times_roman.xfe
new file mode 100644
index 0000000..a277516
--- /dev/null
+++ b/lib/fonts/times_roman.xfe
@@ -0,0 +1,49 @@
+% XCircuit Font encoding (XFE) file
+name: Times-Roman
+file: times_roman.lps
+family: Times-Roman
+weight: normal
+shape: normal
+type: PostScript
+encoding: Standard
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar
+TR::space TR::exclam TR::quote TR::pound TR::dollar TR::percent TR::ampersand
+TR::apostrophe TR::lparen TR::rparen TR::asterisk TR::plus TR::comma TR::minus
+TR::period TR::slash TR::zero TR::one TR::two TR::three TR::four TR::five
+TR::six TR::seven TR::eight TR::nine TR::colon TR::semi TR::less TR::equal
+TR::more TR::question TR::at TR::A TR::B TR::C TR::D TR::E TR::F TR::G TR::H
+TR::I TR::J TR::K TR::L TR::M TR::N TR::O TR::P TR::Q TR::R TR::S TR::T TR::U
+TR::V TR::W TR::X TR::Y TR::Z TR::lbracket TR::backslash TR::rbracket
+TR::caret TR::underscore TR::apostrophe TR::a TR::b TR::c TR::d TR::e
+TR::f TR::g TR::h TR::i TR::j TR::k TR::l TR::m TR::n TR::o TR::p TR::q
+TR::r TR::s TR::t TR::u TR::v TR::w TR::x TR::y TR::z TR::lbrace TR::vbar
+TR::rbrace TR::tilde
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::upexclam TR::cent TR::lb TR::aslash TR::yen TR::itf TR::sy1 TR::sy2
+TR::apos2 TR::lqt TR::lgqt TR::lsang TR::rsang TR::fi TR::fl TR::nullchar
+TR::minus TR::dag TR::ddag TR::dot TR::nullchar TR::para TR::bullet TR::comma2
+TR::rqt2 TR::rqt TR::rgqt TR::dots TR::perzer TR::nullchar TR::uqest TR::nullchar
+TR::grave TR::acute TR::hat TR::tilchar TR::bar TR::uu TR::dot TR::umlaut
+TR::nullchar TR::circ TR::cedilla TR::nullchar TR::uml2 TR::ced2 TR::vee TR::emdash
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::AE
+TR::nullchar TR::ordfem TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::Lslash TR::Oslash TR::OE TR::ordmasc TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::ae TR::nullchar TR::nullchar
+TR::nullchar TR::onesup TR::nullchar TR::nullchar TR::lslash TR::osl TR::oe
+TR::sset TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+
+derived: Times-Bold bold normal PostScript
+derived: Times-Italic normal italic PostScript
+derived: Times-BoldItalic bold italic PostScript
diff --git a/lib/fonts/times_romaniso.xfe b/lib/fonts/times_romaniso.xfe
new file mode 100644
index 0000000..deb0216
--- /dev/null
+++ b/lib/fonts/times_romaniso.xfe
@@ -0,0 +1,47 @@
+% XCircuit Font encoding (XFE) file
+name: Times-RomanISO
+% file: times_roman.lps
+family: Times-Roman
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin1
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::space TR::exclam TR::quote TR::pound TR::dollar
+TR::percent TR::ampersand
+TR::apostrophe TR::lparen TR::rparen TR::asterisk TR::plus TR::comma TR::minus
+TR::period TR::slash TR::zero TR::one TR::two TR::three TR::four TR::five
+TR::six TR::seven TR::eight TR::nine TR::colon TR::semi TR::less TR::equal
+TR::more TR::question TR::at TR::A TR::B TR::C TR::D TR::E TR::F TR::G TR::H
+TR::I TR::J TR::K TR::L TR::M TR::N TR::O TR::P TR::Q TR::R TR::S TR::T TR::U
+TR::V TR::W TR::X TR::Y TR::Z TR::lbracket TR::backslash TR::rbracket
+TR::caret TR::underscore TR::apostrophe TR::a TR::b TR::c TR::d TR::e
+TR::f TR::g TR::h TR::i TR::j TR::k TR::l TR::m TR::n TR::o TR::p TR::q
+TR::r TR::s TR::t TR::u TR::v TR::w TR::x TR::y TR::z TR::lbrace TR::vbar
+TR::rbrace TR::tilde
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::onesmall TR::grave TR::acute TR::hat TR::tilde TR::bar TR::uu TR::dot
+TR::umlaut TR::nullchar TR::circ TR::cedilla TR::nullchar TR::uml2 TR::ced2
+TR::vee TR::space
+TR::upexclam TR::cent TR::lb TR::sy2 TR::yen TR::vbar TR::sy1 TR::umlaut TR::copy
+TR::ordfem TR::lgqt TR::lognot TR::dash TR::regis TR::bar TR::circ TR::pm TR::twosup
+TR::threesup TR::acute TR::mu TR::para TR::dot TR::cedilla TR::onesup TR::ordmasc
+TR::rgqt TR::quarter TR::half TR::threeq TR::uqest
+TR::Agrave TR::Aacute TR::Acircum TR::Atilde TR::Adier TR::Aring TR::AE TR::Ccedil
+TR::Egrave TR::Eacute TR::Ecircum TR::Edier TR::Igrave TR::Iacute TR::Icircum TR::Idier
+TR::Eth TR::Ntilde TR::Ograve TR::Oacute TR::Ocircum TR::Otilde TR::Odier TR::times
+TR::Oslash TR::Ugrave TR::Uacute TR::Ucircum TR::Udier TR::Yacute TR::Thorn TR::sset
+TR::agrave TR::aacute TR::acircum TR::atilde TR::adier TR::aring TR::ae TR::ccedil
+TR::egrave TR::eacute TR::ecircum TR::edier TR::igrave TR::iacute TR::icircum TR::idier
+TR::eth TR::ntilde TR::ograve TR::oacute TR::ocircum TR::otilde TR::odier TR::divide
+TR::osl TR::ugrave TR::uacute TR::ucircum TR::udier TR::yacute TR::thorn TR::ydier
+
+derived: Times-BoldISO bold normal PostScript
+derived: Times-ItalicISO normal italic PostScript
+derived: Times-BoldItalicISO bold italic PostScript
diff --git a/lib/fonts/times_romaniso2.lps b/lib/fonts/times_romaniso2.lps
new file mode 100644
index 0000000..701dccb
--- /dev/null
+++ b/lib/fonts/times_romaniso2.lps
@@ -0,0 +1,414 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: TR
+% Version: 2.0
+%
+
+% XCircuitLib font library
+/TR::Aogonek {
+% 4 -5 24 31 bbox
+begingate
+1.00 0 0 0 TR::A
+1.00 0 16 0 TR::ced2
+endgate
+} def
+
+/TR::Lcaron {
+% 4 0 20 27 bbox
+begingate
+1.00 0 9 -4 TR::apostrophe
+1.00 0 0 0 TR::L
+endgate
+} def
+
+/TR::Scedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 TR::S
+1.00 0 4 0 TR::cedilla
+endgate
+} def
+
+/TR::Sacute {
+% 4 0 22 36 bbox
+begingate
+1.00 0 0 0 TR::S
+1.00 0 4 4 TR::acute
+endgate
+} def
+
+/TR::Scaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 TR::S
+1.00 0 4 2 TR::vee
+endgate
+} def
+
+/TR::Zacute {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 TR::Z
+1.00 0 2 2 TR::acute
+endgate
+} def
+
+/TR::Zcaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 4 2 TR::vee
+1.00 0 0 0 TR::Z
+endgate
+} def
+
+/TR::Zdot {
+% 4 0 22 35 bbox
+begingate
+1.00 0 0 0 TR::Z
+1.00 0 8 32 TR::period
+endgate
+} def
+
+/TR::aogonek {
+% 4 -5 19 21 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 9 0 TR::ced2
+endgate
+} def
+
+/TR::lcaron {
+% 3 0 7 27 bbox
+begingate
+1.00 0 0 0 TR::l
+1.00 0 4 -4 TR::apostrophe
+endgate
+} def
+
+/TR::sacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::s
+1.00 0 0 -8 TR::acute
+endgate
+} def
+
+/TR::zacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::z
+1.00 0 0 -8 TR::acute
+endgate
+} def
+
+/TR::zcaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 -8 TR::vee
+1.00 0 0 0 TR::z
+endgate
+} def
+
+/TR::zdot {
+% 4 0 16 25 bbox
+begingate
+1.00 0 4 22 TR::period
+1.00 0 0 0 TR::z
+endgate
+} def
+
+/TR::tcaron {
+% 4 0 14 27 bbox
+begingate
+1.00 0 0 0 TR::t
+1.00 0 8 -4 TR::apostrophe
+endgate
+} def
+
+/TR::scedil {
+% 4 -6 16 22 bbox
+begingate
+1.00 0 2 0 TR::cedilla
+1.00 0 0 0 TR::s
+endgate
+} def
+
+/TR::Rcaron {
+% 4 0 23 34 bbox
+begingate
+1.00 0 0 0 TR::R
+1.00 0 2 2 TR::vee
+endgate
+} def
+
+/TR::Racute {
+% 4 0 23 36 bbox
+begingate
+1.00 0 0 0 TR::R
+1.00 0 0 4 TR::acute
+endgate
+} def
+
+/TR::Abreve {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 TR::A
+1.00 0 4 0 TR::uu
+endgate
+} def
+
+/TR::Lacute {
+% 4 0 20 36 bbox
+begingate
+1.00 0 0 0 TR::L
+1.00 0 -4 4 TR::acute
+endgate
+} def
+
+/TR::Cacute {
+% 4 0 24 36 bbox
+begingate
+1.00 0 0 0 TR::C
+1.00 0 8 4 TR::acute
+endgate
+} def
+
+/TR::Ccaron {
+% 4 0 24 34 bbox
+begingate
+1.00 0 0 0 TR::C
+1.00 0 4 2 TR::vee
+endgate
+} def
+
+/TR::Eogonek {
+% 4 -5 22 31 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 14 0 TR::ced2
+endgate
+} def
+
+/TR::Ecaron {
+% 4 0 22 34 bbox
+begingate
+1.00 0 0 0 TR::E
+1.00 0 4 2 TR::vee
+endgate
+} def
+
+/TR::Dcaron {
+% 4 0 24 34 bbox
+begingate
+1.00 0 0 0 TR::D
+1.00 0 2 2 TR::vee
+endgate
+} def
+
+/TR::Ncaron {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 TR::N
+1.00 0 4 0 TR::vee
+endgate
+} def
+
+/TR::Nacute {
+% 4 0 24 32 bbox
+begingate
+1.00 0 0 0 TR::N
+1.00 0 4 0 TR::acute
+endgate
+} def
+
+/TR::Ouml2 {
+% 4 0 26 34 bbox
+begingate
+1.00 0 0 0 TR::O
+1.00 0 8 2 TR::uml2
+endgate
+} def
+
+/TR::Ucirc {
+% 4 0 25 38 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 7 4 TR::circ
+endgate
+} def
+
+/TR::Uuml2 {
+% 4 0 25 34 bbox
+begingate
+1.00 0 0 0 TR::U
+1.00 0 6 2 TR::uml2
+endgate
+} def
+
+/TR::Tcedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 TR::T
+1.00 0 4 0 TR::cedilla
+endgate
+} def
+
+/TR::racute {
+% 4 0 12 24 bbox
+begingate
+1.00 0 0 0 TR::r
+1.00 0 0 -8 TR::acute
+endgate
+} def
+
+/TR::rcaron {
+% 4 0 12 24 bbox
+begingate
+1.00 0 0 0 TR::r
+1.00 0 0 -8 TR::vee
+endgate
+} def
+
+/TR::abreve {
+% 4 0 18 23 bbox
+begingate
+1.00 0 0 0 TR::a
+1.00 0 2 -9 TR::uu
+endgate
+} def
+
+/TR::lacute {
+% 3 0 7 36 bbox
+begingate
+1.00 0 0 0 TR::l
+1.00 0 -4 4 TR::acute
+endgate
+} def
+
+/TR::cacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::c
+1.00 0 4 -8 TR::acute
+endgate
+} def
+
+/TR::ccaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::c
+1.00 0 2 -8 TR::vee
+endgate
+} def
+
+/TR::eogonek {
+% 4 -5 18 21 bbox
+begingate
+1.00 0 6 0 TR::ced2
+1.00 0 0 0 TR::e
+endgate
+} def
+
+/TR::ecaron {
+% 4 0 18 24 bbox
+begingate
+1.00 0 0 0 TR::e
+1.00 0 2 -8 TR::vee
+endgate
+} def
+
+/TR::dcaron {
+% 4 0 22 27 bbox
+begingate
+1.00 0 0 0 TR::d
+1.00 0 14 -4 TR::apostrophe
+endgate
+} def
+
+/TR::dbar {
+% 4 0 18 26 bbox
+begingate
+1.00 0 0 0 TR::d
+1.00 0 6 -8 TR::bar
+endgate
+} def
+
+/TR::ncaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::n
+1.00 0 0 -8 TR::vee
+endgate
+} def
+
+/TR::nacute {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::n
+1.00 0 2 -8 TR::acute
+endgate
+} def
+
+/TR::ucirc {
+% 4 0 16 26 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 0 -8 TR::circ
+endgate
+} def
+
+/TR::uuml2 {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::u
+1.00 0 0 -8 TR::uml2
+endgate
+} def
+
+/TR::tcedil {
+% 4 -6 11 32 bbox
+begingate
+1.00 0 0 0 TR::t
+1.00 0 0 0 TR::cedilla
+endgate
+} def
+
+/TR::togonek {
+% 4 -5 11 31 bbox
+begingate
+1.00 0 0 0 TR::t
+1.00 0 5 0 TR::ced2
+endgate
+} def
+
+/TR::ouml2 {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::o
+1.00 0 0 -8 TR::uml2
+endgate
+} def
+
+/TR::scaron {
+% 4 0 16 24 bbox
+begingate
+1.00 0 0 0 TR::s
+1.00 0 0 -8 TR::vee
+endgate
+} def
+
+/TR::Tcaron {
+% 4 0 22 33 bbox
+begingate
+1.00 0 0 0 TR::T
+1.00 0 3 1 TR::vee
+endgate
+} def
+
+/TR::dotacc {
+% 8 30 3 3 bbox
+begingate
+1.00 0 4 30 TR::period
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/times_romaniso2.xfe b/lib/fonts/times_romaniso2.xfe
new file mode 100644
index 0000000..7dce608
--- /dev/null
+++ b/lib/fonts/times_romaniso2.xfe
@@ -0,0 +1,47 @@
+% XCircuit Font encoding (XFE) file
+name: Times-RomanISO2
+file: times_romaniso2.lps
+family: Times-Roman
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin2
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar
+TR::space TR::exclam TR::quote TR::pound TR::dollar TR::percent TR::ampersand
+TR::apostrophe TR::lparen TR::rparen TR::asterisk TR::plus TR::comma TR::minus
+TR::period TR::slash TR::zero TR::one TR::two TR::three TR::four TR::five
+TR::six TR::seven TR::eight TR::nine TR::colon TR::semi TR::less TR::equal
+TR::more TR::question TR::at TR::A TR::B TR::C TR::D TR::E TR::F TR::G TR::H
+TR::I TR::J TR::K TR::L TR::M TR::N TR::O TR::P TR::Q TR::R TR::S TR::T TR::U
+TR::V TR::W TR::X TR::Y TR::Z TR::lbracket TR::backslash TR::rbracket
+TR::caret TR::underscore TR::apostrophe TR::a TR::b TR::c TR::d TR::e
+TR::f TR::g TR::h TR::i TR::j TR::k TR::l TR::m TR::n TR::o TR::p TR::q TR::r
+TR::s TR::t TR::u TR::v TR::w TR::x TR::y TR::z TR::lbrace TR::vbar TR::rbrace
+TR::tilde TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::Aogonek TR::uu TR::Lslash TR::sy2 TR::Lcaron TR::Sacute TR::sy1
+TR::umlaut TR::Scaron TR::Scedil TR::Tcaron TR::Zacute TR::dash TR::Zcaron
+TR::Zdot TR::circ
+TR::aogonek TR::ced2 TR::lslash TR::acute TR::lcaron TR::sacute TR::vee TR::cedilla
+TR::scaron TR::scedil TR::tcaron TR::zacute TR::uml2 TR::zcaron TR::zdot
+TR::Racute TR::Aacute TR::Acircum TR::Abreve TR::Adier TR::Lacute TR::Cacute TR::Ccedil
+TR::Ccaron TR::Eacute TR::Eogonek TR::Edier TR::Ecaron TR::Iacute TR::Icircum TR::Dcaron
+TR::Eth TR::Nacute TR::Ncaron TR::Oacute TR::Ocircum TR::Ouml2 TR::Odier TR::times
+TR::Rcaron TR::Ucirc TR::Uacute TR::Uuml2 TR::Udier TR::Yacute TR::Tcedil TR::sset
+TR::racute TR::aacute TR::acircum TR::abreve TR::adier TR::lacute TR::cacute TR::ccedil
+TR::ecaron TR::eacute TR::eogonek TR::edier TR::ecaron TR::iacute TR::icircum TR::dcaron
+TR::dbar TR::nacute TR::ncaron TR::oacute TR::ocircum TR::ouml2 TR::odier TR::divide
+TR::rcaron TR::ucirc TR::uacute TR::uuml2 TR::udier TR::yacute TR::tcedil TR::dotacc
+
+derived: Times-BoldISO2 bold normal PostScript
+derived: Times-ItalicISO2 normal italic PostScript
+derived: Times-BoldItalicISO2 bold italic PostScript
diff --git a/lib/fonts/times_romaniso5.lps b/lib/fonts/times_romaniso5.lps
new file mode 100644
index 0000000..fb1939f
--- /dev/null
+++ b/lib/fonts/times_romaniso5.lps
@@ -0,0 +1,56 @@
+%! PostScript set of library objects for XCircuit
+% Library name is: TR
+% Version: 2.0
+%
+%
+
+% XCircuitLib library built-in objects
+/TR::Guu {
+% 4 0 26 34 bbox
+begingate
+1.00 0 0 0 TR::G
+1.00 0 4 2 TR::uu
+endgate
+} def
+
+/TR::Idot {
+% 4 0 7 37 bbox
+begingate
+1.00 0 0 0 TR::I
+1.00 0 -3 12 TR::dot
+endgate
+} def
+
+/TR::Scedil {
+% 4 -6 22 32 bbox
+begingate
+1.00 0 0 0 TR::S
+1.00 0 4 0 TR::cedilla
+endgate
+} def
+
+/TR::scedil {
+% 4 -6 16 22 bbox
+begingate
+1.00 0 0 0 TR::s
+1.00 0 2 0 TR::cedilla
+endgate
+} def
+
+/TR::guu {
+% 4 -6 19 30 bbox
+begingate
+1.00 0 0 0 TR::g
+1.00 0 -2 -8 TR::uu
+endgate
+} def
+
+/TR::dotlessi {
+% 3 0 7 22 bbox
+begingate
+1 1.00 5 0 5 16 3 14 3 polygon
+1 1.00 3 0 7 0 2 polygon
+endgate
+} def
+
+% EndLib
diff --git a/lib/fonts/times_romaniso5.xfe b/lib/fonts/times_romaniso5.xfe
new file mode 100644
index 0000000..569b33f
--- /dev/null
+++ b/lib/fonts/times_romaniso5.xfe
@@ -0,0 +1,48 @@
+% XCircuit Font encoding (XFE) file
+name: Times-RomanISO5
+% file: times_roman.lps
+file: times_romaniso5.lps
+family: Times-Roman
+weight: normal
+shape: normal
+type: PostScript
+encoding: ISOLatin5
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar
+TR::space TR::exclam TR::quote TR::pound TR::dollar TR::percent TR::ampersand
+TR::apostrophe TR::lparen TR::rparen TR::asterisk TR::plus TR::comma
+TR::minus TR::period TR::slash TR::zero TR::one TR::two TR::three TR::four
+TR::five TR::six TR::seven TR::eight TR::nine TR::colon TR::semi TR::less
+TR::equal TR::more TR::question TR::at TR::A TR::B TR::C TR::D TR::E TR::F
+TR::G TR::H TR::I TR::J TR::K TR::L TR::M TR::N TR::O TR::P TR::Q TR::R
+TR::S TR::T TR::U TR::V TR::W TR::X TR::Y TR::Z TR::lbracket TR::backslash
+TR::rbracket TR::caret TR::underscore TR::apostrophe TR::a TR::b TR::c TR::d
+TR::e TR::f TR::g TR::h TR::i TR::j TR::k TR::l TR::m TR::n TR::o TR::p TR::q
+TR::r TR::s TR::t TR::u TR::v TR::w TR::x
+TR::y TR::z TR::lbrace TR::vbar TR::rbrace TR::tilde
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar TR::nullchar TR::nullchar TR::nullchar
+TR::nullchar TR::nullchar
+TR::onesmall TR::grave TR::acute TR::hat TR::tilde TR::bar TR::uu TR::dot
+TR::umlaut TR::nullchar TR::circ TR::cedilla TR::nullchar TR::uml2 TR::ced2 TR::vee
+TR::space TR::upexclam TR::cent TR::lb TR::sy2 TR::yen TR::vbar TR::sy1 TR::umlaut
+TR::copy TR::ordfem TR::lgqt TR::lognot TR::dash TR::regis TR::bar TR::circ
+TR::pm TR::twosup TR::threesup TR::acute TR::mu TR::para TR::dot TR::cedilla
+TR::onesup TR::ordmasc TR::rgqt TR::quarter TR::half TR::threeq TR::uqest
+TR::Agrave TR::Aacute TR::Acircum TR::Atilde TR::Adier TR::Aring TR::AE TR::Ccedil
+TR::Egrave TR::Eacute TR::Ecircum TR::Edier TR::Igrave TR::Iacute TR::Icircum TR::Idier
+TR::Guu TR::Ntilde TR::Ograve TR::Oacute TR::Ocircum TR::Otilde TR::Odier TR::times
+TR::Oslash TR::Ugrave TR::Uacute TR::Ucircum TR::Udier TR::Idot TR::Scedil TR::sset
+TR::agrave TR::aacute TR::acircum TR::atilde TR::adier TR::aring TR::ae TR::ccedil
+TR::egrave TR::eacute TR::ecircum TR::edier TR::igrave TR::iacute TR::icircum TR::idier
+TR::guu TR::ntilde TR::ograve TR::oacute TR::ocircum TR::otilde TR::odier TR::divide
+TR::osl TR::ugrave TR::uacute TR::ucircum TR::udier TR::dotlessi TR::scedil TR::ydier
+
+derived: Times-BoldISO5 bold normal PostScript
+derived: Times-ItalicISO5 normal italic PostScript
+derived: Times-BoldItalicISO5 bold italic PostScript
diff --git a/lib/generic.lps b/lib/generic.lps
new file mode 100644
index 0000000..bad4e91
--- /dev/null
+++ b/lib/generic.lps
@@ -0,0 +1,93 @@
+%! PostScript set of library objects for XCircuit
+% Version: 2.3
+% Library name is: generic
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+
+% Depend arrow arrowhead
+% Depend netquery arrowhead
+
+% XCircuitLib library of objects
+
+/generic::arrowhead {
+% nonetwork
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+1.00 90 /generic::arrowhead libinst
+
+/generic::jumper {
+% trivial
+begingate
+1 1.0 0 0 10 -90 90 xcarc
+0 10 0 16 wire
+0 -10 0 -16 wire
+1 0 0 scb
+(a) {/Times-Roman cf} 2 1 0 1.0 0 16 pinlabel
+(a) {/Times-Roman cf} 2 13 0 1.0 0 -16 pinlabel
+sce
+endgate
+} def
+
+1.00 90 /generic::jumper libinst
+
+/generic::circle {
+% trivial
+begingate
+1 1.0 16 0 6 0 360 xcarc
+0 0 10 0 wire
+1 0 0 scb
+(out) {/Times-Roman cf} 2 4 0 1.0 16 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.0 0 0 pinlabel
+sce
+endgate
+} def
+
+1.00 90 /generic::circle libinst
+
+/generic::arrow {
+% nonetwork
+begingate
+1 0.8 0 -40 0 20 2 polygon
+1.0 0 0 40 generic::arrowhead
+endgate
+} def
+
+1.00 90 /generic::arrow libinst
+1.00 45 /generic::arrow libinst
+
+/generic::dot {
+% trivial
+begingate
+248 1.0 0 0 6 0 360 xcarc
+1 0 0 scb
+(x) {/Times-Roman cf} 2 29 0 1.0 0 0 pinlabel
+endgate
+} def
+
+/generic::tap {
+% trivial
+<</in (bus\(0:7\)) /out (bus\(0\)) >> begingate
+496 1.0 0 8 16 0 0 -8 3 polygon
+1 0 0 scb
+mark out {/Helvetica cf} ctmk 20 0 1.0 16 0 pinlabel
+mark in {/Helvetica cf} ctmk 23 0 1.0 0 0 pinlabel
+endgate
+} def
+
+/generic::netquery {
+% nonetwork
+<</netname (\(none\)) (netlist get {0 0} -up -hier -quiet) pop >> begingate
+1 1.00 8 8 16 16 80 16 3 polygon
+mark netname {/Times-Roman cf} ctmk 16 0 1.00 16 24 label
+0.65 135 0 0 generic::arrowhead
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/ic_templates.lps b/lib/ic_templates.lps
new file mode 100644
index 0000000..385ecc7
--- /dev/null
+++ b/lib/ic_templates.lps
@@ -0,0 +1,435 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: ic_templates
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+%
+
+% XCircuitLib library objects
+/templateCLK {
+<</clock_rate (?) /@index (?) /title (clock IC) >> begingate
+0 1.00 -144 -144 -144 144 144 144 144 -144 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 25 0 1.00 0 16 label
+mark (MHz) {hS} clock_rate {/Helvetica cf} ctmk 21 0 1.00 0 -32 label
+(N/C) {/Helvetica cf} 2 20 0 1.00 -128 96 label
+(GND) {/Helvetica cf} 2 20 0 1.00 -128 -96 label
+(OUT) {/Helvetica cf} 2 23 0 1.00 128 -96 label
+(Vdd) {/Helvetica cf} 2 23 0 1.00 128 96 label
+0.180 0.545 0.341 scb
+mark @index (pcb:X) {/Helvetica cf} ctmk 21 0 1.00 0 -176 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -144 96 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -144 -96 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 144 -96 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 144 96 pinlabel
+sce
+mark @index (X) {/Helvetica cf} ctmk 16 0 1.00 -16 160 label
+endgate
+} def
+
+/template8 {
+<</pkg (DIP8) /title (generic 8-pin IC) /gate (part #) /@index (?) /pin14
+(14) /pin13 (13) /pin12
+(12) /pin11 (11) /pin10 (10) /pin9 (9) /pin8 (8) /pin7 (7) /pin6 (6) /pin5
+(5) /pin4 (4) /pin3 (3) /pin2 (2) /pin1 (1) >> begingate
+0 1.00 -224 176 -224 464 224 464 224 176 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 336 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 384 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 496 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin5 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin6 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin7 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin8 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 256 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(6) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(7) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+endgate
+} def
+
+/template14 {
+<</pin1 (1) /pin2 (2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8
+(8) /pin9 (9) /pin10 (10) /pin11 (11) /pin12 (12) /pin13 (13) /pin14 (14) /@index
+(?) /gate (part #) /title (generic 14-pin IC) /pkg (DIP14) >> begingate
+0 1.00 -224 0 -224 448 224 448 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 272 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 320 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 464 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin8 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin9 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin10 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+endgate
+} def
+
+/template16 {
+<</pin16 (16) /pin15 (15) /pin1 (1) /pin2 (2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6
+(6) /pin7 (7) /pin8 (8) /pin9 (9) /pin10 (10) /pin11 (11) /pin12 (12) /pin13
+(13) /pin14 (14) /@index (?) /gate (part #) /title (generic 16-pin IC)
+/pkg (DIP16) >> begingate
+0 1.00 -224 0 -224 512 224 512 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 272 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 320 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 544 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin9 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin10 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+endgate
+} def
+
+/template20 {
+<</pin20 (20) /pin19 (19) /pin18 (18) /pin17 (17) /pin16 (16) /pin15 (15) /pkg
+(DIP20) /title (generic 20-pin IC) /gate (part #) /@index (?) /pin14 (14) /pin13
+(13) /pin12 (12) /pin11 (11) /pin10 (10) /pin9 (9) /pin8 (8) /pin7 (7) /pin6
+(6) /pin5 (5) /pin4 (4) /pin3 (3) /pin2 (2) /pin1 (1) >> begingate
+0 1.00 -224 0 -224 640 224 640 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 400 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 448 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 656 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+endgate
+} def
+
+/template24 {
+<</pin24 (24) /pin23 (23) /pin22 (22) /pin21 (21) /pin20 (20) /pin19 (19) /pin18
+(18) /pin17 (17) /pin16 (16) /pin15 (15) /pin1 (1) /pin2 (2) /pin3 (3) /pin4
+(4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8 (8) /pin9 (9) /pin10 (10) /pin11
+(11) /pin12 (12) /pin13 (13) /pin14 (14) /@index (?) /gate (part #)
+/title (generic 24-pin IC) /pkg (DIP24) >> begingate
+0 1.00 -224 0 -224 768 224 768 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 528 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 576 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 784 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 736 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 672 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin11 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin12 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin21 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin22 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark pin23 {/Helvetica cf} ctmk 23 0 1.00 208 672 label
+mark pin24 {/Helvetica cf} ctmk 23 0 1.00 208 736 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+endgate
+} def
+
+/template28 {
+<</pin28 (28) /pin27 (27) /pin26 (26) /pin25 (25) /pin24 (24) /pin23 (23) /pin22
+(22) /pin21 (21) /pin20 (20) /pin19 (19) /pin18 (18) /pin17 (17) /pin16
+(16) /pin15 (15) /pkg (DIP28) /title (generic 28-pin IC) /gate (part #)
+/@index (?) /pin14 (14) /pin13 (13) /pin12 (12) /pin11 (11) /pin10 (10) /pin9
+(9) /pin8 (8) /pin7 (7) /pin6 (6) /pin5 (5) /pin4 (4) /pin3 (3) /pin2 (2)
+/pin1 (1) >> begingate
+0 1.00 -224 0 -224 896 224 896 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 592 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 640 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 912 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 864 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 800 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 736 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 672 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin11 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin12 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin13 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin14 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin21 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin22 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin23 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin24 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark pin25 {/Helvetica cf} ctmk 23 0 1.00 208 672 label
+mark pin26 {/Helvetica cf} ctmk 23 0 1.00 208 736 label
+mark pin27 {/Helvetica cf} ctmk 23 0 1.00 208 800 label
+mark pin28 {/Helvetica cf} ctmk 23 0 1.00 208 864 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+endgate
+} def
+
+/template40 {
+<</@index (?) /title (generic 40-pin IC) /gate (part #) /pkg (PLCC40) /pin1 (1) /pin2
+(2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8 (8) /pin9 (9) /pin10
+(10) /pin11 (11) /pin12 (12) /pin13 (13) /pin14 (14) /pin15 (15) /pin16
+(16) /pin17 (17) /pin18 (18) /pin19 (19) /pin20 (20) /pin21 (21) /pin22 (22) /pin23
+(23) /pin24 (24) /pin25 (25) /pin26 (26) /pin27 (27) /pin28 (28) /pin29
+(29) /pin30 (30) /pin31 (31) /pin32 (32) /pin33 (33) /pin34 (34) /pin35 (35) /pin36
+(36) /pin37 (37) /pin38 (38) /pin39 (39) /pin40 (40) >> begingate
+0 1.00 -480 -352 -480 480 352 480 352 -352 4 polygon
+mark gate {/Helvetica-Bold cf} ctmk 17 0 1.00 -80 224 label
+mark title {/Helvetica cf} ctmk 21 0 1.00 -80 160 label
+mark @index (U) {/Helvetica cf} ctmk 21 0 1.00 -80 -32 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 -96 -160 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -464 352 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -464 288 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -464 224 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -464 160 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -464 96 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -464 32 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -464 -32 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -464 -96 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -464 -160 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -464 -224 label
+mark pin11 {/Helvetica cf} ctmk 20 270 1.00 -353 -332 label
+mark pin12 {/Helvetica cf} ctmk 20 270 1.00 -290 -332 label
+mark pin13 {/Helvetica cf} ctmk 20 270 1.00 -224 -332 label
+mark pin14 {/Helvetica cf} ctmk 20 270 1.00 -161 -332 label
+mark pin15 {/Helvetica cf} ctmk 20 270 1.00 -98 -333 label
+mark pin16 {/Helvetica cf} ctmk 20 270 1.00 -34 -333 label
+mark pin17 {/Helvetica cf} ctmk 20 270 1.00 29 -333 label
+mark pin18 {/Helvetica cf} ctmk 20 270 1.00 93 -335 label
+mark pin19 {/Helvetica cf} ctmk 20 270 1.00 156 -336 label
+mark pin20 {/Helvetica cf} ctmk 20 270 1.00 221 -335 label
+mark pin21 {/Helvetica cf} ctmk 23 0 1.00 336 -224 label
+mark pin22 {/Helvetica cf} ctmk 23 0 1.00 336 -160 label
+mark pin23 {/Helvetica cf} ctmk 23 0 1.00 336 -96 label
+mark pin24 {/Helvetica cf} ctmk 23 0 1.00 336 -32 label
+mark pin25 {/Helvetica cf} ctmk 23 0 1.00 336 32 label
+mark pin26 {/Helvetica cf} ctmk 23 0 1.00 336 96 label
+mark pin27 {/Helvetica cf} ctmk 23 0 1.00 336 160 label
+mark pin28 {/Helvetica cf} ctmk 23 0 1.00 336 224 label
+mark pin29 {/Helvetica cf} ctmk 23 0 1.00 336 288 label
+mark pin30 {/Helvetica cf} ctmk 23 0 1.00 336 352 label
+mark pin31 {/Helvetica cf} ctmk 20 90 1.00 225 463 label
+mark pin32 {/Helvetica cf} ctmk 20 90 1.00 160 462 label
+mark pin33 {/Helvetica cf} ctmk 20 90 1.00 98 460 label
+mark pin34 {/Helvetica cf} ctmk 20 90 1.00 34 460 label
+mark pin35 {/Helvetica cf} ctmk 20 90 1.00 -32 460 label
+mark pin36 {/Helvetica cf} ctmk 20 90 1.00 -95 462 label
+mark pin37 {/Helvetica cf} ctmk 20 90 1.00 -159 461 label
+mark pin38 {/Helvetica cf} ctmk 20 90 1.00 -223 460 label
+mark pin39 {/Helvetica cf} ctmk 20 90 1.00 -289 460 label
+mark pin40 {/Helvetica cf} ctmk 20 90 1.00 -351 460 label
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 -80 304 infolabel
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -480 352 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -480 288 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -480 224 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -480 160 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -480 96 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -480 32 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -480 -32 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -480 -96 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -480 -160 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -480 -224 pinlabel
+(11) {/Helvetica cf} 2 29 0 1.00 -352 -352 pinlabel
+(12) {/Helvetica cf} 2 29 0 1.00 -288 -352 pinlabel
+(13) {/Helvetica cf} 2 29 0 1.00 -224 -352 pinlabel
+(14) {/Helvetica cf} 2 29 0 1.00 -160 -352 pinlabel
+(15) {/Helvetica cf} 2 29 0 1.00 -96 -352 pinlabel
+(16) {/Helvetica cf} 2 29 0 1.00 -32 -352 pinlabel
+(17) {/Helvetica cf} 2 29 0 1.00 32 -352 pinlabel
+(18) {/Helvetica cf} 2 29 0 1.00 96 -352 pinlabel
+(19) {/Helvetica cf} 2 29 0 1.00 160 -352 pinlabel
+(20) {/Helvetica cf} 2 29 0 1.00 224 -352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 352 -224 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 352 -160 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 352 -96 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 352 -32 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 352 32 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 352 96 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 352 160 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 352 224 pinlabel
+(29) {/Helvetica cf} 2 20 0 1.00 352 288 pinlabel
+(30) {/Helvetica cf} 2 20 0 1.00 352 352 pinlabel
+(31) {/Helvetica cf} 2 25 0 1.00 224 480 pinlabel
+(32) {/Helvetica cf} 2 25 0 1.00 160 480 pinlabel
+(33) {/Helvetica cf} 2 25 0 1.00 96 480 pinlabel
+(34) {/Helvetica cf} 2 25 0 1.00 32 480 pinlabel
+(35) {/Helvetica cf} 2 25 0 1.00 -32 480 pinlabel
+(36) {/Helvetica cf} 2 25 0 1.00 -96 480 pinlabel
+(37) {/Helvetica cf} 2 25 0 1.00 -160 480 pinlabel
+(38) {/Helvetica cf} 2 25 0 1.00 -224 480 pinlabel
+(39) {/Helvetica cf} 2 25 0 1.00 -288 480 pinlabel
+(40) {/Helvetica cf} 2 25 0 1.00 -352 480 pinlabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/lgf.lps b/lib/lgf.lps
new file mode 100644
index 0000000..bc5bcb1
--- /dev/null
+++ b/lib/lgf.lps
@@ -0,0 +1,874 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: lgf
+% Author: R. Timothy Edwards <tim@opencircuitdesign.com>
+%
+
+% Depend VDIFF source
+% Depend IDIFF source arrowhead
+% Depend STAIRS VDIFF
+% Depend NFET7F NFET7T
+% Depend PFET7F PFET7T
+% Depend NPN1 arrowhead
+% Depend PNP1 arrowhead
+% Depend ARROW1 arrowhead
+% Depend ARROW2 arrowhead
+% Depend MMETER arrowhead
+% Depend ISCOPE MMETER
+% Depend GINST1 arrowhead
+% Depend SW2 arrowhead
+% Depend SW4 arrowhead
+% Depend NFET5 NFET7T
+% Depend PFET5 PFET7T
+% Depend PFET6 PFET7F
+% Depend PULSE SWITCH
+
+% XCircuitLib library objects
+/source {
+begingate
+1 1.00 0 32 0 64 2 polygon
+1 1.00 0 -32 0 -64 2 polygon
+1 1.00 0 0 32 0.00 360.00 xcarc
+endgate
+} def
+
+/VDIFF {
+begingate
+1.00 0 0 0 source
+(+) {/Symbol cf} 2 5 0 1.00 0 18 label
+(-) {/Symbol cf} 2 5 0 1.00 0 -18 label
+endgate
+} def
+
+/arrowhead {
+begingate
+8 -28 beginpath
+3 -18 3 -15 0 0 curveto
+-3 -15 -3 -18 -8 -28 curveto
+-2 -26 2 -26 8 -28 curveto
+249 1.00 endpath
+endgate
+} def
+
+/IDIFF {
+begingate
+1 0.75 0 20 0 -8 2 polygon
+1.00 0 0 0 source
+0.80 180 0 -20 arrowhead
+endgate
+} def
+
+/STAIRS {
+begingate
+1.00 0 0 0 VDIFF
+(S) {/Helvetica-Bold cf} 2 21 0 0.50 0 0 label
+endgate
+} def
+
+/NFET7T {
+begingate
+1 1.00 -36 -28 -36 28 2 polygon
+1 1.00 -36 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -24 -28 -24 28 0 28 0 64 6 polygon
+1.000 0.000 0.000 scb
+(G) {/Helvetica cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Helvetica cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Helvetica cf} 2 9 0 1.00 0 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS GND nmos) {/Times-Roman cf} 2 4 0 1.00 -244 -139
+infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/PFET7T {
+begingate
+1 1.00 -36 -28 -36 28 2 polygon
+1 1.00 -52 0 -64 0 2 polygon
+1 1.00 0 -64 0 -28 -24 -28 -24 28 0 28 0 64 6 polygon
+1 1.00 -44 0 8 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(S) {/Helvetica cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Helvetica cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Helvetica cf} 2 7 0 1.00 -64 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS Vdd pmos) {/Times-Roman cf} 2 4 0 1.00 -196 -139
+infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+endgate
+} def
+
+/NFET7F {
+begingate
+1 1.00 -24 0 16 0 2 polygon
+1.00 0 0 0 NFET7T
+1.000 0.000 0.000 scb
+(G) {/Helvetica cf} 2 7 0 1.00 -64 0 pinlabel
+(S) {/Helvetica cf} 2 13 0 1.00 0 -64 pinlabel
+(D) {/Helvetica cf} 2 9 0 1.00 0 64 pinlabel
+(B) {/Helvetica cf} 2 0 0 1.00 16 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS %pB nmos) {/Times-Roman cf} 2 4 0 1.00 -244 -139
+infolabel
+(sim:n %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/PFET7F {
+begingate
+1 1.00 -24 0 16 0 2 polygon
+1.00 0 0 0 PFET7T
+1.000 0.000 0.000 scb
+(S) {/Helvetica cf} 2 9 0 1.00 0 64 pinlabel
+(D) {/Helvetica cf} 2 13 0 1.00 0 -64 pinlabel
+(G) {/Helvetica cf} 2 7 0 1.00 -64 0 pinlabel
+(B) {/Helvetica cf} 2 0 0 1.00 16 0 pinlabel
+0.180 0.545 0.341 scb
+(spice:M%i %pD %pG %pS %pB pmos) {/Times-Roman cf} 2 4 0 1.00 -196 -139
+infolabel
+(sim:p %pG %pS %pD) {/Times-Roman cf} 2 4 0 1.00 -196 -187 infolabel
+endgate
+} def
+
+/VDD {
+begingate
+1 1.00 0 0 0 32 2 polygon
+1 1.00 -32 32 32 32 2 polygon
+(Vdd) {/Times-Roman cf} 2 17 0 0.90 0 38 label
+0.933 0.604 0.000 scb
+(Vdd) {/Times-Roman cf} 2 13 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/GND {
+begingate
+1 1.00 0 0 0 -32 2 polygon
+1 1.00 -32 -32 32 -32 2 polygon
+1 1.00 -18 -46 18 -46 2 polygon
+1 1.00 -4 -60 4 -60 2 polygon
+0.933 0.604 0.000 scb
+(GND) {/Times-Roman cf} 2 1 0 1.00 0 0 pinglobal
+endgate
+} def
+
+/NPN1 {
+begingate
+1 1.00 -16 0 -32 0 2 polygon
+1 1.00 -16 48 -16 -48 2 polygon
+1 1.00 32 48 -16 22 2 polygon
+1 1.00 32 48 32 64 2 polygon
+1 1.00 32 -48 -16 -22 2 polygon
+1 1.00 32 -48 32 -64 2 polygon
+1.00 120 32 -48 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 9 0 1.00 32 64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -32 0 pinlabel
+(E) {/Times-Roman cf} 2 13 0 1.00 32 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:Q%i %pC %pB %pE npn) {/Times-Roman cf} 2 4 0 1.00 -244 -139 infolabel
+(sim:b %pB %pE %pC) {/Times-Roman cf} 2 4 0 1.00 -244 -187 infolabel
+endgate
+} def
+
+/PNP1 {
+begingate
+1 1.00 -16 0 -32 0 2 polygon
+1 1.00 -16 48 -16 -48 2 polygon
+1 1.00 32 48 -16 22 2 polygon
+1 1.00 32 48 32 64 2 polygon
+1 1.00 32 -48 -16 -22 2 polygon
+1 1.00 32 -48 32 -64 2 polygon
+1.00 240 -16 22 arrowhead
+1.000 0.000 0.000 scb
+(C) {/Times-Roman cf} 2 13 0 1.00 32 -64 pinlabel
+(B) {/Times-Roman cf} 2 7 0 1.00 -32 0 pinlabel
+(E) {/Times-Roman cf} 2 9 0 1.00 32 64 pinlabel
+0.180 0.545 0.341 scb
+(spice:Q%i %pC %pB %pE pnp) {/Times-Roman cf} 2 4 0 1.00 -244 -139 infolabel
+endgate
+} def
+
+/RESFLOAT {
+begingate
+1 1.00 0 -48 0 -36 2 polygon
+1 1.00 0 48 0 36 2 polygon
+1 1.00 0 -36 -12 -30 14 -18 -12 -6 14 6 -12 18 12 30 0 36 8 polygon
+1.000 0.000 0.000 scb
+(r.1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(r.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:R%i %pr.1 %pr.2 1.0K) {/Times-Roman cf} 2 0 0 1.00 -208 -160 infolabel
+(sim:r %pr.1 %pr.2) {/Times-Roman cf} 2 0 0 1.00 -208 -208 infolabel
+endgate
+} def
+
+/CAPFLOAT {
+begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 -6 32 -6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1.000 0.000 0.000 scb
+(c.1) {/Times-Roman cf} 2 9 0 1.00 0 64 pinlabel
+(c.2) {/Times-Roman cf} 2 13 0 1.00 0 -64 pinlabel
+0.180 0.545 0.341 scb
+(spice:C%i %pc.1 %pc.2 1.0P) {/Times-Roman cf} 2 0 0 1.00 -208 -160 infolabel
+(sim:c %pc.1 %pc.2) {/Times-Roman cf} 2 0 0 1.00 -208 -208 infolabel
+endgate
+} def
+
+/MOSCAP {
+begingate
+1 1.00 0 4 0 64 2 polygon
+1 1.00 -64 4 64 4 2 polygon
+1 1.00 -64 -4 -8 -4 2 polygon
+1 1.00 8 -4 64 -4 2 polygon
+1 1.00 -56 -36 -16 -36 2 polygon
+1 1.00 36 -36 36 -4 2 polygon
+1 1.00 16 -36 56 -36 2 polygon
+1 1.00 -36 -36 -36 -4 2 polygon
+1 1.00 -48 -44 -24 -44 2 polygon
+1 1.00 -40 -52 -32 -52 2 polygon
+(Vdd) {/Helvetica cf} 2 29 0 0.60 36 -40 label
+endgate
+} def
+
+/DIODE {
+begingate
+1 1.00 0 -48 0 -16 2 polygon
+1 1.00 0 48 0 16 2 polygon
+1 1.00 -18 -16 18 -16 2 polygon
+248 1.00 -18 16 0 -16 18 16 3 polygon
+endgate
+} def
+
+/OPAMP {
+begingate
+1 1.00 0 -40 0 -80 2 polygon
+0 1.00 -80 -80 -80 80 80 0 3 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -64 46 label
+(+) {/Symbol cf} 2 5 0 1.00 -64 -46 label
+endgate
+} def
+
+/WRAMP {
+begingate
+1 1.00 0 -80 0 -45 2 polygon
+1 1.00 48 0 80 0 2 polygon
+0 1.00 -80 -80 -80 80 48 24 48 -24 4 polygon
+(-) {/Symbol cf} 2 5 0 1.00 -64 46 label
+(+) {/Symbol cf} 2 5 0 1.00 -64 -46 label
+endgate
+} def
+
+/ARROW1 {
+begingate
+1 0.80 0 -40 0 20 2 polygon
+1.00 0 0 40 arrowhead
+endgate
+} def
+
+/ARROW2 {
+begingate
+1 0.80 -32 -32 16 16 2 polygon
+1.00 45 32 32 arrowhead
+endgate
+} def
+
+/MMETER {
+begingate
+1 1.00 -24 -24 -8 -8 2 polygon
+0 1.00 -8 -8 -8 8 8 8 8 -8 4 polygon
+0.75 225 -32 -32 arrowhead
+endgate
+} def
+
+/ISCOPE {
+begingate
+1 1.00 8 8 32 32 48 32 3 polygon
+1.00 0 0 0 MMETER
+endgate
+} def
+
+/TO {
+begingate
+1 1.00 -80 0 -64 0 2 polygon
+1 1.00 -76 -12 -64 0 -76 12 3 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 -48 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 -64 0 pinlabel
+endgate
+} def
+
+/FROM {
+begingate
+1 1.00 76 0 64 12 2 polygon
+1 1.00 76 0 80 0 2 polygon
+1 1.00 76 0 64 -12 2 polygon
+1.000 0.000 0.000 scb
+(out) {/Times-Roman cf} 2 4 0 1.00 80 0 pinlabel
+(out) {/Times-Roman cf} 2 7 0 1.00 54 0 pinlabel
+endgate
+} def
+
+/CROSS5 {
+begingate
+1 1.00 32 32 -32 -32 2 polygon
+1 1.00 32 -32 -32 32 2 polygon
+endgate
+} def
+
+/CROSS3 {
+begingate
+1 1.00 16 32 -32 -16 2 polygon
+1 1.00 -32 32 16 -16 2 polygon
+endgate
+} def
+
+/CROSS2 {
+begingate
+1 1.00 16 16 -16 -16 2 polygon
+1 1.00 -16 16 16 -16 2 polygon
+endgate
+} def
+
+/GINST1 {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 0.60 16 36 16 16 2 polygon
+0.60 0 16 48 arrowhead
+endgate
+} def
+
+/SW2 {
+begingate
+1 1.00 0 -32 -16 16 2 polygon
+257 1.00 0 -32 4 0.00 360.00 xcarc
+257 1.00 -16 16 4 0.00 360.00 xcarc
+257 1.00 16 16 4 0.00 360.00 xcarc
+-0.60 340 -15 12 arrowhead
+endgate
+} def
+
+/SW4 {
+begingate
+1 1.00 -16 -16 16 -16 2 polygon
+1 1.00 32 32 16 -16 2 polygon
+1 1.00 -32 32 -48 -16 2 polygon
+3 1.00 -40 8 24 8 2 polygon
+257 1.00 16 -16 4 0.00 360.00 xcarc
+257 1.00 32 32 4 0.00 360.00 xcarc
+257 1.00 48 -16 4 0.00 360.00 xcarc
+257 1.00 -32 32 4 0.00 360.00 xcarc
+257 1.00 -16 -16 4 0.00 360.00 xcarc
+257 1.00 -48 -16 4 0.00 360.00 xcarc
+0.60 200 17 -12 arrowhead
+0.60 200 -47 -11 arrowhead
+endgate
+} def
+
+/NFET5 {
+begingate
+1.00 0 0 0 NFET7T
+endgate
+} def
+
+/PFET5 {
+begingate
+1.00 0 0 0 PFET7T
+endgate
+} def
+
+/PFET6 {
+begingate
+1.00 0 0 0 PFET7F
+endgate
+} def
+
+/NOR {
+begingate
+1 1.00 -40 32 -8 32 2 polygon
+1 1.00 -40 -32 -8 -32 2 polygon
+1 1.00 -24 -16 -24 16 -40 32 -40 -32 spline
+1 1.00 8 32 24 16 32 0 -8 32 spline
+1 1.00 40 0 8 0.00 360.00 xcarc
+1 1.00 48 0 64 0 2 polygon
+1 1.00 8 -32 24 -16 32 0 -8 -32 spline
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+endgate
+} def
+
+/OR {
+begingate
+1 1.00 -40 32 -8 32 2 polygon
+1 1.00 -40 -32 -8 -32 2 polygon
+1 1.00 -24 -16 -24 16 -40 32 -40 -32 spline
+1 1.00 8 32 24 16 32 0 -8 32 spline
+1 1.00 32 0 64 0 2 polygon
+1 1.00 8 -32 24 -16 32 0 -8 -32 spline
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+endgate
+} def
+
+/NAND {
+begingate
+1 1.00 24 -32 32 -16 32 0 8 -32 spline
+1 1.00 48 0 64 0 2 polygon
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+1 1.00 24 32 32 16 32 0 8 32 spline
+1 1.00 8 32 -32 32 -32 -32 8 -32 4 polygon
+1 1.00 40 0 8 0.00 360.00 xcarc
+endgate
+} def
+
+/AND {
+begingate
+1 1.00 24 -32 32 -16 32 0 8 -32 spline
+1 1.00 32 0 64 0 2 polygon
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+1 1.00 24 32 32 16 32 0 8 32 spline
+1 1.00 8 32 -32 32 -32 -32 8 -32 4 polygon
+endgate
+} def
+
+/INV {
+begingate
+1 1.00 -48 0 -24 0 2 polygon
+1 1.00 -24 32 -24 -32 2 polygon
+1 1.00 -24 32 16 0 -24 -32 3 polygon
+1 1.00 24 0 8 0.00 360.00 xcarc
+1 1.00 32 0 48 0 2 polygon
+endgate
+} def
+
+/LED {
+begingate
+0 1.00 -16 -16 -16 16 16 16 16 -16 4 polygon
+1.000 0.000 0.000 scb
+241 1.00 0 0 12 0.00 360.00 xcarc
+sce
+1 1.00 0 0 12 0.00 360.00 xcarc
+endgate
+} def
+
+/CLOCK {
+begingate
+0 1.00 -40 -40 -40 40 40 40 40 -40 4 polygon
+1 1.00 40 16 64 16 2 polygon
+1 1.00 40 -16 64 -16 2 polygon
+1 1.00 16 -16 12 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+241 1.00 16 16 12 0.00 360.00 xcarc
+sce
+1 1.00 16 16 12 0.00 360.00 xcarc
+endgate
+} def
+
+/SWITCH {
+begingate
+1 1.00 16 16 -16 16 -16 -16 16 -16 32 0 16 16 6 polygon
+1.000 0.000 0.000 scb
+241 1.00 0 0 12 0.00 360.00 xcarc
+sce
+1 1.00 0 0 12 0.00 360.00 xcarc
+endgate
+} def
+
+/PULSE {
+begingate
+1.00 0 8 0 SWITCH
+1 1.00 16 16 32 16 48 0 32 -16 16 -16 5 polygon
+endgate
+} def
+
+/XNOR {
+begingate
+1 1.00 -40 32 -8 32 2 polygon
+1 1.00 -40 -32 -8 -32 2 polygon
+1 1.00 -32 -16 -32 16 -48 32 -48 -32 spline
+1 1.00 8 32 24 16 32 0 -8 32 spline
+1 1.00 40 0 8 0.00 360.00 xcarc
+1 1.00 48 0 64 0 2 polygon
+1 1.00 8 -32 24 -16 32 0 -8 -32 spline
+1 1.00 -40 16 -64 16 2 polygon
+1 1.00 -40 -16 -64 -16 2 polygon
+1 1.00 -24 -16 -24 16 -40 32 -40 -32 spline
+endgate
+} def
+
+/XOR {
+begingate
+1 1.00 -40 32 -8 32 2 polygon
+1 1.00 -40 -32 -8 -32 2 polygon
+1 1.00 -32 -16 -32 16 -48 32 -48 -32 spline
+1 1.00 8 32 24 16 32 0 -8 32 spline
+1 1.00 32 0 64 0 2 polygon
+1 1.00 8 -32 24 -16 32 0 -8 -32 spline
+1 1.00 -40 16 -64 16 2 polygon
+1 1.00 -40 -16 -64 -16 2 polygon
+1 1.00 -24 -16 -24 16 -40 32 -40 -32 spline
+endgate
+} def
+
+/AND3 {
+begingate
+1 1.00 24 -48 32 -32 32 0 8 -48 spline
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -32 -32 -64 -32 2 polygon
+1 1.00 24 48 32 32 32 0 8 48 spline
+1 1.00 8 48 -32 48 -32 -48 8 -48 4 polygon
+1 1.00 -32 0 -64 0 2 polygon
+1 1.00 32 0 64 0 2 polygon
+endgate
+} def
+
+/AND4 {
+begingate
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 24 -64 48 -32 48 0 8 -64 spline
+1 1.00 -32 48 -64 48 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+1 1.00 8 64 -32 64 -32 -64 8 -64 4 polygon
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 48 0 80 0 2 polygon
+1 1.00 24 64 48 32 48 0 8 64 spline
+endgate
+} def
+
+/AND8 {
+begingate
+1 1.00 -64 -64 -32 -64 2 polygon
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -32 -32 -64 -32 2 polygon
+1 1.00 24 56 48 32 48 0 8 56 spline
+1 1.00 8 56 -32 56 -32 -80 8 -80 4 polygon
+1 1.00 -32 0 -64 0 2 polygon
+1 1.00 48 0 80 0 2 polygon
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 -64 -16 -32 -16 2 polygon
+1 1.00 -64 16 -32 16 2 polygon
+1 1.00 -64 48 -32 48 2 polygon
+1 1.00 32 -80 48 -48 48 0 8 -80 spline
+endgate
+} def
+
+/NAND3 {
+begingate
+1 1.00 24 -48 32 -32 32 0 8 -48 spline
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -32 -32 -64 -32 2 polygon
+1 1.00 24 48 32 32 32 0 8 48 spline
+1 1.00 8 48 -32 48 -32 -48 8 -48 4 polygon
+1 1.00 -32 0 -64 0 2 polygon
+1 1.00 48 0 64 0 2 polygon
+1 1.00 40 0 8 0.00 360.00 xcarc
+endgate
+} def
+
+/NAND4 {
+begingate
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 -32 48 -64 48 2 polygon
+1 1.00 -32 -16 -64 -16 2 polygon
+1 1.00 8 64 -32 64 -32 -64 8 -64 4 polygon
+1 1.00 -32 16 -64 16 2 polygon
+1 1.00 64 0 80 0 2 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 24 -64 48 -32 48 0 8 -64 spline
+1 1.00 24 64 48 32 48 0 8 64 spline
+endgate
+} def
+
+/NAND8 {
+begingate
+1 1.00 -64 -64 -32 -64 2 polygon
+1 1.00 32 56 48 32 48 0 8 56 spline
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -32 -32 -64 -32 2 polygon
+1 1.00 32 -80 48 -56 48 0 8 -80 spline
+1 1.00 8 56 -32 56 -32 -80 8 -80 4 polygon
+1 1.00 -32 0 -64 0 2 polygon
+1 1.00 64 0 80 0 2 polygon
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 -64 -16 -32 -16 2 polygon
+1 1.00 -64 16 -32 16 2 polygon
+1 1.00 -64 48 -32 48 2 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+endgate
+} def
+
+/OR3 {
+begingate
+1 1.00 -40 48 -8 48 2 polygon
+1 1.00 -40 -48 -8 -48 2 polygon
+1 1.00 -24 -32 -24 32 -40 48 -40 -48 spline
+1 1.00 8 -48 24 -32 32 0 -8 -48 spline
+1 1.00 32 0 64 0 2 polygon
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -28 0 -64 0 2 polygon
+1 1.00 -64 -32 -32 -32 2 polygon
+1 1.00 8 48 24 32 32 0 -8 48 spline
+endgate
+} def
+
+/OR4 {
+begingate
+1 1.00 -40 64 -8 64 2 polygon
+1 1.00 -40 -64 -8 -64 2 polygon
+1 1.00 -24 -48 -24 48 -40 64 -40 -64 spline
+1 1.00 48 0 80 0 2 polygon
+1 1.00 -34 48 -64 48 2 polygon
+1 1.00 -29 16 -64 16 2 polygon
+1 1.00 -64 -16 -29 -16 2 polygon
+1 1.00 -64 -48 -34 -48 2 polygon
+1 1.00 8 -64 40 -40 48 0 -8 -64 spline
+1 1.00 8 64 40 40 48 0 -8 64 spline
+endgate
+} def
+
+/OR8 {
+begingate
+1 1.00 -40 64 -8 64 2 polygon
+1 1.00 -40 -72 -8 -72 2 polygon
+1 1.00 -24 -56 -24 48 -40 64 -40 -72 spline
+1 1.00 48 0 80 0 2 polygon
+1 1.00 -34 48 -64 48 2 polygon
+1 1.00 -29 16 -64 16 2 polygon
+1 1.00 -64 -16 -29 -16 2 polygon
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 8 -72 32 -48 48 0 -8 -72 spline
+1 1.00 -64 32 -30 32 2 polygon
+1 1.00 -64 0 -28 0 2 polygon
+1 1.00 -64 -32 -30 -32 2 polygon
+1 1.00 -64 -64 -36 -64 2 polygon
+1 1.00 8 64 32 48 48 0 -8 64 spline
+endgate
+} def
+
+/NOR3 {
+begingate
+1 1.00 -40 48 -8 48 2 polygon
+1 1.00 -40 -48 -8 -48 2 polygon
+1 1.00 -24 -32 -24 32 -40 48 -40 -48 spline
+1 1.00 8 -48 24 -32 32 0 -8 -48 spline
+1 1.00 48 0 64 0 2 polygon
+1 1.00 -32 32 -64 32 2 polygon
+1 1.00 -28 0 -64 0 2 polygon
+1 1.00 -64 -32 -32 -32 2 polygon
+1 1.00 8 48 24 32 32 0 -8 48 spline
+1 1.00 40 0 8 0.00 360.00 xcarc
+endgate
+} def
+
+/NOR4 {
+begingate
+1 1.00 -40 64 -8 64 2 polygon
+1 1.00 -40 -64 -8 -64 2 polygon
+1 1.00 -24 -48 -24 48 -40 64 -40 -64 spline
+1 1.00 64 0 80 0 2 polygon
+1 1.00 -34 48 -64 48 2 polygon
+1 1.00 -29 16 -64 16 2 polygon
+1 1.00 -64 -16 -29 -16 2 polygon
+1 1.00 -64 -48 -34 -48 2 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+1 1.00 8 -64 40 -40 48 0 -8 -64 spline
+1 1.00 8 64 40 40 48 0 -8 64 spline
+endgate
+} def
+
+/NOR8 {
+begingate
+1 1.00 -40 64 -8 64 2 polygon
+1 1.00 -40 -72 -8 -72 2 polygon
+1 1.00 -24 -56 -24 48 -40 64 -40 -72 spline
+1 1.00 64 0 80 0 2 polygon
+1 1.00 -34 48 -64 48 2 polygon
+1 1.00 -29 16 -64 16 2 polygon
+1 1.00 -64 -16 -29 -16 2 polygon
+1 1.00 8 -72 40 -40 48 0 -8 -72 spline
+1 1.00 -64 -48 -32 -48 2 polygon
+1 1.00 8 64 32 48 48 0 -8 64 spline
+1 1.00 -64 32 -30 32 2 polygon
+1 1.00 -64 0 -28 0 2 polygon
+1 1.00 -64 -32 -30 -32 2 polygon
+1 1.00 -64 -64 -36 -64 2 polygon
+1 1.00 56 0 8 0.00 360.00 xcarc
+endgate
+} def
+
+/TPOS {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 -16 -32 -16 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 0 -16 -16 -32 -32 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(T) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+endgate
+} def
+
+/TNEG {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 -16 -48 -16 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 0 -16 -16 -32 -32 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(T) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -40 -16 8 0.00 360.00 xcarc
+endgate
+} def
+
+/DPOS {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 -16 -32 -16 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 0 -16 -16 -32 -32 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(D) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+endgate
+} def
+
+/DNEG {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 -16 -48 -16 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 0 -16 -16 -32 -32 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(D) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -40 -16 8 0.00 360.00 xcarc
+endgate
+} def
+
+/GDNEG {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 0 -48 0 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 16 -16 0 -32 -16 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(G) {/Times-Roman cf} 2 4 0 0.65 -24 -32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -40 0 8 0.00 360.00 xcarc
+1 1.00 -64 -32 -32 -32 2 polygon
+(D) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+endgate
+} def
+
+/GDPOS {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 0 -32 0 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -16 64 -16 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 16 -16 0 -32 -16 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -16 label
+(G) {/Times-Roman cf} 2 4 0 0.65 -24 -32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -64 -32 -32 -32 2 polygon
+(D) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+1 1.00 -64 32 -32 32 2 polygon
+endgate
+} def
+
+/JKNEG {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 0 -48 0 2 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -32 64 -32 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 16 -16 0 -32 -16 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -40 0 8 0.00 360.00 xcarc
+1 1.00 -64 -32 -32 -32 2 polygon
+(J) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(K) {/Times-Roman cf} 2 4 0 0.65 -24 -32 label
+endgate
+} def
+
+/JKPOS {
+begingate
+0 1.00 -32 -48 -32 48 32 48 32 -48 4 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -32 64 -32 2 polygon
+1 1.00 0 -56 8 0.00 360.00 xcarc
+1 1.00 0 -64 0 -80 2 polygon
+1 1.00 0 56 8 0.00 360.00 xcarc
+1 1.00 0 64 0 80 2 polygon
+1 1.00 -32 16 -16 0 -32 -16 3 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -64 -32 -32 -32 2 polygon
+(J) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(K) {/Times-Roman cf} 2 4 0 0.65 -24 -32 label
+1 1.00 -32 0 -64 0 2 polygon
+endgate
+} def
+
+/LATCH {
+begingate
+0 1.00 -32 -56 -32 56 32 56 32 -56 4 polygon
+1 1.00 -64 32 -32 32 2 polygon
+1 1.00 32 32 64 32 2 polygon
+1 1.00 32 -32 64 -32 2 polygon
+(Q) {ol} {/Times-Roman cf} 3 7 0 0.65 24 -32 label
+(Q) {/Times-Roman cf} 2 7 0 0.65 24 32 label
+1 1.00 -64 -32 -32 -32 2 polygon
+(D) {/Times-Roman cf} 2 4 0 0.65 -24 32 label
+(L) {/Times-Roman cf} 2 4 0 0.65 -24 -32 label
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/musiclib.lps b/lib/musiclib.lps
new file mode 100644
index 0000000..a8a9e75
--- /dev/null
+++ b/lib/musiclib.lps
@@ -0,0 +1,701 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.6
+% Library name is: musiclib
+% Author: R. Timothy Edwards <tim@khachaturian.tim.linglan.net>
+%
+
+% Depend musiclib::qn musiclib::hd
+% Depend musiclib::qnd musiclib::qn
+% Depend musiclib::qstem1 musiclib::qn musiclib::lnt
+% Depend musiclib::qstem2 musiclib::qn musiclib::lnt
+% Depend musiclib::qstem3 musiclib::qn musiclib::lnt
+% Depend musiclib::qstem4 musiclib::qn musiclib::lnt
+% Depend musiclib::hn musiclib::hhd
+% Depend musiclib::hnd musiclib::hn
+% Depend musiclib::hnd2 musiclib::lnt musiclib::hn
+% Depend musiclib::hnd3 musiclib::lnt musiclib::hn
+% Depend musiclib::hnt musiclib::lnt musiclib::hn
+% Depend musiclib::hnt2 musiclib::hn musiclib::lnt
+% Depend musiclib::wnt musiclib::lnt musiclib::wn
+% Depend musiclib::en musiclib::qn musiclib::flg
+% Depend musiclib::en2 musiclib::qn musiclib::flg
+% Depend musiclib::ent musiclib::en2 musiclib::lnt
+% Depend musiclib::ent2 musiclib::en musiclib::lnt
+% Depend musiclib::ent3 musiclib::en musiclib::lnt
+% Depend musiclib::ent4 musiclib::en2 musiclib::lnt
+% Depend musiclib::sn musiclib::qn musiclib::flg
+% Depend musiclib::sn2 musiclib::qn
+% Depend musiclib::sr musiclib::er
+% Depend musiclib::keyBf musiclib::flt
+% Depend musiclib::keyEf musiclib::flt
+% Depend musiclib::keyDf musiclib::flt
+% Depend musiclib::cuttime musiclib::common
+% Depend musiclib::pedalstop musiclib::ppin
+% Depend musiclib::rept musiclib::ddot
+% Depend musiclib::gliss musiclib::blip
+% Depend musiclib::staff musiclib::lines musiclib::br1 musiclib::bar musiclib::tclef musiclib::bclef
+% Depend musiclib::doublet musiclib::qn
+% Depend musiclib::triplet musiclib::qn musiclib::hd
+
+% XCircuitLib library objects
+/musiclib::lnt {
+begingate
+1 1.750 -4 0 60 0 2 polygon
+endgate
+} def
+
+/musiclib::hd {
+begingate
+6 9 beginpath
+-2 25 -38 9 -30 -9 curveto
+-22 -25 14 -9 6 9 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::qn {
+begingate
+1.000 0 -7 16 musiclib::hd
+1 1.000 0 18 0 128 2 polygon
+endgate
+} def
+
+/musiclib::qnd {
+begingate
+1.000 180 -40 32 musiclib::qn
+endgate
+} def
+
+/musiclib::qstem1 {
+begingate
+1.000 180 -40 32 musiclib::qn
+1.000 0 -48 16 musiclib::lnt
+endgate
+} def
+
+/musiclib::qstem2 {
+begingate
+1.000 180 -40 32 musiclib::qn
+1.000 0 -52 0 musiclib::lnt
+endgate
+} def
+
+/musiclib::qstem3 {
+begingate
+1.000 0 0 0 musiclib::qn
+1.000 0 -48 16 musiclib::lnt
+endgate
+} def
+
+/musiclib::qstem4 {
+begingate
+1.000 0 0 0 musiclib::qn
+1.000 0 -45 32 musiclib::lnt
+endgate
+} def
+
+/musiclib::hhd {
+begingate
+6 28 beginpath
+16 12 -20 -12 -30 4 curveto
+-24 -6 12 20 6 28 curveto
+-4 44 -40 20 -30 4 curveto
+-36 12 0
+38 6 28 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::hn {
+begingate
+1 1.000 0 23 0 128 2 polygon
+1.000 0 -8 0 musiclib::hhd
+endgate
+} def
+
+/musiclib::hnd {
+begingate
+1.000 180 -40 32 musiclib::hn
+endgate
+} def
+
+/musiclib::hnd2 {
+begingate
+1.000 0 -48 0 musiclib::lnt
+1.000 180 -40 32 musiclib::hn
+endgate
+} def
+
+/musiclib::hnd3 {
+begingate
+1.000 0 -48 16 musiclib::lnt
+1.000 180 -40 32 musiclib::hn
+endgate
+} def
+
+/musiclib::hnt {
+begingate
+1.000 0 -48 16 musiclib::lnt
+1.000 0 0 0 musiclib::hn
+endgate
+} def
+
+/musiclib::hnt2 {
+begingate
+1.000 0 0 0 musiclib::hn
+1.000 0 -44 32 musiclib::lnt
+endgate
+} def
+
+/musiclib::wn {
+begingate
+-28 32 beginpath
+-48 32 -28 0 -12 0 curveto
+-52 0 -52 32 -28 32 curveto
+12 32 12 0 -12 0 curveto
+8 0 -12
+32 -28 32 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::wnt {
+begingate
+1.000 0 -49 16 musiclib::lnt
+1.000 0 0 0 musiclib::wn
+endgate
+} def
+
+/musiclib::flg {
+begingate
+0 76 beginpath
+0 32 68 8 28 -52 curveto
+64 0 0 32 0 32 curveto
+240 1.000 endpath
+endgate
+} def
+
+/musiclib::en {
+begingate
+1.000 0 0 0 musiclib::qn
+1.000 0 0 78 musiclib::flg
+endgate
+} def
+
+/musiclib::en2 {
+begingate
+1.000 180 -40 32 musiclib::qn
+-1.000 180 -40 -54 musiclib::flg
+endgate
+} def
+
+/musiclib::ent {
+begingate
+1.000 0 0 0 musiclib::en2
+1.000 0 -48 16 musiclib::lnt
+endgate
+} def
+
+/musiclib::ent2 {
+begingate
+1.000 0 0 0 musiclib::en
+1.000 0 -44 16 musiclib::lnt
+endgate
+} def
+
+/musiclib::ent3 {
+begingate
+1.000 0 0 0 musiclib::en
+1.000 0 -44 32 musiclib::lnt
+endgate
+} def
+
+/musiclib::ent4 {
+begingate
+1.000 0 0 0 musiclib::en2
+1.000 0 -52 0 musiclib::lnt
+endgate
+} def
+
+/musiclib::sn {
+begingate
+1.000 0 0 0 musiclib::qn
+0 188 beginpath
+0 144 56 120 36 72 curveto
+52 104 0 144 0 144 curveto
+240 1.000 endpath
+1.000 0 0 72 musiclib::flg
+endgate
+} def
+
+/musiclib::sn2 {
+begingate
+1.000 180 -40 32 musiclib::qn
+-40 -136 beginpath
+-40 -92 16 -68 -4 -20 curveto
+12 -52 -40 -92 -40 -92 curveto
+240 1.000 endpath
+-40 -96 beginpath
+-40 -52 12 -36 -4 4 curveto
+8 -24 -40 -52 -40 -52 curveto
+240 1.000 endpath
+endgate
+} def
+
+/musiclib::flt {
+begingate
+1 1.000 -8 71 -8 -1 2 polygon
+-8 -2 beginpath
+32 22 12 46 -8 30 curveto
+2 40 20 22 -8 -2 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::shp {
+begingate
+240 1.000 -16 24 16 32 16 40 -16 32 4 polygon
+240 1.000 -16 -8 16 0 16 8 -16 0 4 polygon
+1 1.000 -8 56 -8 -28 2 polygon
+1 1.000 8 -24 8 60 2 polygon
+endgate
+} def
+
+/musiclib::nat {
+begingate
+240 1.000 -14 -8 8 0 8 8 -14 0 4 polygon
+240 1.000 -14 24 8 32 8 40 -14 32 4 polygon
+1 1.000 -14 62 -14 -8 2 polygon
+1 1.000 8 -32 8 40 2 polygon
+endgate
+} def
+
+/musiclib::hr {
+begingate
+240 1.000 -24 0 -24 16 20 16 20 0 4 polygon
+endgate
+} def
+
+/musiclib::qr {
+begingate
+1 1.000 3 41 -1 49 2 polygon
+1 1.000 14 -34 -14 6 2 polygon
+8 -26 beginpath
+-2 -12 -30 -22 -6 -50 curveto
+-20 -36 -4 -24 14 -34 curveto
+241 1.000 endpath
+-14 6 beginpath
+-10 30 6 34 -2 50 curveto
+10 26 1 polyc
+-2 14 -6 -6 0 -14 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::er {
+begingate
+1 1.300 -3 39 -20 -8 2 polygon
+241 1.000 -24 36 6 0.000 360.000 xcarc
+1 1.000 -18 44 16 237.000 337.000 xcarc
+endgate
+} def
+
+/musiclib::sr {
+begingate
+241 1.000 -34 12 6 0.000 360.000 xcarc
+1 1.000 -28 20 16 237.000 337.000 xcarc
+1.000 0 -3 -6 musiclib::er
+endgate
+} def
+
+/musiclib::fermata {
+begingate
+241 1.000 0 -12 4 0.000 360.000 xcarc
+-32 -12 beginpath
+-24 28 24 28 32 -12 curveto
+28 16 -28 16 -32 -12 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::br1 {
+begingate
+0 96 beginpath
+-76 52 60 -100 -32 -160 curveto
+44 -116 -92 36 0 96 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::tclef {
+begingate
+1 1.000 -2 -26 16 180.000 360.000 xcarc
+241 1.000 -8 -26 10 0.000 360.000 xcarc
+1 1.000 14 -26 -4 112 2 polygon
+-4 12 beginpath
+-20 20 -16 50 12 50 curveto
+42 50 36 0 4 0 curveto
+48 0 52 64 12 64 curveto
+-20 64 -28
+20 -4 12 curveto
+241 1.000 endpath
+4 0 beginpath
+-24 0 -32 16 -32 32 curveto
+-32 80 30 84 30 140 curveto
+30 170 -10 140 -4 112 curveto
+-10
+156 12 164 22 168 curveto
+28 158 30 152 30 140 curveto
+30 108 -44 92 -44 40 curveto
+-44 8 -16 0 4 0 curveto
+241
+1.000 endpath
+endgate
+} def
+
+/musiclib::bclef {
+begingate
+1 1.000 0 5 27 90.000 192.000 xcarc
+241 1.000 48 16 3 0.000 360.000 xcarc
+241 1.000 48 -15 3 0.000 360.000 xcarc
+241 1.000 -17 3 10 0.000 360.000 xcarc
+36 -4 beginpath
+36 -44 8 -60 -28 -68 curveto
+40 -52 32 32 0 32 curveto
+28 32 36 12 36 -4 curveto
+241
+1.000 endpath
+endgate
+} def
+
+/musiclib::keyBf {
+begingate
+1.000 0 -18 -17 musiclib::flt
+1.000 0 14 31 musiclib::flt
+endgate
+} def
+
+/musiclib::keyEf {
+begingate
+1.000 0 -18 -17 musiclib::flt
+1.000 0 14 31 musiclib::flt
+1.000 0 46 -33 musiclib::flt
+endgate
+} def
+
+/musiclib::keyDf {
+begingate
+1.000 0 -96 -48 musiclib::flt
+1.000 0 -64 0 musiclib::flt
+1.000 0 -32 -64 musiclib::flt
+1.000 0 0 -16 musiclib::flt
+1.000 0 32 -80 musiclib::flt
+endgate
+} def
+
+/musiclib::dot {
+begingate
+248 1.000 0 0 6 0.000 360.000 xcarc
+endgate
+} def
+
+/musiclib::ddot {
+begingate
+241 1.000 0 16 5 0.000 360.000 xcarc
+241 1.000 0 -16 5 0.000 360.000 xcarc
+endgate
+} def
+
+/musiclib::common {
+begingate
+241 1.000 14 18 8 -180.000 180.000 xcarc
+1 1.000 18 30 20 26 22 20 8 32 spline
+1 1.000 18 -26 22 -20 24 -14 14 -28 spline
+-24 0 beginpath
+-24 16 -16 36 8 32 curveto
+-20 38 -18 -48 14 -28 curveto
+4 -36 -24 -32 -24 0 curveto
+241
+1.000 endpath
+endgate
+} def
+
+/musiclib::cuttime {
+begingate
+1.000 0 0 0 musiclib::common
+1 1.000 2 46 2 -46 2 polygon
+endgate
+} def
+
+/musiclib::two {
+begingate
+241 1.000 -10 18 8 0.000 360.000 xcarc
+1 1.000 -14 30 -16 26 -18 20 -4 32 spline
+1 1.000 -18 -20 -18 -16 2 -6 -24 -32 spline
+26 -12 beginpath
+26 -50 -14 -20 -24 -32 curveto
+-8 0 26 -34 26 -12 curveto
+241 1.000 endpath
+-4 32 beginpath
+16 34 22 4 2 -6 curveto
+24 2 26 8 26 18 curveto
+26 24 20 36 -4 32 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::three {
+begingate
+241 1.000 -14 -18 8 0.000 360.000 xcarc
+1 1.000 -18 -30 -20 -26 -22 -20 -8 -32 spline
+241 1.000 -14 18 8 0.000 360.000 xcarc
+1 1.000 -18 30 -20 26 -22 20 -8 32 spline
+-6 0 beginpath
+16 0 22 6 22 18 curveto
+22 24 16 36 -8 32 curveto
+12 34 18 0 -6 0 curveto
+16 0 22 -6 22
+-18 curveto
+22 -24 16 -34 -8 -32 curveto
+12 -34 18 0 -6 0 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::four {
+begingate
+1 1.000 -24 -10 24 -10 2 polygon
+12 -24 beginpath
+11 -28 15 -31 20 -32 curveto
+-10 -32 1 polyc
+-5 -31 -2 -28 -2 -24 curveto
+12
+-24 12 18 -2 2 3 polyc
+241 1.000 endpath
+-24 -10 beginpath
+-16 0 -6 20 -6 28 curveto
+-22 -10 14 32 2 polyc
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::six {
+begingate
+241 1.000 12 20 8 0.000 360.000 xcarc
+1 1.000 16 30 18 26 20 20 6 32 spline
+1 1.000 -6 4 -12 -4 -10 -14 0 4 spline
+0 4 beginpath
+14 5 12 -34 0 -32 curveto
+-26 -32 -24 -4 -24 0 curveto
+-24 8 -20 36 6 32 curveto
+-14 34
+-16 -32 0 -32 curveto
+20 -32 22 -20 22 -12 curveto
+22 2 8 6 0 4 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::eight {
+begingate
+1 1.000 -6 -34 8 -34 14 -30 -12 -30 spline
+-10 30 beginpath
+-22 24 -30 4 0 -6 curveto
+20 -14 22 -24 14 -30 curveto
+26 -24 34 0 4 10 curveto
+-14 16
+-18 24 -10 30 curveto
+241 1.000 endpath
+-12 -30 beginpath
+-18 -26 -22 -14 -14 0 curveto
+-24 -6 -28 -22 -12 -30 curveto
+241 1.000 endpath
+14 30 beginpath
+22 22 20 10 16 4 curveto
+22 8 30 22 14 30 curveto
+241 1.000 endpath
+1 1.000 -4 34 8 34 14 30 -10 30 spline
+endgate
+} def
+
+/musiclib::nine {
+begingate
+241 1.000 -16 -18 8 0.000 360.000 xcarc
+1 1.000 -20 -30 -22 -26 -24 -20 -10 -32 spline
+1 1.000 4 -4 8 0 9 10 -4 -4 spline
+-4 -4 beginpath
+-18 -5 -16 34 -4 32 curveto
+15 32 16 -39 -10 -32 curveto
+26 -34 24 -6 24 0 curveto
+24 4
+26 32 -4 32 curveto
+-24 32 -26 20 -26 12 curveto
+-26 -2 -13 -4 -4 -4 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::pedal {
+begingate
+1 1.000 -22 34 -32 32 -36 30 -12 30 spline
+4 -28 beginpath
+-8 -18 -30 -34 -32 -32 curveto
+-34 -30 -18 -24 -4 -32 curveto
+4 -28 1 polyc
+241
+1.000 endpath
+-20 -28 beginpath
+-6 0 -32 12 -26 32 curveto
+-40 4 -14 -8 -20 -28 curveto
+241 1.000 endpath
+-18 18 beginpath
+-6 2 4 22 -12 30 curveto
+18 18 -8 -12 -18 18 curveto
+241 1.000 endpath
+-36 30 beginpath
+-60 18 -52 -10 -34 6 curveto
+-50 -4 -48 24 -36 30 curveto
+241 1.000 endpath
+1 1.000 22 -18 20 0 12 0 4 -28 spline
+44 -30 beginpath
+30 -36 24 -4 32 0 curveto
+20 -6 20 -40 44 -30 curveto
+62 -20 42 22 12 16 curveto
+36 24
+52 -24 44 -30 curveto
+241 1.000 endpath
+12 0 beginpath
+-2 0 0 -44 26 -28 curveto
+8 -40 4 0 12 0 curveto
+241 1.000 endpath
+241 1.000 58 -30 2 0.000 360.000 xcarc
+endgate
+} def
+
+/musiclib::ppin {
+% hidden
+begingate
+3 -12 beginpath
+3 -9 1 polyc
+-1 -8 0 1 2 2 curveto
+5 4 6 7 5 10 curveto
+3 13 0 14 -2 13 curveto
+-5 11 -6
+8 -5 5 curveto
+-4 4 -3 3 -2 2 curveto
+0 1 1 -8 -3 -9 curveto
+-3 -12 1 polyc
+-1 -10 1 -10 2 -12 curveto
+241
+1.000 endpath
+endgate
+} def
+
+/musiclib::blip {
+% hidden
+begingate
+0 -16 beginpath
+-24 8 12 4 0 16 curveto
+24 -8 -12 -4 0 -16 curveto
+241 1.000 endpath
+endgate
+} def
+
+/musiclib::pedalstop {
+begingate
+-1.000 45 11 11 musiclib::ppin
+1.000 0 0 15 musiclib::ppin
+1.000 90 15 0 musiclib::ppin
+-1.000 225 -11 -11 musiclib::ppin
+-1.000 315 -11 11 musiclib::ppin
+-1.000 270 -15 0 musiclib::ppin
+-1.000 180 0 -15 musiclib::ppin
+-1.000 135 11 -11 musiclib::ppin
+endgate
+} def
+
+/musiclib::rept {
+begingate
+240 1.000 -32 -256 -32 256 -16 256 -16 -256 4 polygon
+1 1.000 0 256 0 -256 2 polygon
+1.000 0 16 192 musiclib::ddot
+1.000 0 16 -192 musiclib::ddot
+endgate
+} def
+
+/musiclib::gliss {
+begingate
+1.000 0 0 80 musiclib::blip
+1.000 0 0 16 musiclib::blip
+1.000 0 0 48 musiclib::blip
+1.000 0 0 -16 musiclib::blip
+1.000 0 0 -80 musiclib::blip
+1.000 0 0 -48 musiclib::blip
+endgate
+} def
+
+/musiclib::bar {
+begingate
+1 1.500 0 256 0 -256 2 polygon
+endgate
+} def
+
+/musiclib::lines {
+begingate
+1 1.000 0 -32 3552 -32 2 polygon
+1 1.000 0 64 3552 64 2 polygon
+1 1.000 0 0 3552 0 2 polygon
+1 1.000 0 32 3552 32 2 polygon
+1 1.000 0 -64 3552 -64 2 polygon
+endgate
+} def
+
+/musiclib::staff {
+begingate
+1.000 0 64 -192 musiclib::lines
+1.000 0 64 192 musiclib::lines
+-1.000 180 48 -160 musiclib::br1
+1.000 0 48 160 musiclib::br1
+1.000 0 64 0 musiclib::bar
+1.000 0 3616 0 musiclib::bar
+1.000 0 144 128 musiclib::tclef
+1.000 0 128 -160 musiclib::bclef
+endgate
+} def
+
+/musiclib::doublet {
+<</p_xps 64 /p_yps -64 /p_yps2 80 (expr @p_yps + 144) pop /p_yps3 64
+(expr @p_yps + 128) pop >> begingate
+1.000 0 -32 -96 musiclib::qn
+1.000 0 p_xps p_yps musiclib::qn
+496 1.000 -32 32 -32 48 p_xps p_yps2 p_xps p_yps3 4 polygon
+endgate
+} def
+
+/musiclib::triplet {
+<</p_yps3 96 (expr @p_yps + 128) pop
+ /p_yps2 112 (expr @p_yps + 144) pop
+ /p_yps -32 /p_xps 160 /p_yps4 -48
+ /p_xps2 64 (expr -32 + (@p_xps + 32) / 2) pop
+ /p_xps3 72 (expr @p_xps2 + 7) pop
+ /p_yps5 64 (expr 8 + (32 + @p_yps3) / 2) pop >> begingate
+1.000 0 -32 -96 musiclib::qn
+1.000 0 p_xps p_yps musiclib::qn
+1.000 0 p_xps2 p_yps4 musiclib::hd
+1 1.000 p_xps3 p_yps4 p_xps3 p_yps5 2 polygon
+496 1.000 -32 32 -32 48 p_xps p_yps2 p_xps p_yps3 4 polygon
+endgate
+} def
+
+/musiclib::tie {
+<</p_xps -96 /p_yps -32 /p_xps2 96 /p_yps2 32 /p_xps3 0 /p_xps4 64
+/p_yps5 -24 /p_yps4 -18 (expr @p_yps5 + 6) pop
+/p_yps6 -56 /p_yps3 -50 (expr @p_yps6 + 6) pop >> begingate
+p_xps p_yps beginpath
+p_xps3 p_yps3 p_xps4 p_yps4 p_xps2 p_yps2 curveto
+p_xps4 p_yps5 p_xps3 p_yps6 p_xps p_yps curveto
+497 1.000 endpath
+endgate
+} def
+
+% EndLib
diff --git a/lib/pcb.lps b/lib/pcb.lps
new file mode 100644
index 0000000..c1cc605
--- /dev/null
+++ b/lib/pcb.lps
@@ -0,0 +1,1249 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: pcb
+% Author: R. Timothy Edwards <tim@opencircuitdesign.com>
+%
+
+% Depend cap300 polarized pin
+% Depend cap200 polarized pin
+% Depend res300 resistor pin
+% Depend regulator pin
+% Depend sip8 pin1 pin
+% Depend sip10 pin1 pin
+% Depend clock8 pin1 pin
+% Depend dip8 pin pin1
+% Depend dip14 pin pin1
+% Depend dip16 pin pin1
+% Depend dip20 pin1 pin
+% Depend dip24n pin pin1
+% Depend dip28n pin1 pin
+% Depend dip40 pin1 pin
+% Depend dio_port pin1 pin
+% Depend pga68 pin1 pin
+% Depend pga44 pin1 pin
+
+% XCircuitLib library objects
+/polarized {
+begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+endgate
+} def
+
+/pin {
+begingate
+1 5.00 0 0 12 0.00 360.00 xcarc
+endgate
+} def
+
+/cap300 {
+begingate
+1 1.00 0 64 0 96 2 polygon
+1 1.00 0 -96 0 -64 2 polygon
+1.00 0 0 0 polarized
+(+) {/Symbol cf} 2 24 0 1.00 32 32 label
+1.00 0 0 96 pin
+1.00 0 0 -96 pin
+endgate
+} def
+
+/cap200 {
+begingate
+1.00 0 0 0 polarized
+(+) {/Symbol cf} 2 24 0 1.00 32 32 label
+1.00 0 0 64 pin
+1.00 0 0 -64 pin
+endgate
+} def
+
+/resistor {
+begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+endgate
+} def
+
+/res300 {
+begingate
+1.00 0 0 0 resistor
+1 1.00 0 64 0 96 2 polygon
+1 1.00 0 -96 0 -64 2 polygon
+1.00 0 0 96 pin
+1.00 0 0 -96 pin
+endgate
+} def
+
+/regulator {
+begingate
+0 1.00 -96 -48 -96 48 96 48 96 -48 4 polygon
+1 1.00 -96 16 96 16 2 polygon
+1.00 0 64 -16 pin
+1.00 0 0 -16 pin
+1.00 0 -64 -16 pin
+endgate
+} def
+
+/pin1 {
+begingate
+8 0 beginpath
+0 0 8 0.00 360.00 arc
+15 0 15 -15 -15 -15 -15 15 15 15 15 0 6 polyc
+
+241 1.00 endpath
+endgate
+} def
+
+/sip8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -240 -32 -240 0 240 0 240 -32 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -160 16 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -32 16 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -96 16 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -224 16 label
+(6) {/Times-Roman cf} 2 29 180 0.75 96 16 label
+(7) {/Times-Roman cf} 2 29 180 0.75 160 16 label
+(5) {/Times-Roman cf} 2 29 180 0.75 32 16 label
+(8) {/Times-Roman cf} 2 29 180 0.75 224 16 label
+sce
+1.00 0 -224 -16 pin1
+1.00 0 -160 -16 pin
+1.00 0 -96 -16 pin
+1.00 0 -32 -16 pin
+1.00 0 32 -16 pin
+1.00 0 96 -16 pin
+1.00 0 160 -16 pin
+1.00 0 224 -16 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -160 -16 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -32 -16 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -96 -16 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -224 -16 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 96 -16 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 160 -16 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 32 -16 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 224 -16 pinlabel
+endgate
+} def
+
+/sip10 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -240 -32 -240 0 368 0 368 -32 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -160 16 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -32 16 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -96 16 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -224 16 label
+(6) {/Times-Roman cf} 2 29 180 0.75 96 16 label
+(7) {/Times-Roman cf} 2 29 180 0.75 160 16 label
+(5) {/Times-Roman cf} 2 29 180 0.75 32 16 label
+(8) {/Times-Roman cf} 2 29 180 0.75 224 16 label
+(9) {/Times-Roman cf} 2 29 180 0.75 288 16 label
+(10) {/Times-Roman cf} 2 29 180 0.75 352 16 label
+sce
+1.00 0 -224 -16 pin1
+1.00 0 -160 -16 pin
+1.00 0 -96 -16 pin
+1.00 0 -32 -16 pin
+1.00 0 32 -16 pin
+1.00 0 96 -16 pin
+1.00 0 160 -16 pin
+1.00 0 224 -16 pin
+1.00 0 288 -16 pin
+1.00 0 352 -16 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -160 -16 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -32 -16 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -96 -16 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -224 -16 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 96 -16 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 160 -16 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 32 -16 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 224 -16 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 288 -16 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 352 -16 pinlabel
+endgate
+} def
+
+/clock8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -96 -96 -96 96 96 96 96 -96 4 polygon
+0.000 0.000 1.000 scb
+(4) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(8) {/Times-Roman cf} 2 17 180 0.75 -96 64 label
+(5) {/Times-Roman cf} 2 17 180 0.75 96 64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+sce
+1.00 0 -96 -96 pin1
+1.00 0 96 -96 pin
+1.00 0 96 96 pin
+1.00 0 -96 96 pin
+1.000 0.000 0.000 scb
+(4) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -96 96 pinlabel
+(5) {/Times-Roman cf} 2 29 180 0.75 96 96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+endgate
+} def
+
+/dip8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 -80 112 -80 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(7) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(5) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(8) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.00 0 -272 -80 pin1
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(7) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(5) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+endgate
+} def
+
+/dip14 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 112 -80 112 112 -272 112 -272 -80 4 polygon
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(9) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 112 -80 pin
+1.00 0 48 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.00 0 -272 -80 pin1
+0.000 0.000 1.000 scb
+(12) {/Times-Roman cf} 2 17 180 0.75 -144 80 label
+(14) {/Times-Roman cf} 2 17 180 0.75 -272 80 label
+(13) {/Times-Roman cf} 2 17 180 0.75 -208 80 label
+(11) {/Times-Roman cf} 2 17 180 0.75 -80 80 label
+(10) {/Times-Roman cf} 2 17 180 0.75 -16 80 label
+(9) {/Times-Roman cf} 2 17 180 0.75 48 80 label
+(8) {/Times-Roman cf} 2 17 180 0.75 112 80 label
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+endgate
+} def
+
+/dip16 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 176 112 176 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(12) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(14) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(11) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(9) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 -208 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 48 -80 pin
+1.00 0 112 -80 pin
+1.00 0 176 -80 pin
+1.00 0 -272 -80 pin1
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(9) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+endgate
+} def
+
+/dip20 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 304 112 304 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(12) {/Times-Roman cf} 2 25 180 0.75 240 80 label
+(14) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+(11) {/Times-Roman cf} 2 25 180 0.75 304 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 29 180 0.75 304 -48 label
+(9) {/Times-Roman cf} 2 29 180 0.75 240 -48 label
+(18) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(17) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(19) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+sce
+1.00 0 -272 -80 pin1
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 240 112 pin
+1.00 0 304 112 pin
+1.00 0 304 -80 pin
+1.00 0 240 -80 pin
+1.00 0 176 -80 pin
+1.00 0 112 -80 pin
+1.00 0 48 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 240 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 304 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 304 -80 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 240 -80 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+endgate
+} def
+
+/dip24n {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 432 112 432 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(14) {/Times-Roman cf} 2 25 180 0.75 368 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 432 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 240 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 304 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 29 180 0.75 304 -48 label
+(9) {/Times-Roman cf} 2 29 180 0.75 240 -48 label
+(18) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(17) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(19) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(21) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(23) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(24) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(12) {/Times-Roman cf} 2 29 180 0.75 432 -48 label
+(11) {/Times-Roman cf} 2 29 180 0.75 368 -48 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 240 112 pin
+1.00 0 304 112 pin
+1.00 0 368 112 pin
+1.00 0 432 112 pin
+1.00 0 -272 -80 pin1
+1.00 0 -208 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 48 -80 pin
+1.00 0 112 -80 pin
+1.00 0 176 -80 pin
+1.00 0 240 -80 pin
+1.00 0 304 -80 pin
+1.00 0 368 -80 pin
+1.00 0 432 -80 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 368 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 432 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 240 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 304 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 304 -80 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 240 -80 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 432 -80 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 368 -80 pinlabel
+endgate
+} def
+
+/dip28n {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -416 -96 -416 96 416 96 416 -96 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -352 -64 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -224 -64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -32 64 label
+(24) {/Times-Roman cf} 2 25 180 0.75 -160 64 label
+(23) {/Times-Roman cf} 2 25 180 0.75 -96 64 label
+(21) {/Times-Roman cf} 2 25 180 0.75 32 64 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -288 -64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -416 -64 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -32 -64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -160 -64 label
+(16) {/Times-Roman cf} 2 25 180 0.75 352 64 label
+(15) {/Times-Roman cf} 2 25 180 0.75 416 64 label
+(8) {/Times-Roman cf} 2 29 180 0.75 32 -64 label
+(10) {/Times-Roman cf} 2 29 180 0.75 160 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(18) {/Times-Roman cf} 2 25 180 0.75 224 64 label
+(17) {/Times-Roman cf} 2 25 180 0.75 288 64 label
+(20) {/Times-Roman cf} 2 25 180 0.75 96 64 label
+(19) {/Times-Roman cf} 2 25 180 0.75 160 64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 -288 64 label
+(28) {/Times-Roman cf} 2 25 180 0.75 -416 64 label
+(27) {/Times-Roman cf} 2 25 180 0.75 -352 64 label
+(25) {/Times-Roman cf} 2 25 180 0.75 -224 64 label
+(11) {/Times-Roman cf} 2 29 180 0.75 224 -64 label
+(12) {/Times-Roman cf} 2 29 180 0.75 288 -64 label
+(14) {/Times-Roman cf} 2 29 180 0.75 416 -64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 352 -64 label
+sce
+1.00 0 -416 -96 pin1
+1.00 0 -352 -96 pin
+1.00 0 -288 -96 pin
+1.00 0 -224 -96 pin
+1.00 0 -160 -96 pin
+1.00 0 -96 -96 pin
+1.00 0 -32 -96 pin
+1.00 0 32 -96 pin
+1.00 0 96 -96 pin
+1.00 0 160 -96 pin
+1.00 0 224 -96 pin
+1.00 0 288 -96 pin
+1.00 0 352 -96 pin
+1.00 0 416 -96 pin
+1.00 0 416 96 pin
+1.00 0 352 96 pin
+1.00 0 288 96 pin
+1.00 0 224 96 pin
+1.00 0 160 96 pin
+1.00 0 96 96 pin
+1.00 0 32 96 pin
+1.00 0 -32 96 pin
+1.00 0 -96 96 pin
+1.00 0 -160 96 pin
+1.00 0 -224 96 pin
+1.00 0 -288 96 pin
+1.00 0 -352 96 pin
+1.00 0 -416 96 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -352 -96 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -224 -96 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -32 96 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 -160 96 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 -96 96 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 32 96 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -288 -96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -416 -96 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -32 -96 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -160 -96 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 352 96 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 416 96 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 32 -96 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 160 -96 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 224 96 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 288 96 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 96 96 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 160 96 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 -288 96 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 -416 96 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 -352 96 pinlabel
+(25) {/Times-Roman cf} 2 29 180 0.75 -224 96 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 224 -96 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 288 -96 pinlabel
+(14) {/Times-Roman cf} 2 17 180 0.75 416 -96 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 352 -96 pinlabel
+endgate
+} def
+
+/dip40 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -416 -96 -416 224 800 224 800 -96 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -352 -64 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -224 -64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 736 192 label
+(24) {/Times-Roman cf} 2 25 180 0.75 608 192 label
+(23) {/Times-Roman cf} 2 25 180 0.75 672 192 label
+(21) {/Times-Roman cf} 2 25 180 0.75 800 192 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -288 -64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -416 -64 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -32 -64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -160 -64 label
+(8) {/Times-Roman cf} 2 29 180 0.75 32 -64 label
+(10) {/Times-Roman cf} 2 29 180 0.75 160 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 480 192 label
+(28) {/Times-Roman cf} 2 25 180 0.75 352 192 label
+(27) {/Times-Roman cf} 2 25 180 0.75 416 192 label
+(25) {/Times-Roman cf} 2 25 180 0.75 544 192 label
+(11) {/Times-Roman cf} 2 29 180 0.75 224 -64 label
+(12) {/Times-Roman cf} 2 29 180 0.75 288 -64 label
+(14) {/Times-Roman cf} 2 29 180 0.75 416 -64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 352 -64 label
+(29) {/Times-Roman cf} 2 25 180 0.75 288 192 label
+(30) {/Times-Roman cf} 2 25 180 0.75 224 192 label
+(31) {/Times-Roman cf} 2 25 180 0.75 160 192 label
+(32) {/Times-Roman cf} 2 25 180 0.75 96 192 label
+(33) {/Times-Roman cf} 2 25 180 0.75 32 192 label
+(34) {/Times-Roman cf} 2 25 180 0.75 -32 192 label
+(35) {/Times-Roman cf} 2 25 180 0.75 -96 192 label
+(36) {/Times-Roman cf} 2 25 180 0.75 -160 192 label
+(37) {/Times-Roman cf} 2 25 180 0.75 -224 192 label
+(38) {/Times-Roman cf} 2 25 180 0.75 -288 192 label
+(39) {/Times-Roman cf} 2 25 180 0.75 -352 192 label
+(40) {/Times-Roman cf} 2 25 180 0.75 -416 192 label
+(15) {/Times-Roman cf} 2 29 180 0.75 480 -64 label
+(16) {/Times-Roman cf} 2 29 180 0.75 544 -64 label
+(17) {/Times-Roman cf} 2 29 180 0.75 608 -64 label
+(19) {/Times-Roman cf} 2 29 180 0.75 736 -64 label
+(18) {/Times-Roman cf} 2 29 180 0.75 672 -64 label
+(20) {/Times-Roman cf} 2 29 180 0.75 800 -64 label
+sce
+1.00 0 -416 -96 pin1
+1.00 0 -352 -96 pin
+1.00 0 -288 -96 pin
+1.00 0 -224 -96 pin
+1.00 0 -160 -96 pin
+1.00 0 -96 -96 pin
+1.00 0 -32 -96 pin
+1.00 0 32 -96 pin
+1.00 0 96 -96 pin
+1.00 0 160 -96 pin
+1.00 0 224 -96 pin
+1.00 0 288 -96 pin
+1.00 0 352 -96 pin
+1.00 0 416 -96 pin
+1.00 0 480 -96 pin
+1.00 0 544 -96 pin
+1.00 0 608 -96 pin
+1.00 0 672 -96 pin
+1.00 0 736 -96 pin
+1.00 0 800 -96 pin
+1.00 0 800 224 pin
+1.00 0 736 224 pin
+1.00 0 672 224 pin
+1.00 0 608 224 pin
+1.00 0 544 224 pin
+1.00 0 480 224 pin
+1.00 0 416 224 pin
+1.00 0 352 224 pin
+1.00 0 288 224 pin
+1.00 0 224 224 pin
+1.00 0 160 224 pin
+1.00 0 96 224 pin
+1.00 0 32 224 pin
+1.00 0 -32 224 pin
+1.00 0 -96 224 pin
+1.00 0 -160 224 pin
+1.00 0 -224 224 pin
+1.00 0 -288 224 pin
+1.00 0 -352 224 pin
+1.00 0 -416 224 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -352 -96 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -224 -96 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 736 224 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 608 224 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 672 224 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 800 224 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -288 -96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -416 -96 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -32 -96 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -160 -96 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 32 -96 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 160 -96 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 480 224 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 352 224 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 416 224 pinlabel
+(25) {/Times-Roman cf} 2 29 180 0.75 544 224 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 224 -96 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 288 -96 pinlabel
+(14) {/Times-Roman cf} 2 17 180 0.75 416 -96 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 352 -96 pinlabel
+(29) {/Times-Roman cf} 2 29 180 0.75 288 224 pinlabel
+(30) {/Times-Roman cf} 2 29 180 0.75 224 224 pinlabel
+(31) {/Times-Roman cf} 2 29 180 0.75 160 224 pinlabel
+(32) {/Times-Roman cf} 2 29 180 0.75 96 224 pinlabel
+(33) {/Times-Roman cf} 2 29 180 0.75 32 224 pinlabel
+(34) {/Times-Roman cf} 2 29 180 0.75 -32 224 pinlabel
+(35) {/Times-Roman cf} 2 29 180 0.75 -96 224 pinlabel
+(36) {/Times-Roman cf} 2 29 180 0.75 -160 224 pinlabel
+(37) {/Times-Roman cf} 2 29 180 0.75 -224 224 pinlabel
+(38) {/Times-Roman cf} 2 29 180 0.75 -288 224 pinlabel
+(39) {/Times-Roman cf} 2 29 180 0.75 -352 224 pinlabel
+(40) {/Times-Roman cf} 2 29 180 0.75 -416 224 pinlabel
+(15) {/Times-Roman cf} 2 17 180 0.75 480 -96 pinlabel
+(16) {/Times-Roman cf} 2 17 180 0.75 544 -96 pinlabel
+(17) {/Times-Roman cf} 2 17 180 0.75 608 -96 pinlabel
+(19) {/Times-Roman cf} 2 17 180 0.75 736 -96 pinlabel
+(18) {/Times-Roman cf} 2 17 180 0.75 672 -96 pinlabel
+(20) {/Times-Roman cf} 2 17 180 0.75 800 -96 pinlabel
+endgate
+} def
+
+/dio_port {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -768 -32 -768 32 768 32 768 -32 4 polygon
+0.000 0.000 1.000 scb
+(12) {/Times-Roman cf} 2 25 180 0.75 448 -64 label
+(14) {/Times-Roman cf} 2 25 180 0.75 384 -64 label
+(3) {/Times-Roman cf} 2 29 180 0.75 704 64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 768 64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 576 64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 640 64 label
+(16) {/Times-Roman cf} 2 25 180 0.75 320 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 512 64 label
+(18) {/Times-Roman cf} 2 25 180 0.75 256 -64 label
+(20) {/Times-Roman cf} 2 25 180 0.75 192 -64 label
+(2) {/Times-Roman cf} 2 25 180 0.75 768 -64 label
+(4) {/Times-Roman cf} 2 25 180 0.75 704 -64 label
+(6) {/Times-Roman cf} 2 25 180 0.75 640 -64 label
+(8) {/Times-Roman cf} 2 25 180 0.75 576 -64 label
+(10) {/Times-Roman cf} 2 25 180 0.75 512 -64 label
+(11) {/Times-Roman cf} 2 29 180 0.75 448 64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 384 64 label
+(15) {/Times-Roman cf} 2 29 180 0.75 320 64 label
+(17) {/Times-Roman cf} 2 29 180 0.75 256 64 label
+(19) {/Times-Roman cf} 2 29 180 0.75 192 64 label
+(21) {/Times-Roman cf} 2 29 180 0.75 128 64 label
+(23) {/Times-Roman cf} 2 29 180 0.75 64 64 label
+(25) {/Times-Roman cf} 2 29 180 0.75 0 64 label
+(27) {/Times-Roman cf} 2 29 180 0.75 -64 64 label
+(29) {/Times-Roman cf} 2 29 180 0.75 -128 64 label
+(31) {/Times-Roman cf} 2 29 180 0.75 -192 64 label
+(33) {/Times-Roman cf} 2 29 180 0.75 -256 64 label
+(35) {/Times-Roman cf} 2 29 180 0.75 -320 64 label
+(37) {/Times-Roman cf} 2 29 180 0.75 -384 64 label
+(39) {/Times-Roman cf} 2 29 180 0.75 -448 64 label
+(41) {/Times-Roman cf} 2 29 180 0.75 -512 64 label
+(43) {/Times-Roman cf} 2 29 180 0.75 -576 64 label
+(45) {/Times-Roman cf} 2 29 180 0.75 -640 64 label
+(47) {/Times-Roman cf} 2 29 180 0.75 -704 64 label
+(49) {/Times-Roman cf} 2 29 180 0.75 -768 64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 128 -64 label
+(24) {/Times-Roman cf} 2 25 180 0.75 64 -64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 0 -64 label
+(28) {/Times-Roman cf} 2 25 180 0.75 -64 -64 label
+(30) {/Times-Roman cf} 2 25 180 0.75 -128 -64 label
+(32) {/Times-Roman cf} 2 25 180 0.75 -192 -64 label
+(34) {/Times-Roman cf} 2 25 180 0.75 -256 -64 label
+(36) {/Times-Roman cf} 2 25 180 0.75 -320 -64 label
+(38) {/Times-Roman cf} 2 25 180 0.75 -384 -64 label
+(40) {/Times-Roman cf} 2 25 180 0.75 -448 -64 label
+(42) {/Times-Roman cf} 2 25 180 0.75 -512 -64 label
+(44) {/Times-Roman cf} 2 25 180 0.75 -576 -64 label
+(46) {/Times-Roman cf} 2 25 180 0.75 -640 -64 label
+(48) {/Times-Roman cf} 2 25 180 0.75 -704 -64 label
+(50) {/Times-Roman cf} 2 25 180 0.75 -768 -64 label
+sce
+1.00 0 768 32 pin1
+1.00 0 704 32 pin
+1.00 0 640 32 pin
+1.00 0 576 32 pin
+1.00 0 512 32 pin
+1.00 0 448 32 pin
+1.00 0 768 -32 pin
+1.00 0 704 -32 pin
+1.00 0 640 -32 pin
+1.00 0 576 -32 pin
+1.00 0 512 -32 pin
+1.00 0 448 -32 pin
+1.00 0 384 -32 pin
+1.00 0 384 32 pin
+1.00 0 320 32 pin
+1.00 0 256 32 pin
+1.00 0 320 -32 pin
+1.00 0 256 -32 pin
+1.00 0 192 -32 pin
+1.00 0 192 32 pin
+1.00 0 128 32 pin
+1.00 0 64 32 pin
+1.00 0 0 32 pin
+1.00 0 128 -32 pin
+1.00 0 64 -32 pin
+1.00 0 0 -32 pin
+1.00 0 -64 -32 pin
+1.00 0 -64 32 pin
+1.00 0 -128 32 pin
+1.00 0 -128 -32 pin
+1.00 0 -192 -32 pin
+1.00 0 -192 32 pin
+1.00 0 -256 32 pin
+1.00 0 -256 -32 pin
+1.00 0 -320 -32 pin
+1.00 0 -320 32 pin
+1.00 0 -384 32 pin
+1.00 0 -384 -32 pin
+1.00 0 -448 -32 pin
+1.00 0 -448 32 pin
+1.00 0 -512 32 pin
+1.00 0 -512 -32 pin
+1.00 0 -576 -32 pin
+1.00 0 -576 32 pin
+1.00 0 -640 32 pin
+1.00 0 -640 -32 pin
+1.00 0 -704 -32 pin
+1.00 0 -704 32 pin
+1.00 0 -768 32 pin
+1.00 0 -768 -32 pin
+1.000 0.000 0.000 scb
+(12) {/Times-Roman cf} 2 29 180 0.75 448 -32 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 384 -32 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 320 -32 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 256 -32 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 192 -32 pinlabel
+(2) {/Times-Roman cf} 2 29 180 0.75 768 -32 pinlabel
+(4) {/Times-Roman cf} 2 29 180 0.75 704 -32 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 640 -32 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 576 -32 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 512 -32 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 128 -32 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 64 -32 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 0 -32 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 -64 -32 pinlabel
+(30) {/Times-Roman cf} 2 29 180 0.75 -128 -32 pinlabel
+(32) {/Times-Roman cf} 2 29 180 0.75 -192 -32 pinlabel
+(34) {/Times-Roman cf} 2 29 180 0.75 -256 -32 pinlabel
+(36) {/Times-Roman cf} 2 29 180 0.75 -320 -32 pinlabel
+(38) {/Times-Roman cf} 2 29 180 0.75 -384 -32 pinlabel
+(40) {/Times-Roman cf} 2 29 180 0.75 -448 -32 pinlabel
+(42) {/Times-Roman cf} 2 29 180 0.75 -512 -32 pinlabel
+(44) {/Times-Roman cf} 2 29 180 0.75 -576 -32 pinlabel
+(46) {/Times-Roman cf} 2 29 180 0.75 -640 -32 pinlabel
+(48) {/Times-Roman cf} 2 29 180 0.75 -704 -32 pinlabel
+(50) {/Times-Roman cf} 2 29 180 0.75 -768 -32 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 704 32 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 768 32 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 576 32 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 640 32 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 512 32 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 448 32 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 384 32 pinlabel
+(15) {/Times-Roman cf} 2 17 180 0.75 320 32 pinlabel
+(17) {/Times-Roman cf} 2 17 180 0.75 256 32 pinlabel
+(19) {/Times-Roman cf} 2 17 180 0.75 192 32 pinlabel
+(21) {/Times-Roman cf} 2 17 180 0.75 128 32 pinlabel
+(23) {/Times-Roman cf} 2 17 180 0.75 64 32 pinlabel
+(25) {/Times-Roman cf} 2 17 180 0.75 0 32 pinlabel
+(27) {/Times-Roman cf} 2 17 180 0.75 -64 32 pinlabel
+(29) {/Times-Roman cf} 2 17 180 0.75 -128 32 pinlabel
+(31) {/Times-Roman cf} 2 17 180 0.75 -192 32 pinlabel
+(33) {/Times-Roman cf} 2 17 180 0.75 -256 32 pinlabel
+(35) {/Times-Roman cf} 2 17 180 0.75 -320 32 pinlabel
+(37) {/Times-Roman cf} 2 17 180 0.75 -384 32 pinlabel
+(39) {/Times-Roman cf} 2 17 180 0.75 -448 32 pinlabel
+(41) {/Times-Roman cf} 2 17 180 0.75 -512 32 pinlabel
+(43) {/Times-Roman cf} 2 17 180 0.75 -576 32 pinlabel
+(45) {/Times-Roman cf} 2 17 180 0.75 -640 32 pinlabel
+(47) {/Times-Roman cf} 2 17 180 0.75 -704 32 pinlabel
+(49) {/Times-Roman cf} 2 17 180 0.75 -768 32 pinlabel
+endgate
+} def
+
+/pga68 {
+begingate
+0.843 0.843 0.843 scb
+241 1.00 -448 -256 -384 -256 -384 -320 128 -320 128 -256 192 -256 192 256 128
+256 128 320 -384 320 -384 256 -448 256 -448 0 -384 0 -384 192 -320 192 -320 256
+64 256 64 192 128 192 128 -192 64 -192 64 -256 -320 -256 -320 -192 -384 -192
+-384 0 -448 0 -448 -256 29 polygon
+sce
+1 1.00 -432 -272 0 0.00 360.00 xcarc
+0.000 0.000 1.000 scb
+(10) {/Times-Roman cf} 2 20 180 0.75 -480 256 label
+(11) {/Times-Roman cf} 2 28 180 0.75 -400 272 label
+(12) {/Times-Roman cf} 2 20 180 0.75 -480 192 label
+(13) {/Times-Roman cf} 2 23 180 0.75 -352 176 label
+(14) {/Times-Roman cf} 2 20 180 0.75 -480 128 label
+(15) {/Times-Roman cf} 2 23 180 0.75 -352 128 label
+(16) {/Times-Roman cf} 2 20 180 0.75 -480 64 label
+(17) {/Times-Roman cf} 2 23 180 0.75 -352 64 label
+(18) {/Times-Roman cf} 2 20 180 0.75 -480 0 label
+(19) {/Times-Roman cf} 2 23 180 0.75 -352 0 label
+(20) {/Times-Roman cf} 2 20 180 0.75 -480 -64 label
+(21) {/Times-Roman cf} 2 23 180 0.75 -352 -64 label
+(22) {/Times-Roman cf} 2 20 180 0.75 -480 -128 label
+(23) {/Times-Roman cf} 2 23 180 0.75 -352 -128 label
+(24) {/Times-Roman cf} 2 20 180 0.75 -480 -192 label
+(25) {/Times-Roman cf} 2 23 180 0.75 -352 -176 label
+(27) {/Times-Roman cf} 2 25 180 0.75 -384 -368 label
+(28) {/Times-Roman cf} 2 24 180 0.75 -400 -288 label
+(29) {/Times-Roman cf} 2 25 180 0.75 -320 -368 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -128 352 label
+(2) {/Times-Roman cf} 2 25 180 0.75 -128 208 label
+(4) {/Times-Roman cf} 2 25 180 0.75 -192 208 label
+(6) {/Times-Roman cf} 2 25 180 0.75 -256 208 label
+(8) {/Times-Roman cf} 2 25 180 0.75 -320 208 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -192 352 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -256 352 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -320 352 label
+(9) {/Times-Roman cf} 2 29 180 0.75 -384 352 label
+(30) {/Times-Roman cf} 2 29 180 0.75 -320 -224 label
+(32) {/Times-Roman cf} 2 29 180 0.75 -256 -224 label
+(34) {/Times-Roman cf} 2 29 180 0.75 -192 -224 label
+(36) {/Times-Roman cf} 2 29 180 0.75 -128 -224 label
+(38) {/Times-Roman cf} 2 29 180 0.75 -64 -224 label
+(40) {/Times-Roman cf} 2 29 180 0.75 0 -224 label
+(42) {/Times-Roman cf} 2 29 180 0.75 64 -224 label
+(31) {/Times-Roman cf} 2 25 180 0.75 -256 -368 label
+(33) {/Times-Roman cf} 2 25 180 0.75 -192 -368 label
+(35) {/Times-Roman cf} 2 25 180 0.75 -128 -368 label
+(37) {/Times-Roman cf} 2 25 180 0.75 -64 -368 label
+(39) {/Times-Roman cf} 2 25 180 0.75 0 -368 label
+(41) {/Times-Roman cf} 2 25 180 0.75 64 -368 label
+(43) {/Times-Roman cf} 2 25 180 0.75 128 -368 label
+(44) {/Times-Roman cf} 2 23 180 0.75 224 -256 label
+(46) {/Times-Roman cf} 2 23 180 0.75 224 -192 label
+(48) {/Times-Roman cf} 2 23 180 0.75 224 -128 label
+(50) {/Times-Roman cf} 2 23 180 0.75 224 -64 label
+(52) {/Times-Roman cf} 2 23 180 0.75 224 0 label
+(54) {/Times-Roman cf} 2 23 180 0.75 224 64 label
+(56) {/Times-Roman cf} 2 23 180 0.75 224 128 label
+(58) {/Times-Roman cf} 2 23 180 0.75 224 192 label
+(60) {/Times-Roman cf} 2 23 180 0.75 224 256 label
+(61) {/Times-Roman cf} 2 29 180 0.75 128 352 label
+(63) {/Times-Roman cf} 2 29 180 0.75 64 352 label
+(65) {/Times-Roman cf} 2 29 180 0.75 0 352 label
+(67) {/Times-Roman cf} 2 29 180 0.75 -64 352 label
+(45) {/Times-Roman cf} 2 27 180 0.75 144 -288 label
+(47) {/Times-Roman cf} 2 20 180 0.75 96 -176 label
+(49) {/Times-Roman cf} 2 20 180 0.75 96 -128 label
+(51) {/Times-Roman cf} 2 20 180 0.75 96 -64 label
+(53) {/Times-Roman cf} 2 20 180 0.75 96 0 label
+(55) {/Times-Roman cf} 2 20 180 0.75 96 64 label
+(57) {/Times-Roman cf} 2 20 180 0.75 96 128 label
+(59) {/Times-Roman cf} 2 20 180 0.75 96 176 label
+(62) {/Times-Roman cf} 2 31 180 0.75 144 288 label
+(64) {/Times-Roman cf} 2 25 180 0.75 64 208 label
+(66) {/Times-Roman cf} 2 25 180 0.75 0 208 label
+(68) {/Times-Roman cf} 2 25 180 0.75 -64 208 label
+(26) {/Times-Roman cf} 2 20 180 0.75 -480 -256 label
+sce
+1.00 0 -128 320 pin1
+1.00 0 -384 -256 pin
+1.00 0 -320 -256 pin
+1.00 0 -384 -320 pin
+1.00 0 -320 -320 pin
+1.00 0 -256 -320 pin
+1.00 0 -192 -320 pin
+1.00 0 -128 -320 pin
+1.00 0 -64 -320 pin
+1.00 0 0 -320 pin
+1.00 0 64 -320 pin
+1.00 0 128 -320 pin
+1.00 0 128 -256 pin
+1.00 0 64 -256 pin
+1.00 0 0 -256 pin
+1.00 0 -64 -256 pin
+1.00 0 -128 -256 pin
+1.00 0 -192 -256 pin
+1.00 0 -256 -256 pin
+1.00 0 -448 -256 pin
+1.00 0 -448 -192 pin
+1.00 0 -384 -192 pin
+1.00 0 -384 -128 pin
+1.00 0 -384 -64 pin
+1.00 0 -384 0 pin
+1.00 0 -384 64 pin
+1.00 0 -384 128 pin
+1.00 0 -384 192 pin
+1.00 0 -384 256 pin
+1.00 0 -384 320 pin
+1.00 0 -448 256 pin
+1.00 0 -448 192 pin
+1.00 0 -448 128 pin
+1.00 0 -448 64 pin
+1.00 0 -448 0 pin
+1.00 0 -448 -64 pin
+1.00 0 -448 -128 pin
+1.00 0 192 -256 pin
+1.00 0 192 -192 pin
+1.00 0 128 -192 pin
+1.00 0 128 -128 pin
+1.00 0 192 -128 pin
+1.00 0 192 -64 pin
+1.00 0 128 -64 pin
+1.00 0 128 0 pin
+1.00 0 192 0 pin
+1.00 0 192 64 pin
+1.00 0 128 64 pin
+1.00 0 128 128 pin
+1.00 0 192 128 pin
+1.00 0 192 192 pin
+1.00 0 128 192 pin
+1.00 0 128 256 pin
+1.00 0 192 256 pin
+1.00 0 128 320 pin
+1.00 0 64 320 pin
+1.00 0 64 256 pin
+1.00 0 0 256 pin
+1.00 0 0 320 pin
+1.00 0 -64 320 pin
+1.00 0 -64 256 pin
+1.00 0 -128 256 pin
+1.00 0 -192 256 pin
+1.00 0 -192 320 pin
+1.00 0 -256 320 pin
+1.00 0 -256 256 pin
+1.00 0 -320 256 pin
+1.00 0 -320 320 pin
+1.000 0.000 0.000 scb
+(13) {/Times-Roman cf} 2 20 180 0.75 -384 192 pinlabel
+(15) {/Times-Roman cf} 2 20 180 0.75 -384 128 pinlabel
+(17) {/Times-Roman cf} 2 20 180 0.75 -384 64 pinlabel
+(19) {/Times-Roman cf} 2 20 180 0.75 -384 0 pinlabel
+(21) {/Times-Roman cf} 2 20 180 0.75 -384 -64 pinlabel
+(23) {/Times-Roman cf} 2 20 180 0.75 -384 -128 pinlabel
+(25) {/Times-Roman cf} 2 20 180 0.75 -384 -192 pinlabel
+(2) {/Times-Roman cf} 2 29 180 0.75 -128 256 pinlabel
+(4) {/Times-Roman cf} 2 29 180 0.75 -192 256 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -256 256 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -320 256 pinlabel
+(30) {/Times-Roman cf} 2 17 180 0.75 -320 -256 pinlabel
+(32) {/Times-Roman cf} 2 17 180 0.75 -256 -256 pinlabel
+(34) {/Times-Roman cf} 2 17 180 0.75 -192 -256 pinlabel
+(36) {/Times-Roman cf} 2 17 180 0.75 -128 -256 pinlabel
+(38) {/Times-Roman cf} 2 17 180 0.75 -64 -256 pinlabel
+(40) {/Times-Roman cf} 2 17 180 0.75 0 -256 pinlabel
+(42) {/Times-Roman cf} 2 17 180 0.75 64 -256 pinlabel
+(47) {/Times-Roman cf} 2 23 180 0.75 128 -192 pinlabel
+(49) {/Times-Roman cf} 2 23 180 0.75 128 -128 pinlabel
+(51) {/Times-Roman cf} 2 23 180 0.75 128 -64 pinlabel
+(53) {/Times-Roman cf} 2 23 180 0.75 128 0 pinlabel
+(55) {/Times-Roman cf} 2 23 180 0.75 128 64 pinlabel
+(57) {/Times-Roman cf} 2 23 180 0.75 128 128 pinlabel
+(59) {/Times-Roman cf} 2 23 180 0.75 128 192 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 64 256 pinlabel
+(66) {/Times-Roman cf} 2 29 180 0.75 0 256 pinlabel
+(68) {/Times-Roman cf} 2 29 180 0.75 -64 256 pinlabel
+(44) {/Times-Roman cf} 2 20 180 0.75 192 -256 pinlabel
+(46) {/Times-Roman cf} 2 20 180 0.75 192 -192 pinlabel
+(48) {/Times-Roman cf} 2 20 180 0.75 192 -128 pinlabel
+(50) {/Times-Roman cf} 2 20 180 0.75 192 -64 pinlabel
+(52) {/Times-Roman cf} 2 20 180 0.75 192 0 pinlabel
+(54) {/Times-Roman cf} 2 20 180 0.75 192 64 pinlabel
+(56) {/Times-Roman cf} 2 20 180 0.75 192 128 pinlabel
+(58) {/Times-Roman cf} 2 20 180 0.75 192 192 pinlabel
+(60) {/Times-Roman cf} 2 20 180 0.75 192 256 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -128 320 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -192 320 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -256 320 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -320 320 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 -384 320 pinlabel
+(61) {/Times-Roman cf} 2 17 180 0.75 128 320 pinlabel
+(63) {/Times-Roman cf} 2 17 180 0.75 64 320 pinlabel
+(65) {/Times-Roman cf} 2 17 180 0.75 0 320 pinlabel
+(67) {/Times-Roman cf} 2 17 180 0.75 -64 320 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 -384 -320 pinlabel
+(29) {/Times-Roman cf} 2 29 180 0.75 -320 -320 pinlabel
+(31) {/Times-Roman cf} 2 29 180 0.75 -256 -320 pinlabel
+(33) {/Times-Roman cf} 2 29 180 0.75 -192 -320 pinlabel
+(35) {/Times-Roman cf} 2 29 180 0.75 -128 -320 pinlabel
+(37) {/Times-Roman cf} 2 29 180 0.75 -64 -320 pinlabel
+(39) {/Times-Roman cf} 2 29 180 0.75 0 -320 pinlabel
+(41) {/Times-Roman cf} 2 29 180 0.75 64 -320 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 128 -320 pinlabel
+(10) {/Times-Roman cf} 2 23 180 0.75 -448 256 pinlabel
+(12) {/Times-Roman cf} 2 23 180 0.75 -448 192 pinlabel
+(14) {/Times-Roman cf} 2 23 180 0.75 -448 128 pinlabel
+(16) {/Times-Roman cf} 2 23 180 0.75 -448 64 pinlabel
+(18) {/Times-Roman cf} 2 23 180 0.75 -448 0 pinlabel
+(20) {/Times-Roman cf} 2 23 180 0.75 -448 -64 pinlabel
+(22) {/Times-Roman cf} 2 23 180 0.75 -448 -128 pinlabel
+(24) {/Times-Roman cf} 2 23 180 0.75 -448 -192 pinlabel
+(26) {/Times-Roman cf} 2 23 180 0.75 -448 -256 pinlabel
+(62) {/Times-Roman cf} 2 31 180 0.75 128 256 pinlabel
+(11) {/Times-Roman cf} 2 28 180 0.75 -384 256 pinlabel
+sce
+1 1.00 432 -256 0 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(45) {/Times-Roman cf} 2 19 180 0.75 128 -256 pinlabel
+(28) {/Times-Roman cf} 2 16 180 0.75 -384 -256 pinlabel
+endgate
+} def
+
+/pga44 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -192 -256 -192 -320 128 -320 128 -256 192 -256 192 64 128 64 128 128
+-192 128 -192 64 -256 64 -256 -128 -192 -128 -192 0 -128 0 -128 64 64 64 64 0
+128 0 128 -192 64 -192 64 -256 -128 -256 -128 -192 -192 -192 -192 -128 -256
+-128 -256 -256 28 polygon
+0.000 0.000 1.000 scb
+(7) {/Times-Roman cf} 2 20 180 0.75 -288 64 label
+(8) {/Times-Roman cf} 2 28 180 0.75 -216 96 label
+(9) {/Times-Roman cf} 2 20 180 0.75 -288 0 label
+(10) {/Times-Roman cf} 2 23 180 0.75 -160 -16 label
+(11) {/Times-Roman cf} 2 20 180 0.75 -288 -64 label
+(12) {/Times-Roman cf} 2 23 180 0.75 -160 -64 label
+(13) {/Times-Roman cf} 2 20 180 0.75 -288 -128 label
+(14) {/Times-Roman cf} 2 23 180 0.75 -160 -128 label
+(15) {/Times-Roman cf} 2 20 180 0.75 -288 -192 label
+(16) {/Times-Roman cf} 2 23 180 0.75 -160 -176 label
+(18) {/Times-Roman cf} 2 25 180 0.75 -192 -368 label
+(19) {/Times-Roman cf} 2 24 180 0.75 -224 -296 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -128 -368 label
+(1) {/Times-Roman cf} 2 21 180 0.75 0 16 label
+(3) {/Times-Roman cf} 2 25 180 0.75 -64 16 label
+(5) {/Times-Roman cf} 2 25 180 0.75 -128 16 label
+(2) {/Times-Roman cf} 2 29 180 0.75 -64 160 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -128 160 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -192 160 label
+(21) {/Times-Roman cf} 2 29 180 0.75 -128 -224 label
+(23) {/Times-Roman cf} 2 29 180 0.75 -64 -224 label
+(25) {/Times-Roman cf} 2 29 180 0.75 0 -224 label
+(27) {/Times-Roman cf} 2 29 180 0.75 64 -224 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -64 -368 label
+(24) {/Times-Roman cf} 2 25 180 0.75 0 -368 label
+(26) {/Times-Roman cf} 2 25 180 0.75 64 -368 label
+(28) {/Times-Roman cf} 2 25 180 0.75 128 -368 label
+(29) {/Times-Roman cf} 2 23 180 0.75 224 -256 label
+(31) {/Times-Roman cf} 2 23 180 0.75 224 -192 label
+(33) {/Times-Roman cf} 2 23 180 0.75 224 -128 label
+(35) {/Times-Roman cf} 2 23 180 0.75 224 -64 label
+(37) {/Times-Roman cf} 2 23 180 0.75 224 0 label
+(39) {/Times-Roman cf} 2 23 180 0.75 224 64 label
+(40) {/Times-Roman cf} 2 29 180 0.75 128 160 label
+(42) {/Times-Roman cf} 2 29 180 0.75 64 160 label
+(30) {/Times-Roman cf} 2 27 180 0.75 152 -296 label
+(32) {/Times-Roman cf} 2 20 180 0.75 96 -176 label
+(34) {/Times-Roman cf} 2 20 180 0.75 96 -128 label
+(36) {/Times-Roman cf} 2 20 180 0.75 96 -64 label
+(38) {/Times-Roman cf} 2 20 180 0.75 96 -16 label
+(41) {/Times-Roman cf} 2 31 180 0.75 160 96 label
+(43) {/Times-Roman cf} 2 25 180 0.75 64 16 label
+(17) {/Times-Roman cf} 2 20 180 0.75 -288 -256 label
+sce
+1.00 0 0 64 pin1
+1.00 0 -192 -256 pin
+1.00 0 -128 -256 pin
+1.00 0 -192 -320 pin
+1.00 0 -128 -320 pin
+1.00 0 -64 -320 pin
+1.00 0 0 -320 pin
+1.00 0 64 -320 pin
+1.00 0 128 -320 pin
+1.00 0 128 -256 pin
+1.00 0 64 -256 pin
+1.00 0 0 -256 pin
+1.00 0 -64 -256 pin
+1.00 0 -256 -256 pin
+1.00 0 -256 -192 pin
+1.00 0 -192 -192 pin
+1.00 0 -192 -128 pin
+1.00 0 -192 -64 pin
+1.00 0 -192 0 pin
+1.00 0 -192 64 pin
+1.00 0 -192 128 pin
+1.00 0 -256 64 pin
+1.00 0 -256 0 pin
+1.00 0 -256 -64 pin
+1.00 0 -256 -128 pin
+1.00 0 192 -256 pin
+1.00 0 192 -192 pin
+1.00 0 128 -192 pin
+1.00 0 128 -128 pin
+1.00 0 192 -128 pin
+1.00 0 128 -64 pin
+1.00 0 192 -64 pin
+1.00 0 192 0 pin
+1.00 0 128 0 pin
+1.00 0 128 64 pin
+1.00 0 192 64 pin
+1.00 0 128 128 pin
+1.00 0 64 128 pin
+1.00 0 64 64 pin
+1.00 0 -64 128 pin
+1.00 0 -64 64 pin
+1.00 0 -128 64 pin
+1.00 0 -128 128 pin
+1.000 0.000 0.000 scb
+(10) {/Times-Roman cf} 2 20 180 0.75 -192 0 pinlabel
+(12) {/Times-Roman cf} 2 20 180 0.75 -192 -64 pinlabel
+(14) {/Times-Roman cf} 2 20 180 0.75 -192 -128 pinlabel
+(16) {/Times-Roman cf} 2 20 180 0.75 -192 -192 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -64 64 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -128 64 pinlabel
+(21) {/Times-Roman cf} 2 17 180 0.75 -128 -256 pinlabel
+(23) {/Times-Roman cf} 2 17 180 0.75 -64 -256 pinlabel
+(25) {/Times-Roman cf} 2 17 180 0.75 0 -256 pinlabel
+(27) {/Times-Roman cf} 2 17 180 0.75 64 -256 pinlabel
+(32) {/Times-Roman cf} 2 23 180 0.75 128 -192 pinlabel
+(34) {/Times-Roman cf} 2 23 180 0.75 128 -128 pinlabel
+(36) {/Times-Roman cf} 2 23 180 0.75 128 -64 pinlabel
+(38) {/Times-Roman cf} 2 23 180 0.75 128 0 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 64 64 pinlabel
+(29) {/Times-Roman cf} 2 20 180 0.75 192 -256 pinlabel
+(31) {/Times-Roman cf} 2 20 180 0.75 192 -192 pinlabel
+(33) {/Times-Roman cf} 2 20 180 0.75 192 -128 pinlabel
+(35) {/Times-Roman cf} 2 20 180 0.75 192 -64 pinlabel
+(37) {/Times-Roman cf} 2 20 180 0.75 192 0 pinlabel
+(39) {/Times-Roman cf} 2 20 180 0.75 192 64 pinlabel
+(1) {/Times-Roman cf} 2 17 0 0.75 0 64 pinlabel
+(2) {/Times-Roman cf} 2 17 180 0.75 -64 128 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -128 128 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -192 128 pinlabel
+(40) {/Times-Roman cf} 2 17 180 0.75 128 128 pinlabel
+(42) {/Times-Roman cf} 2 17 180 0.75 64 128 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 -192 -320 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -128 -320 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -64 -320 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 0 -320 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 64 -320 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 128 -320 pinlabel
+(7) {/Times-Roman cf} 2 23 180 0.75 -256 64 pinlabel
+(9) {/Times-Roman cf} 2 23 180 0.75 -256 0 pinlabel
+(11) {/Times-Roman cf} 2 23 180 0.75 -256 -64 pinlabel
+(13) {/Times-Roman cf} 2 23 180 0.75 -256 -128 pinlabel
+(15) {/Times-Roman cf} 2 23 180 0.75 -256 -192 pinlabel
+(17) {/Times-Roman cf} 2 23 180 0.75 -256 -256 pinlabel
+(41) {/Times-Roman cf} 2 31 180 0.75 128 64 pinlabel
+(8) {/Times-Roman cf} 2 28 180 0.75 -192 64 pinlabel
+sce
+1 1.00 432 -256 0 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(30) {/Times-Roman cf} 2 19 180 0.75 128 -256 pinlabel
+(19) {/Times-Roman cf} 2 16 180 0.75 -192 -256 pinlabel
+0.000 0.000 1.000 scb
+(44) {/Times-Roman cf} 2 29 180 0.75 0 160 label
+sce
+1.00 0 0 128 pin
+1.000 0.000 0.000 scb
+(44) {/Times-Roman cf} 2 17 180 0.75 0 128 pinlabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/pcb_layout.lps b/lib/pcb_layout.lps
new file mode 100644
index 0000000..668e8ed
--- /dev/null
+++ b/lib/pcb_layout.lps
@@ -0,0 +1,1249 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: new_pcb
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+%
+
+% Depend cap300 polarized pin
+% Depend cap200 polarized pin
+% Depend res300 resistor pin
+% Depend regulator pin
+% Depend sip8 pin1 pin
+% Depend sip10 pin1 pin
+% Depend clock8 pin1 pin
+% Depend dip8 pin pin1
+% Depend dip14 pin pin1
+% Depend dip16 pin pin1
+% Depend dip20 pin1 pin
+% Depend dip24n pin pin1
+% Depend dip28n pin1 pin
+% Depend dip40 pin1 pin
+% Depend dio_port pin1 pin
+% Depend pga68 pin1 pin
+% Depend pga44 pin1 pin
+
+% XCircuitLib library objects
+/polarized {
+begingate
+1 1.00 0 -64 0 -6 2 polygon
+1 1.00 0 64 0 6 2 polygon
+1 1.00 -32 6 32 6 2 polygon
+1 1.00 0 -80 74 66.00 114.00 xcarc
+endgate
+} def
+
+/pin {
+begingate
+1 5.00 0 0 12 0.00 360.00 xcarc
+endgate
+} def
+
+/cap300 {
+begingate
+1 1.00 0 64 0 96 2 polygon
+1 1.00 0 -96 0 -64 2 polygon
+1.00 0 0 0 polarized
+(+) {/Symbol cf} 2 24 0 1.00 32 32 label
+1.00 0 0 96 pin
+1.00 0 0 -96 pin
+endgate
+} def
+
+/cap200 {
+begingate
+1.00 0 0 0 polarized
+(+) {/Symbol cf} 2 24 0 1.00 32 32 label
+1.00 0 0 64 pin
+1.00 0 0 -64 pin
+endgate
+} def
+
+/resistor {
+begingate
+1 1.00 0 64 0 36 2 polygon
+1 1.00 0 -64 0 -36 2 polygon
+1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon
+endgate
+} def
+
+/res300 {
+begingate
+1.00 0 0 0 resistor
+1 1.00 0 64 0 96 2 polygon
+1 1.00 0 -96 0 -64 2 polygon
+1.00 0 0 96 pin
+1.00 0 0 -96 pin
+endgate
+} def
+
+/regulator {
+begingate
+0 1.00 -96 -48 -96 48 96 48 96 -48 4 polygon
+1 1.00 -96 16 96 16 2 polygon
+1.00 0 64 -16 pin
+1.00 0 0 -16 pin
+1.00 0 -64 -16 pin
+endgate
+} def
+
+/pin1 {
+begingate
+8 0 beginpath
+0 0 8 0.00 360.00 arc
+15 0 15 -15 -15 -15 -15 15 15 15 15 0 6 polyc
+
+241 1.00 endpath
+endgate
+} def
+
+/sip8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -240 -32 -240 0 240 0 240 -32 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -160 16 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -32 16 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -96 16 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -224 16 label
+(6) {/Times-Roman cf} 2 29 180 0.75 96 16 label
+(7) {/Times-Roman cf} 2 29 180 0.75 160 16 label
+(5) {/Times-Roman cf} 2 29 180 0.75 32 16 label
+(8) {/Times-Roman cf} 2 29 180 0.75 224 16 label
+sce
+1.00 0 -224 -16 pin1
+1.00 0 -160 -16 pin
+1.00 0 -96 -16 pin
+1.00 0 -32 -16 pin
+1.00 0 32 -16 pin
+1.00 0 96 -16 pin
+1.00 0 160 -16 pin
+1.00 0 224 -16 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -160 -16 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -32 -16 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -96 -16 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -224 -16 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 96 -16 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 160 -16 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 32 -16 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 224 -16 pinlabel
+endgate
+} def
+
+/sip10 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -240 -32 -240 0 368 0 368 -32 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -160 16 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -32 16 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -96 16 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -224 16 label
+(6) {/Times-Roman cf} 2 29 180 0.75 96 16 label
+(7) {/Times-Roman cf} 2 29 180 0.75 160 16 label
+(5) {/Times-Roman cf} 2 29 180 0.75 32 16 label
+(8) {/Times-Roman cf} 2 29 180 0.75 224 16 label
+(9) {/Times-Roman cf} 2 29 180 0.75 288 16 label
+(10) {/Times-Roman cf} 2 29 180 0.75 352 16 label
+sce
+1.00 0 -224 -16 pin1
+1.00 0 -160 -16 pin
+1.00 0 -96 -16 pin
+1.00 0 -32 -16 pin
+1.00 0 32 -16 pin
+1.00 0 96 -16 pin
+1.00 0 160 -16 pin
+1.00 0 224 -16 pin
+1.00 0 288 -16 pin
+1.00 0 352 -16 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -160 -16 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -32 -16 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -96 -16 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -224 -16 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 96 -16 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 160 -16 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 32 -16 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 224 -16 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 288 -16 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 352 -16 pinlabel
+endgate
+} def
+
+/clock8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -96 -96 -96 96 96 96 96 -96 4 polygon
+0.000 0.000 1.000 scb
+(4) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(8) {/Times-Roman cf} 2 17 180 0.75 -96 64 label
+(5) {/Times-Roman cf} 2 17 180 0.75 96 64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+sce
+1.00 0 -96 -96 pin1
+1.00 0 96 -96 pin
+1.00 0 96 96 pin
+1.00 0 -96 96 pin
+1.000 0.000 0.000 scb
+(4) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -96 96 pinlabel
+(5) {/Times-Roman cf} 2 29 180 0.75 96 96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+endgate
+} def
+
+/dip8 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 -80 112 -80 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(7) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(5) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(8) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.00 0 -272 -80 pin1
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(7) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(5) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+endgate
+} def
+
+/dip14 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 112 -80 112 112 -272 112 -272 -80 4 polygon
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(9) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 112 -80 pin
+1.00 0 48 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.00 0 -272 -80 pin1
+0.000 0.000 1.000 scb
+(12) {/Times-Roman cf} 2 17 180 0.75 -144 80 label
+(14) {/Times-Roman cf} 2 17 180 0.75 -272 80 label
+(13) {/Times-Roman cf} 2 17 180 0.75 -208 80 label
+(11) {/Times-Roman cf} 2 17 180 0.75 -80 80 label
+(10) {/Times-Roman cf} 2 17 180 0.75 -16 80 label
+(9) {/Times-Roman cf} 2 17 180 0.75 48 80 label
+(8) {/Times-Roman cf} 2 17 180 0.75 112 80 label
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+endgate
+} def
+
+/dip16 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 176 112 176 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(12) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(14) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(11) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(9) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 -208 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 48 -80 pin
+1.00 0 112 -80 pin
+1.00 0 176 -80 pin
+1.00 0 -272 -80 pin1
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(9) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+endgate
+} def
+
+/dip20 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 304 112 304 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(12) {/Times-Roman cf} 2 25 180 0.75 240 80 label
+(14) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+(11) {/Times-Roman cf} 2 25 180 0.75 304 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 29 180 0.75 304 -48 label
+(9) {/Times-Roman cf} 2 29 180 0.75 240 -48 label
+(18) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(17) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(19) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+sce
+1.00 0 -272 -80 pin1
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 240 112 pin
+1.00 0 304 112 pin
+1.00 0 304 -80 pin
+1.00 0 240 -80 pin
+1.00 0 176 -80 pin
+1.00 0 112 -80 pin
+1.00 0 48 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -208 -80 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(12) {/Times-Roman cf} 2 29 180 0.75 240 112 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+(11) {/Times-Roman cf} 2 29 180 0.75 304 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 304 -80 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 240 -80 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+endgate
+} def
+
+/dip24n {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -272 -80 -272 112 432 112 432 -80 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -208 -48 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -80 -48 label
+(14) {/Times-Roman cf} 2 25 180 0.75 368 80 label
+(13) {/Times-Roman cf} 2 25 180 0.75 432 80 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -144 -48 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -272 -48 label
+(6) {/Times-Roman cf} 2 29 180 0.75 48 -48 label
+(7) {/Times-Roman cf} 2 29 180 0.75 112 -48 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -16 -48 label
+(16) {/Times-Roman cf} 2 25 180 0.75 240 80 label
+(15) {/Times-Roman cf} 2 25 180 0.75 304 80 label
+(8) {/Times-Roman cf} 2 29 180 0.75 176 -48 label
+(10) {/Times-Roman cf} 2 29 180 0.75 304 -48 label
+(9) {/Times-Roman cf} 2 29 180 0.75 240 -48 label
+(18) {/Times-Roman cf} 2 25 180 0.75 112 80 label
+(17) {/Times-Roman cf} 2 25 180 0.75 176 80 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -16 80 label
+(19) {/Times-Roman cf} 2 25 180 0.75 48 80 label
+(21) {/Times-Roman cf} 2 25 180 0.75 -80 80 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -144 80 label
+(23) {/Times-Roman cf} 2 25 180 0.75 -208 80 label
+(24) {/Times-Roman cf} 2 25 180 0.75 -272 80 label
+(12) {/Times-Roman cf} 2 29 180 0.75 432 -48 label
+(11) {/Times-Roman cf} 2 29 180 0.75 368 -48 label
+sce
+1.00 0 -272 112 pin
+1.00 0 -208 112 pin
+1.00 0 -144 112 pin
+1.00 0 -80 112 pin
+1.00 0 -16 112 pin
+1.00 0 48 112 pin
+1.00 0 112 112 pin
+1.00 0 176 112 pin
+1.00 0 240 112 pin
+1.00 0 304 112 pin
+1.00 0 368 112 pin
+1.00 0 432 112 pin
+1.00 0 -272 -80 pin1
+1.00 0 -208 -80 pin
+1.00 0 -144 -80 pin
+1.00 0 -80 -80 pin
+1.00 0 -16 -80 pin
+1.00 0 48 -80 pin
+1.00 0 112 -80 pin
+1.00 0 176 -80 pin
+1.00 0 240 -80 pin
+1.00 0 304 -80 pin
+1.00 0 368 -80 pin
+1.00 0 432 -80 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -208 -80 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -80 -80 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 368 112 pinlabel
+(13) {/Times-Roman cf} 2 29 180 0.75 432 112 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -144 -80 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -272 -80 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 48 -80 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 112 -80 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -16 -80 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 240 112 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 304 112 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 176 -80 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 304 -80 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 240 -80 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 112 112 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 176 112 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -16 112 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 48 112 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 -80 112 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -144 112 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 -208 112 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 -272 112 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 432 -80 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 368 -80 pinlabel
+endgate
+} def
+
+/dip28n {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -416 -96 -416 96 416 96 416 -96 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -352 -64 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -224 -64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -32 64 label
+(24) {/Times-Roman cf} 2 25 180 0.75 -160 64 label
+(23) {/Times-Roman cf} 2 25 180 0.75 -96 64 label
+(21) {/Times-Roman cf} 2 25 180 0.75 32 64 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -288 -64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -416 -64 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -32 -64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -160 -64 label
+(16) {/Times-Roman cf} 2 25 180 0.75 352 64 label
+(15) {/Times-Roman cf} 2 25 180 0.75 416 64 label
+(8) {/Times-Roman cf} 2 29 180 0.75 32 -64 label
+(10) {/Times-Roman cf} 2 29 180 0.75 160 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(18) {/Times-Roman cf} 2 25 180 0.75 224 64 label
+(17) {/Times-Roman cf} 2 25 180 0.75 288 64 label
+(20) {/Times-Roman cf} 2 25 180 0.75 96 64 label
+(19) {/Times-Roman cf} 2 25 180 0.75 160 64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 -288 64 label
+(28) {/Times-Roman cf} 2 25 180 0.75 -416 64 label
+(27) {/Times-Roman cf} 2 25 180 0.75 -352 64 label
+(25) {/Times-Roman cf} 2 25 180 0.75 -224 64 label
+(11) {/Times-Roman cf} 2 29 180 0.75 224 -64 label
+(12) {/Times-Roman cf} 2 29 180 0.75 288 -64 label
+(14) {/Times-Roman cf} 2 29 180 0.75 416 -64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 352 -64 label
+sce
+1.00 0 -416 -96 pin1
+1.00 0 -352 -96 pin
+1.00 0 -288 -96 pin
+1.00 0 -224 -96 pin
+1.00 0 -160 -96 pin
+1.00 0 -96 -96 pin
+1.00 0 -32 -96 pin
+1.00 0 32 -96 pin
+1.00 0 96 -96 pin
+1.00 0 160 -96 pin
+1.00 0 224 -96 pin
+1.00 0 288 -96 pin
+1.00 0 352 -96 pin
+1.00 0 416 -96 pin
+1.00 0 416 96 pin
+1.00 0 352 96 pin
+1.00 0 288 96 pin
+1.00 0 224 96 pin
+1.00 0 160 96 pin
+1.00 0 96 96 pin
+1.00 0 32 96 pin
+1.00 0 -32 96 pin
+1.00 0 -96 96 pin
+1.00 0 -160 96 pin
+1.00 0 -224 96 pin
+1.00 0 -288 96 pin
+1.00 0 -352 96 pin
+1.00 0 -416 96 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -352 -96 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -224 -96 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -32 96 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 -160 96 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 -96 96 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 32 96 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -288 -96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -416 -96 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -32 -96 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -160 -96 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 352 96 pinlabel
+(15) {/Times-Roman cf} 2 29 180 0.75 416 96 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 32 -96 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 160 -96 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 224 96 pinlabel
+(17) {/Times-Roman cf} 2 29 180 0.75 288 96 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 96 96 pinlabel
+(19) {/Times-Roman cf} 2 29 180 0.75 160 96 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 -288 96 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 -416 96 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 -352 96 pinlabel
+(25) {/Times-Roman cf} 2 29 180 0.75 -224 96 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 224 -96 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 288 -96 pinlabel
+(14) {/Times-Roman cf} 2 17 180 0.75 416 -96 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 352 -96 pinlabel
+endgate
+} def
+
+/dip40 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -416 -96 -416 224 800 224 800 -96 4 polygon
+0.000 0.000 1.000 scb
+(2) {/Times-Roman cf} 2 29 180 0.75 -352 -64 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -224 -64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 736 192 label
+(24) {/Times-Roman cf} 2 25 180 0.75 608 192 label
+(23) {/Times-Roman cf} 2 25 180 0.75 672 192 label
+(21) {/Times-Roman cf} 2 25 180 0.75 800 192 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -288 -64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -416 -64 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -96 -64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -32 -64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -160 -64 label
+(8) {/Times-Roman cf} 2 29 180 0.75 32 -64 label
+(10) {/Times-Roman cf} 2 29 180 0.75 160 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 96 -64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 480 192 label
+(28) {/Times-Roman cf} 2 25 180 0.75 352 192 label
+(27) {/Times-Roman cf} 2 25 180 0.75 416 192 label
+(25) {/Times-Roman cf} 2 25 180 0.75 544 192 label
+(11) {/Times-Roman cf} 2 29 180 0.75 224 -64 label
+(12) {/Times-Roman cf} 2 29 180 0.75 288 -64 label
+(14) {/Times-Roman cf} 2 29 180 0.75 416 -64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 352 -64 label
+(29) {/Times-Roman cf} 2 25 180 0.75 288 192 label
+(30) {/Times-Roman cf} 2 25 180 0.75 224 192 label
+(31) {/Times-Roman cf} 2 25 180 0.75 160 192 label
+(32) {/Times-Roman cf} 2 25 180 0.75 96 192 label
+(33) {/Times-Roman cf} 2 25 180 0.75 32 192 label
+(34) {/Times-Roman cf} 2 25 180 0.75 -32 192 label
+(35) {/Times-Roman cf} 2 25 180 0.75 -96 192 label
+(36) {/Times-Roman cf} 2 25 180 0.75 -160 192 label
+(37) {/Times-Roman cf} 2 25 180 0.75 -224 192 label
+(38) {/Times-Roman cf} 2 25 180 0.75 -288 192 label
+(39) {/Times-Roman cf} 2 25 180 0.75 -352 192 label
+(40) {/Times-Roman cf} 2 25 180 0.75 -416 192 label
+(15) {/Times-Roman cf} 2 29 180 0.75 480 -64 label
+(16) {/Times-Roman cf} 2 29 180 0.75 544 -64 label
+(17) {/Times-Roman cf} 2 29 180 0.75 608 -64 label
+(19) {/Times-Roman cf} 2 29 180 0.75 736 -64 label
+(18) {/Times-Roman cf} 2 29 180 0.75 672 -64 label
+(20) {/Times-Roman cf} 2 29 180 0.75 800 -64 label
+sce
+1.00 0 -416 -96 pin1
+1.00 0 -352 -96 pin
+1.00 0 -288 -96 pin
+1.00 0 -224 -96 pin
+1.00 0 -160 -96 pin
+1.00 0 -96 -96 pin
+1.00 0 -32 -96 pin
+1.00 0 32 -96 pin
+1.00 0 96 -96 pin
+1.00 0 160 -96 pin
+1.00 0 224 -96 pin
+1.00 0 288 -96 pin
+1.00 0 352 -96 pin
+1.00 0 416 -96 pin
+1.00 0 480 -96 pin
+1.00 0 544 -96 pin
+1.00 0 608 -96 pin
+1.00 0 672 -96 pin
+1.00 0 736 -96 pin
+1.00 0 800 -96 pin
+1.00 0 800 224 pin
+1.00 0 736 224 pin
+1.00 0 672 224 pin
+1.00 0 608 224 pin
+1.00 0 544 224 pin
+1.00 0 480 224 pin
+1.00 0 416 224 pin
+1.00 0 352 224 pin
+1.00 0 288 224 pin
+1.00 0 224 224 pin
+1.00 0 160 224 pin
+1.00 0 96 224 pin
+1.00 0 32 224 pin
+1.00 0 -32 224 pin
+1.00 0 -96 224 pin
+1.00 0 -160 224 pin
+1.00 0 -224 224 pin
+1.00 0 -288 224 pin
+1.00 0 -352 224 pin
+1.00 0 -416 224 pin
+1.000 0.000 0.000 scb
+(2) {/Times-Roman cf} 2 17 180 0.75 -352 -96 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -224 -96 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 736 224 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 608 224 pinlabel
+(23) {/Times-Roman cf} 2 29 180 0.75 672 224 pinlabel
+(21) {/Times-Roman cf} 2 29 180 0.75 800 224 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -288 -96 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -416 -96 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -96 -96 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -32 -96 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -160 -96 pinlabel
+(8) {/Times-Roman cf} 2 17 180 0.75 32 -96 pinlabel
+(10) {/Times-Roman cf} 2 17 180 0.75 160 -96 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 96 -96 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 480 224 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 352 224 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 416 224 pinlabel
+(25) {/Times-Roman cf} 2 29 180 0.75 544 224 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 224 -96 pinlabel
+(12) {/Times-Roman cf} 2 17 180 0.75 288 -96 pinlabel
+(14) {/Times-Roman cf} 2 17 180 0.75 416 -96 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 352 -96 pinlabel
+(29) {/Times-Roman cf} 2 29 180 0.75 288 224 pinlabel
+(30) {/Times-Roman cf} 2 29 180 0.75 224 224 pinlabel
+(31) {/Times-Roman cf} 2 29 180 0.75 160 224 pinlabel
+(32) {/Times-Roman cf} 2 29 180 0.75 96 224 pinlabel
+(33) {/Times-Roman cf} 2 29 180 0.75 32 224 pinlabel
+(34) {/Times-Roman cf} 2 29 180 0.75 -32 224 pinlabel
+(35) {/Times-Roman cf} 2 29 180 0.75 -96 224 pinlabel
+(36) {/Times-Roman cf} 2 29 180 0.75 -160 224 pinlabel
+(37) {/Times-Roman cf} 2 29 180 0.75 -224 224 pinlabel
+(38) {/Times-Roman cf} 2 29 180 0.75 -288 224 pinlabel
+(39) {/Times-Roman cf} 2 29 180 0.75 -352 224 pinlabel
+(40) {/Times-Roman cf} 2 29 180 0.75 -416 224 pinlabel
+(15) {/Times-Roman cf} 2 17 180 0.75 480 -96 pinlabel
+(16) {/Times-Roman cf} 2 17 180 0.75 544 -96 pinlabel
+(17) {/Times-Roman cf} 2 17 180 0.75 608 -96 pinlabel
+(19) {/Times-Roman cf} 2 17 180 0.75 736 -96 pinlabel
+(18) {/Times-Roman cf} 2 17 180 0.75 672 -96 pinlabel
+(20) {/Times-Roman cf} 2 17 180 0.75 800 -96 pinlabel
+endgate
+} def
+
+/dio_port {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -768 -32 -768 32 768 32 768 -32 4 polygon
+0.000 0.000 1.000 scb
+(12) {/Times-Roman cf} 2 25 180 0.75 448 -64 label
+(14) {/Times-Roman cf} 2 25 180 0.75 384 -64 label
+(3) {/Times-Roman cf} 2 29 180 0.75 704 64 label
+(1) {/Times-Roman cf} 2 29 180 0.75 768 64 label
+(7) {/Times-Roman cf} 2 29 180 0.75 576 64 label
+(5) {/Times-Roman cf} 2 29 180 0.75 640 64 label
+(16) {/Times-Roman cf} 2 25 180 0.75 320 -64 label
+(9) {/Times-Roman cf} 2 29 180 0.75 512 64 label
+(18) {/Times-Roman cf} 2 25 180 0.75 256 -64 label
+(20) {/Times-Roman cf} 2 25 180 0.75 192 -64 label
+(2) {/Times-Roman cf} 2 25 180 0.75 768 -64 label
+(4) {/Times-Roman cf} 2 25 180 0.75 704 -64 label
+(6) {/Times-Roman cf} 2 25 180 0.75 640 -64 label
+(8) {/Times-Roman cf} 2 25 180 0.75 576 -64 label
+(10) {/Times-Roman cf} 2 25 180 0.75 512 -64 label
+(11) {/Times-Roman cf} 2 29 180 0.75 448 64 label
+(13) {/Times-Roman cf} 2 29 180 0.75 384 64 label
+(15) {/Times-Roman cf} 2 29 180 0.75 320 64 label
+(17) {/Times-Roman cf} 2 29 180 0.75 256 64 label
+(19) {/Times-Roman cf} 2 29 180 0.75 192 64 label
+(21) {/Times-Roman cf} 2 29 180 0.75 128 64 label
+(23) {/Times-Roman cf} 2 29 180 0.75 64 64 label
+(25) {/Times-Roman cf} 2 29 180 0.75 0 64 label
+(27) {/Times-Roman cf} 2 29 180 0.75 -64 64 label
+(29) {/Times-Roman cf} 2 29 180 0.75 -128 64 label
+(31) {/Times-Roman cf} 2 29 180 0.75 -192 64 label
+(33) {/Times-Roman cf} 2 29 180 0.75 -256 64 label
+(35) {/Times-Roman cf} 2 29 180 0.75 -320 64 label
+(37) {/Times-Roman cf} 2 29 180 0.75 -384 64 label
+(39) {/Times-Roman cf} 2 29 180 0.75 -448 64 label
+(41) {/Times-Roman cf} 2 29 180 0.75 -512 64 label
+(43) {/Times-Roman cf} 2 29 180 0.75 -576 64 label
+(45) {/Times-Roman cf} 2 29 180 0.75 -640 64 label
+(47) {/Times-Roman cf} 2 29 180 0.75 -704 64 label
+(49) {/Times-Roman cf} 2 29 180 0.75 -768 64 label
+(22) {/Times-Roman cf} 2 25 180 0.75 128 -64 label
+(24) {/Times-Roman cf} 2 25 180 0.75 64 -64 label
+(26) {/Times-Roman cf} 2 25 180 0.75 0 -64 label
+(28) {/Times-Roman cf} 2 25 180 0.75 -64 -64 label
+(30) {/Times-Roman cf} 2 25 180 0.75 -128 -64 label
+(32) {/Times-Roman cf} 2 25 180 0.75 -192 -64 label
+(34) {/Times-Roman cf} 2 25 180 0.75 -256 -64 label
+(36) {/Times-Roman cf} 2 25 180 0.75 -320 -64 label
+(38) {/Times-Roman cf} 2 25 180 0.75 -384 -64 label
+(40) {/Times-Roman cf} 2 25 180 0.75 -448 -64 label
+(42) {/Times-Roman cf} 2 25 180 0.75 -512 -64 label
+(44) {/Times-Roman cf} 2 25 180 0.75 -576 -64 label
+(46) {/Times-Roman cf} 2 25 180 0.75 -640 -64 label
+(48) {/Times-Roman cf} 2 25 180 0.75 -704 -64 label
+(50) {/Times-Roman cf} 2 25 180 0.75 -768 -64 label
+sce
+1.00 0 768 32 pin1
+1.00 0 704 32 pin
+1.00 0 640 32 pin
+1.00 0 576 32 pin
+1.00 0 512 32 pin
+1.00 0 448 32 pin
+1.00 0 768 -32 pin
+1.00 0 704 -32 pin
+1.00 0 640 -32 pin
+1.00 0 576 -32 pin
+1.00 0 512 -32 pin
+1.00 0 448 -32 pin
+1.00 0 384 -32 pin
+1.00 0 384 32 pin
+1.00 0 320 32 pin
+1.00 0 256 32 pin
+1.00 0 320 -32 pin
+1.00 0 256 -32 pin
+1.00 0 192 -32 pin
+1.00 0 192 32 pin
+1.00 0 128 32 pin
+1.00 0 64 32 pin
+1.00 0 0 32 pin
+1.00 0 128 -32 pin
+1.00 0 64 -32 pin
+1.00 0 0 -32 pin
+1.00 0 -64 -32 pin
+1.00 0 -64 32 pin
+1.00 0 -128 32 pin
+1.00 0 -128 -32 pin
+1.00 0 -192 -32 pin
+1.00 0 -192 32 pin
+1.00 0 -256 32 pin
+1.00 0 -256 -32 pin
+1.00 0 -320 -32 pin
+1.00 0 -320 32 pin
+1.00 0 -384 32 pin
+1.00 0 -384 -32 pin
+1.00 0 -448 -32 pin
+1.00 0 -448 32 pin
+1.00 0 -512 32 pin
+1.00 0 -512 -32 pin
+1.00 0 -576 -32 pin
+1.00 0 -576 32 pin
+1.00 0 -640 32 pin
+1.00 0 -640 -32 pin
+1.00 0 -704 -32 pin
+1.00 0 -704 32 pin
+1.00 0 -768 32 pin
+1.00 0 -768 -32 pin
+1.000 0.000 0.000 scb
+(12) {/Times-Roman cf} 2 29 180 0.75 448 -32 pinlabel
+(14) {/Times-Roman cf} 2 29 180 0.75 384 -32 pinlabel
+(16) {/Times-Roman cf} 2 29 180 0.75 320 -32 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 256 -32 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 192 -32 pinlabel
+(2) {/Times-Roman cf} 2 29 180 0.75 768 -32 pinlabel
+(4) {/Times-Roman cf} 2 29 180 0.75 704 -32 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 640 -32 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 576 -32 pinlabel
+(10) {/Times-Roman cf} 2 29 180 0.75 512 -32 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 128 -32 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 64 -32 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 0 -32 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 -64 -32 pinlabel
+(30) {/Times-Roman cf} 2 29 180 0.75 -128 -32 pinlabel
+(32) {/Times-Roman cf} 2 29 180 0.75 -192 -32 pinlabel
+(34) {/Times-Roman cf} 2 29 180 0.75 -256 -32 pinlabel
+(36) {/Times-Roman cf} 2 29 180 0.75 -320 -32 pinlabel
+(38) {/Times-Roman cf} 2 29 180 0.75 -384 -32 pinlabel
+(40) {/Times-Roman cf} 2 29 180 0.75 -448 -32 pinlabel
+(42) {/Times-Roman cf} 2 29 180 0.75 -512 -32 pinlabel
+(44) {/Times-Roman cf} 2 29 180 0.75 -576 -32 pinlabel
+(46) {/Times-Roman cf} 2 29 180 0.75 -640 -32 pinlabel
+(48) {/Times-Roman cf} 2 29 180 0.75 -704 -32 pinlabel
+(50) {/Times-Roman cf} 2 29 180 0.75 -768 -32 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 704 32 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 768 32 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 576 32 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 640 32 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 512 32 pinlabel
+(11) {/Times-Roman cf} 2 17 180 0.75 448 32 pinlabel
+(13) {/Times-Roman cf} 2 17 180 0.75 384 32 pinlabel
+(15) {/Times-Roman cf} 2 17 180 0.75 320 32 pinlabel
+(17) {/Times-Roman cf} 2 17 180 0.75 256 32 pinlabel
+(19) {/Times-Roman cf} 2 17 180 0.75 192 32 pinlabel
+(21) {/Times-Roman cf} 2 17 180 0.75 128 32 pinlabel
+(23) {/Times-Roman cf} 2 17 180 0.75 64 32 pinlabel
+(25) {/Times-Roman cf} 2 17 180 0.75 0 32 pinlabel
+(27) {/Times-Roman cf} 2 17 180 0.75 -64 32 pinlabel
+(29) {/Times-Roman cf} 2 17 180 0.75 -128 32 pinlabel
+(31) {/Times-Roman cf} 2 17 180 0.75 -192 32 pinlabel
+(33) {/Times-Roman cf} 2 17 180 0.75 -256 32 pinlabel
+(35) {/Times-Roman cf} 2 17 180 0.75 -320 32 pinlabel
+(37) {/Times-Roman cf} 2 17 180 0.75 -384 32 pinlabel
+(39) {/Times-Roman cf} 2 17 180 0.75 -448 32 pinlabel
+(41) {/Times-Roman cf} 2 17 180 0.75 -512 32 pinlabel
+(43) {/Times-Roman cf} 2 17 180 0.75 -576 32 pinlabel
+(45) {/Times-Roman cf} 2 17 180 0.75 -640 32 pinlabel
+(47) {/Times-Roman cf} 2 17 180 0.75 -704 32 pinlabel
+(49) {/Times-Roman cf} 2 17 180 0.75 -768 32 pinlabel
+endgate
+} def
+
+/pga68 {
+begingate
+0.843 0.843 0.843 scb
+241 1.00 -448 -256 -384 -256 -384 -320 128 -320 128 -256 192 -256 192 256 128
+256 128 320 -384 320 -384 256 -448 256 -448 0 -384 0 -384 192 -320 192 -320 256
+64 256 64 192 128 192 128 -192 64 -192 64 -256 -320 -256 -320 -192 -384 -192
+-384 0 -448 0 -448 -256 29 polygon
+sce
+1 1.00 -432 -272 0 0.00 360.00 xcarc
+0.000 0.000 1.000 scb
+(10) {/Times-Roman cf} 2 20 180 0.75 -480 256 label
+(11) {/Times-Roman cf} 2 28 180 0.75 -400 272 label
+(12) {/Times-Roman cf} 2 20 180 0.75 -480 192 label
+(13) {/Times-Roman cf} 2 23 180 0.75 -352 176 label
+(14) {/Times-Roman cf} 2 20 180 0.75 -480 128 label
+(15) {/Times-Roman cf} 2 23 180 0.75 -352 128 label
+(16) {/Times-Roman cf} 2 20 180 0.75 -480 64 label
+(17) {/Times-Roman cf} 2 23 180 0.75 -352 64 label
+(18) {/Times-Roman cf} 2 20 180 0.75 -480 0 label
+(19) {/Times-Roman cf} 2 23 180 0.75 -352 0 label
+(20) {/Times-Roman cf} 2 20 180 0.75 -480 -64 label
+(21) {/Times-Roman cf} 2 23 180 0.75 -352 -64 label
+(22) {/Times-Roman cf} 2 20 180 0.75 -480 -128 label
+(23) {/Times-Roman cf} 2 23 180 0.75 -352 -128 label
+(24) {/Times-Roman cf} 2 20 180 0.75 -480 -192 label
+(25) {/Times-Roman cf} 2 23 180 0.75 -352 -176 label
+(27) {/Times-Roman cf} 2 25 180 0.75 -384 -368 label
+(28) {/Times-Roman cf} 2 24 180 0.75 -400 -288 label
+(29) {/Times-Roman cf} 2 25 180 0.75 -320 -368 label
+(1) {/Times-Roman cf} 2 29 180 0.75 -128 352 label
+(2) {/Times-Roman cf} 2 25 180 0.75 -128 208 label
+(4) {/Times-Roman cf} 2 25 180 0.75 -192 208 label
+(6) {/Times-Roman cf} 2 25 180 0.75 -256 208 label
+(8) {/Times-Roman cf} 2 25 180 0.75 -320 208 label
+(3) {/Times-Roman cf} 2 29 180 0.75 -192 352 label
+(5) {/Times-Roman cf} 2 29 180 0.75 -256 352 label
+(7) {/Times-Roman cf} 2 29 180 0.75 -320 352 label
+(9) {/Times-Roman cf} 2 29 180 0.75 -384 352 label
+(30) {/Times-Roman cf} 2 29 180 0.75 -320 -224 label
+(32) {/Times-Roman cf} 2 29 180 0.75 -256 -224 label
+(34) {/Times-Roman cf} 2 29 180 0.75 -192 -224 label
+(36) {/Times-Roman cf} 2 29 180 0.75 -128 -224 label
+(38) {/Times-Roman cf} 2 29 180 0.75 -64 -224 label
+(40) {/Times-Roman cf} 2 29 180 0.75 0 -224 label
+(42) {/Times-Roman cf} 2 29 180 0.75 64 -224 label
+(31) {/Times-Roman cf} 2 25 180 0.75 -256 -368 label
+(33) {/Times-Roman cf} 2 25 180 0.75 -192 -368 label
+(35) {/Times-Roman cf} 2 25 180 0.75 -128 -368 label
+(37) {/Times-Roman cf} 2 25 180 0.75 -64 -368 label
+(39) {/Times-Roman cf} 2 25 180 0.75 0 -368 label
+(41) {/Times-Roman cf} 2 25 180 0.75 64 -368 label
+(43) {/Times-Roman cf} 2 25 180 0.75 128 -368 label
+(44) {/Times-Roman cf} 2 23 180 0.75 224 -256 label
+(46) {/Times-Roman cf} 2 23 180 0.75 224 -192 label
+(48) {/Times-Roman cf} 2 23 180 0.75 224 -128 label
+(50) {/Times-Roman cf} 2 23 180 0.75 224 -64 label
+(52) {/Times-Roman cf} 2 23 180 0.75 224 0 label
+(54) {/Times-Roman cf} 2 23 180 0.75 224 64 label
+(56) {/Times-Roman cf} 2 23 180 0.75 224 128 label
+(58) {/Times-Roman cf} 2 23 180 0.75 224 192 label
+(60) {/Times-Roman cf} 2 23 180 0.75 224 256 label
+(61) {/Times-Roman cf} 2 29 180 0.75 128 352 label
+(63) {/Times-Roman cf} 2 29 180 0.75 64 352 label
+(65) {/Times-Roman cf} 2 29 180 0.75 0 352 label
+(67) {/Times-Roman cf} 2 29 180 0.75 -64 352 label
+(45) {/Times-Roman cf} 2 27 180 0.75 144 -288 label
+(47) {/Times-Roman cf} 2 20 180 0.75 96 -176 label
+(49) {/Times-Roman cf} 2 20 180 0.75 96 -128 label
+(51) {/Times-Roman cf} 2 20 180 0.75 96 -64 label
+(53) {/Times-Roman cf} 2 20 180 0.75 96 0 label
+(55) {/Times-Roman cf} 2 20 180 0.75 96 64 label
+(57) {/Times-Roman cf} 2 20 180 0.75 96 128 label
+(59) {/Times-Roman cf} 2 20 180 0.75 96 176 label
+(62) {/Times-Roman cf} 2 31 180 0.75 144 288 label
+(64) {/Times-Roman cf} 2 25 180 0.75 64 208 label
+(66) {/Times-Roman cf} 2 25 180 0.75 0 208 label
+(68) {/Times-Roman cf} 2 25 180 0.75 -64 208 label
+(26) {/Times-Roman cf} 2 20 180 0.75 -480 -256 label
+sce
+1.00 0 -128 320 pin1
+1.00 0 -384 -256 pin
+1.00 0 -320 -256 pin
+1.00 0 -384 -320 pin
+1.00 0 -320 -320 pin
+1.00 0 -256 -320 pin
+1.00 0 -192 -320 pin
+1.00 0 -128 -320 pin
+1.00 0 -64 -320 pin
+1.00 0 0 -320 pin
+1.00 0 64 -320 pin
+1.00 0 128 -320 pin
+1.00 0 128 -256 pin
+1.00 0 64 -256 pin
+1.00 0 0 -256 pin
+1.00 0 -64 -256 pin
+1.00 0 -128 -256 pin
+1.00 0 -192 -256 pin
+1.00 0 -256 -256 pin
+1.00 0 -448 -256 pin
+1.00 0 -448 -192 pin
+1.00 0 -384 -192 pin
+1.00 0 -384 -128 pin
+1.00 0 -384 -64 pin
+1.00 0 -384 0 pin
+1.00 0 -384 64 pin
+1.00 0 -384 128 pin
+1.00 0 -384 192 pin
+1.00 0 -384 256 pin
+1.00 0 -384 320 pin
+1.00 0 -448 256 pin
+1.00 0 -448 192 pin
+1.00 0 -448 128 pin
+1.00 0 -448 64 pin
+1.00 0 -448 0 pin
+1.00 0 -448 -64 pin
+1.00 0 -448 -128 pin
+1.00 0 192 -256 pin
+1.00 0 192 -192 pin
+1.00 0 128 -192 pin
+1.00 0 128 -128 pin
+1.00 0 192 -128 pin
+1.00 0 192 -64 pin
+1.00 0 128 -64 pin
+1.00 0 128 0 pin
+1.00 0 192 0 pin
+1.00 0 192 64 pin
+1.00 0 128 64 pin
+1.00 0 128 128 pin
+1.00 0 192 128 pin
+1.00 0 192 192 pin
+1.00 0 128 192 pin
+1.00 0 128 256 pin
+1.00 0 192 256 pin
+1.00 0 128 320 pin
+1.00 0 64 320 pin
+1.00 0 64 256 pin
+1.00 0 0 256 pin
+1.00 0 0 320 pin
+1.00 0 -64 320 pin
+1.00 0 -64 256 pin
+1.00 0 -128 256 pin
+1.00 0 -192 256 pin
+1.00 0 -192 320 pin
+1.00 0 -256 320 pin
+1.00 0 -256 256 pin
+1.00 0 -320 256 pin
+1.00 0 -320 320 pin
+1.000 0.000 0.000 scb
+(13) {/Times-Roman cf} 2 20 180 0.75 -384 192 pinlabel
+(15) {/Times-Roman cf} 2 20 180 0.75 -384 128 pinlabel
+(17) {/Times-Roman cf} 2 20 180 0.75 -384 64 pinlabel
+(19) {/Times-Roman cf} 2 20 180 0.75 -384 0 pinlabel
+(21) {/Times-Roman cf} 2 20 180 0.75 -384 -64 pinlabel
+(23) {/Times-Roman cf} 2 20 180 0.75 -384 -128 pinlabel
+(25) {/Times-Roman cf} 2 20 180 0.75 -384 -192 pinlabel
+(2) {/Times-Roman cf} 2 29 180 0.75 -128 256 pinlabel
+(4) {/Times-Roman cf} 2 29 180 0.75 -192 256 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -256 256 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -320 256 pinlabel
+(30) {/Times-Roman cf} 2 17 180 0.75 -320 -256 pinlabel
+(32) {/Times-Roman cf} 2 17 180 0.75 -256 -256 pinlabel
+(34) {/Times-Roman cf} 2 17 180 0.75 -192 -256 pinlabel
+(36) {/Times-Roman cf} 2 17 180 0.75 -128 -256 pinlabel
+(38) {/Times-Roman cf} 2 17 180 0.75 -64 -256 pinlabel
+(40) {/Times-Roman cf} 2 17 180 0.75 0 -256 pinlabel
+(42) {/Times-Roman cf} 2 17 180 0.75 64 -256 pinlabel
+(47) {/Times-Roman cf} 2 23 180 0.75 128 -192 pinlabel
+(49) {/Times-Roman cf} 2 23 180 0.75 128 -128 pinlabel
+(51) {/Times-Roman cf} 2 23 180 0.75 128 -64 pinlabel
+(53) {/Times-Roman cf} 2 23 180 0.75 128 0 pinlabel
+(55) {/Times-Roman cf} 2 23 180 0.75 128 64 pinlabel
+(57) {/Times-Roman cf} 2 23 180 0.75 128 128 pinlabel
+(59) {/Times-Roman cf} 2 23 180 0.75 128 192 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 64 256 pinlabel
+(66) {/Times-Roman cf} 2 29 180 0.75 0 256 pinlabel
+(68) {/Times-Roman cf} 2 29 180 0.75 -64 256 pinlabel
+(44) {/Times-Roman cf} 2 20 180 0.75 192 -256 pinlabel
+(46) {/Times-Roman cf} 2 20 180 0.75 192 -192 pinlabel
+(48) {/Times-Roman cf} 2 20 180 0.75 192 -128 pinlabel
+(50) {/Times-Roman cf} 2 20 180 0.75 192 -64 pinlabel
+(52) {/Times-Roman cf} 2 20 180 0.75 192 0 pinlabel
+(54) {/Times-Roman cf} 2 20 180 0.75 192 64 pinlabel
+(56) {/Times-Roman cf} 2 20 180 0.75 192 128 pinlabel
+(58) {/Times-Roman cf} 2 20 180 0.75 192 192 pinlabel
+(60) {/Times-Roman cf} 2 20 180 0.75 192 256 pinlabel
+(1) {/Times-Roman cf} 2 17 180 0.75 -128 320 pinlabel
+(3) {/Times-Roman cf} 2 17 180 0.75 -192 320 pinlabel
+(5) {/Times-Roman cf} 2 17 180 0.75 -256 320 pinlabel
+(7) {/Times-Roman cf} 2 17 180 0.75 -320 320 pinlabel
+(9) {/Times-Roman cf} 2 17 180 0.75 -384 320 pinlabel
+(61) {/Times-Roman cf} 2 17 180 0.75 128 320 pinlabel
+(63) {/Times-Roman cf} 2 17 180 0.75 64 320 pinlabel
+(65) {/Times-Roman cf} 2 17 180 0.75 0 320 pinlabel
+(67) {/Times-Roman cf} 2 17 180 0.75 -64 320 pinlabel
+(27) {/Times-Roman cf} 2 29 180 0.75 -384 -320 pinlabel
+(29) {/Times-Roman cf} 2 29 180 0.75 -320 -320 pinlabel
+(31) {/Times-Roman cf} 2 29 180 0.75 -256 -320 pinlabel
+(33) {/Times-Roman cf} 2 29 180 0.75 -192 -320 pinlabel
+(35) {/Times-Roman cf} 2 29 180 0.75 -128 -320 pinlabel
+(37) {/Times-Roman cf} 2 29 180 0.75 -64 -320 pinlabel
+(39) {/Times-Roman cf} 2 29 180 0.75 0 -320 pinlabel
+(41) {/Times-Roman cf} 2 29 180 0.75 64 -320 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 128 -320 pinlabel
+(10) {/Times-Roman cf} 2 23 180 0.75 -448 256 pinlabel
+(12) {/Times-Roman cf} 2 23 180 0.75 -448 192 pinlabel
+(14) {/Times-Roman cf} 2 23 180 0.75 -448 128 pinlabel
+(16) {/Times-Roman cf} 2 23 180 0.75 -448 64 pinlabel
+(18) {/Times-Roman cf} 2 23 180 0.75 -448 0 pinlabel
+(20) {/Times-Roman cf} 2 23 180 0.75 -448 -64 pinlabel
+(22) {/Times-Roman cf} 2 23 180 0.75 -448 -128 pinlabel
+(24) {/Times-Roman cf} 2 23 180 0.75 -448 -192 pinlabel
+(26) {/Times-Roman cf} 2 23 180 0.75 -448 -256 pinlabel
+(62) {/Times-Roman cf} 2 31 180 0.75 128 256 pinlabel
+(11) {/Times-Roman cf} 2 28 180 0.75 -384 256 pinlabel
+sce
+1 1.00 432 -256 0 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(45) {/Times-Roman cf} 2 19 180 0.75 128 -256 pinlabel
+(28) {/Times-Roman cf} 2 16 180 0.75 -384 -256 pinlabel
+endgate
+} def
+
+/pga44 {
+begingate
+0.843 0.843 0.843 scb
+240 1.00 -192 -256 -192 -320 128 -320 128 -256 192 -256 192 64 128 64 128 128
+-192 128 -192 64 -256 64 -256 -128 -192 -128 -192 0 -128 0 -128 64 64 64 64 0
+128 0 128 -192 64 -192 64 -256 -128 -256 -128 -192 -192 -192 -192 -128 -256
+-128 -256 -256 28 polygon
+0.000 0.000 1.000 scb
+(7) {/Times-Roman cf} 2 20 180 0.75 -288 64 label
+(8) {/Times-Roman cf} 2 28 180 0.75 -216 96 label
+(9) {/Times-Roman cf} 2 20 180 0.75 -288 0 label
+(10) {/Times-Roman cf} 2 23 180 0.75 -160 -16 label
+(11) {/Times-Roman cf} 2 20 180 0.75 -288 -64 label
+(12) {/Times-Roman cf} 2 23 180 0.75 -160 -64 label
+(13) {/Times-Roman cf} 2 20 180 0.75 -288 -128 label
+(14) {/Times-Roman cf} 2 23 180 0.75 -160 -128 label
+(15) {/Times-Roman cf} 2 20 180 0.75 -288 -192 label
+(16) {/Times-Roman cf} 2 23 180 0.75 -160 -176 label
+(18) {/Times-Roman cf} 2 25 180 0.75 -192 -368 label
+(19) {/Times-Roman cf} 2 24 180 0.75 -224 -296 label
+(20) {/Times-Roman cf} 2 25 180 0.75 -128 -368 label
+(1) {/Times-Roman cf} 2 21 180 0.75 0 16 label
+(3) {/Times-Roman cf} 2 25 180 0.75 -64 16 label
+(5) {/Times-Roman cf} 2 25 180 0.75 -128 16 label
+(2) {/Times-Roman cf} 2 29 180 0.75 -64 160 label
+(4) {/Times-Roman cf} 2 29 180 0.75 -128 160 label
+(6) {/Times-Roman cf} 2 29 180 0.75 -192 160 label
+(21) {/Times-Roman cf} 2 29 180 0.75 -128 -224 label
+(23) {/Times-Roman cf} 2 29 180 0.75 -64 -224 label
+(25) {/Times-Roman cf} 2 29 180 0.75 0 -224 label
+(27) {/Times-Roman cf} 2 29 180 0.75 64 -224 label
+(22) {/Times-Roman cf} 2 25 180 0.75 -64 -368 label
+(24) {/Times-Roman cf} 2 25 180 0.75 0 -368 label
+(26) {/Times-Roman cf} 2 25 180 0.75 64 -368 label
+(28) {/Times-Roman cf} 2 25 180 0.75 128 -368 label
+(29) {/Times-Roman cf} 2 23 180 0.75 224 -256 label
+(31) {/Times-Roman cf} 2 23 180 0.75 224 -192 label
+(33) {/Times-Roman cf} 2 23 180 0.75 224 -128 label
+(35) {/Times-Roman cf} 2 23 180 0.75 224 -64 label
+(37) {/Times-Roman cf} 2 23 180 0.75 224 0 label
+(39) {/Times-Roman cf} 2 23 180 0.75 224 64 label
+(40) {/Times-Roman cf} 2 29 180 0.75 128 160 label
+(42) {/Times-Roman cf} 2 29 180 0.75 64 160 label
+(30) {/Times-Roman cf} 2 27 180 0.75 152 -296 label
+(32) {/Times-Roman cf} 2 20 180 0.75 96 -176 label
+(34) {/Times-Roman cf} 2 20 180 0.75 96 -128 label
+(36) {/Times-Roman cf} 2 20 180 0.75 96 -64 label
+(38) {/Times-Roman cf} 2 20 180 0.75 96 -16 label
+(41) {/Times-Roman cf} 2 31 180 0.75 160 96 label
+(43) {/Times-Roman cf} 2 25 180 0.75 64 16 label
+(17) {/Times-Roman cf} 2 20 180 0.75 -288 -256 label
+sce
+1.00 0 0 64 pin1
+1.00 0 -192 -256 pin
+1.00 0 -128 -256 pin
+1.00 0 -192 -320 pin
+1.00 0 -128 -320 pin
+1.00 0 -64 -320 pin
+1.00 0 0 -320 pin
+1.00 0 64 -320 pin
+1.00 0 128 -320 pin
+1.00 0 128 -256 pin
+1.00 0 64 -256 pin
+1.00 0 0 -256 pin
+1.00 0 -64 -256 pin
+1.00 0 -256 -256 pin
+1.00 0 -256 -192 pin
+1.00 0 -192 -192 pin
+1.00 0 -192 -128 pin
+1.00 0 -192 -64 pin
+1.00 0 -192 0 pin
+1.00 0 -192 64 pin
+1.00 0 -192 128 pin
+1.00 0 -256 64 pin
+1.00 0 -256 0 pin
+1.00 0 -256 -64 pin
+1.00 0 -256 -128 pin
+1.00 0 192 -256 pin
+1.00 0 192 -192 pin
+1.00 0 128 -192 pin
+1.00 0 128 -128 pin
+1.00 0 192 -128 pin
+1.00 0 128 -64 pin
+1.00 0 192 -64 pin
+1.00 0 192 0 pin
+1.00 0 128 0 pin
+1.00 0 128 64 pin
+1.00 0 192 64 pin
+1.00 0 128 128 pin
+1.00 0 64 128 pin
+1.00 0 64 64 pin
+1.00 0 -64 128 pin
+1.00 0 -64 64 pin
+1.00 0 -128 64 pin
+1.00 0 -128 128 pin
+1.000 0.000 0.000 scb
+(10) {/Times-Roman cf} 2 20 180 0.75 -192 0 pinlabel
+(12) {/Times-Roman cf} 2 20 180 0.75 -192 -64 pinlabel
+(14) {/Times-Roman cf} 2 20 180 0.75 -192 -128 pinlabel
+(16) {/Times-Roman cf} 2 20 180 0.75 -192 -192 pinlabel
+(6) {/Times-Roman cf} 2 29 180 0.75 -64 64 pinlabel
+(8) {/Times-Roman cf} 2 29 180 0.75 -128 64 pinlabel
+(21) {/Times-Roman cf} 2 17 180 0.75 -128 -256 pinlabel
+(23) {/Times-Roman cf} 2 17 180 0.75 -64 -256 pinlabel
+(25) {/Times-Roman cf} 2 17 180 0.75 0 -256 pinlabel
+(27) {/Times-Roman cf} 2 17 180 0.75 64 -256 pinlabel
+(32) {/Times-Roman cf} 2 23 180 0.75 128 -192 pinlabel
+(34) {/Times-Roman cf} 2 23 180 0.75 128 -128 pinlabel
+(36) {/Times-Roman cf} 2 23 180 0.75 128 -64 pinlabel
+(38) {/Times-Roman cf} 2 23 180 0.75 128 0 pinlabel
+(43) {/Times-Roman cf} 2 29 180 0.75 64 64 pinlabel
+(29) {/Times-Roman cf} 2 20 180 0.75 192 -256 pinlabel
+(31) {/Times-Roman cf} 2 20 180 0.75 192 -192 pinlabel
+(33) {/Times-Roman cf} 2 20 180 0.75 192 -128 pinlabel
+(35) {/Times-Roman cf} 2 20 180 0.75 192 -64 pinlabel
+(37) {/Times-Roman cf} 2 20 180 0.75 192 0 pinlabel
+(39) {/Times-Roman cf} 2 20 180 0.75 192 64 pinlabel
+(1) {/Times-Roman cf} 2 17 0 0.75 0 64 pinlabel
+(2) {/Times-Roman cf} 2 17 180 0.75 -64 128 pinlabel
+(4) {/Times-Roman cf} 2 17 180 0.75 -128 128 pinlabel
+(6) {/Times-Roman cf} 2 17 180 0.75 -192 128 pinlabel
+(40) {/Times-Roman cf} 2 17 180 0.75 128 128 pinlabel
+(42) {/Times-Roman cf} 2 17 180 0.75 64 128 pinlabel
+(18) {/Times-Roman cf} 2 29 180 0.75 -192 -320 pinlabel
+(20) {/Times-Roman cf} 2 29 180 0.75 -128 -320 pinlabel
+(22) {/Times-Roman cf} 2 29 180 0.75 -64 -320 pinlabel
+(24) {/Times-Roman cf} 2 29 180 0.75 0 -320 pinlabel
+(26) {/Times-Roman cf} 2 29 180 0.75 64 -320 pinlabel
+(28) {/Times-Roman cf} 2 29 180 0.75 128 -320 pinlabel
+(7) {/Times-Roman cf} 2 23 180 0.75 -256 64 pinlabel
+(9) {/Times-Roman cf} 2 23 180 0.75 -256 0 pinlabel
+(11) {/Times-Roman cf} 2 23 180 0.75 -256 -64 pinlabel
+(13) {/Times-Roman cf} 2 23 180 0.75 -256 -128 pinlabel
+(15) {/Times-Roman cf} 2 23 180 0.75 -256 -192 pinlabel
+(17) {/Times-Roman cf} 2 23 180 0.75 -256 -256 pinlabel
+(41) {/Times-Roman cf} 2 31 180 0.75 128 64 pinlabel
+(8) {/Times-Roman cf} 2 28 180 0.75 -192 64 pinlabel
+sce
+1 1.00 432 -256 0 0.00 360.00 xcarc
+1.000 0.000 0.000 scb
+(30) {/Times-Roman cf} 2 19 180 0.75 128 -256 pinlabel
+(19) {/Times-Roman cf} 2 16 180 0.75 -192 -256 pinlabel
+0.000 0.000 1.000 scb
+(44) {/Times-Roman cf} 2 29 180 0.75 0 160 label
+sce
+1.00 0 0 128 pin
+1.000 0.000 0.000 scb
+(44) {/Times-Roman cf} 2 17 180 0.75 0 128 pinlabel
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/pixmaps/a.gif b/lib/pixmaps/a.gif
new file mode 100644
index 0000000..825bbc6
--- /dev/null
+++ b/lib/pixmaps/a.gif
Binary files differ
diff --git a/lib/pixmaps/a.xpm b/lib/pixmaps/a.xpm
new file mode 100644
index 0000000..26d6e65
--- /dev/null
+++ b/lib/pixmaps/a.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+
+static char * a_xpm[] = {
+"20 20 6 1",
+" c #FFFFFFFFFFFF",
+". c #000000000000",
+"X c #BABAC1C1FFFF",
+"o c #00000000FFFF",
+"O c #7D7D9797FFFF",
+"+ c #1A1AB3B32020",
+" ",
+" ...... ",
+" .. .. ",
+" . XXX. ",
+" . oooX . ",
+" . XooX . ",
+" . XoXo . ",
+" . XoX . ",
+" . OX . ",
+" . + + . ",
+" . + ++ ++ +. ",
+" . + + . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" ...... ",
+" "};
diff --git a/lib/pixmaps/b.gif b/lib/pixmaps/b.gif
new file mode 100644
index 0000000..8b35cb1
--- /dev/null
+++ b/lib/pixmaps/b.gif
Binary files differ
diff --git a/lib/pixmaps/b.xpm b/lib/pixmaps/b.xpm
new file mode 100644
index 0000000..4bcde8b
--- /dev/null
+++ b/lib/pixmaps/b.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * b_xpm[] = {
+"20 20 5 1",
+" c #FFFFFFFFFFFF",
+". c #000000000000",
+"X c #BEFBC30BFFFF",
+"o c #00000000FFFF",
+"O c #79E79658FFFF",
+" ",
+" .................. ",
+" . XXX. ",
+" . oooX. ",
+" . XooX. ",
+" . XoXo . ",
+" . XoX . ",
+" . OX . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .................. ",
+" "};
diff --git a/lib/pixmaps/bd.gif b/lib/pixmaps/bd.gif
new file mode 100644
index 0000000..12d1ac3
--- /dev/null
+++ b/lib/pixmaps/bd.gif
Binary files differ
diff --git a/lib/pixmaps/bd.xpm b/lib/pixmaps/bd.xpm
new file mode 100644
index 0000000..6ab221a
--- /dev/null
+++ b/lib/pixmaps/bd.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * bd_xpm[] = {
+"20 20 3 1",
+" c #FFFF00000000",
+". c #FFFFFFFFFFFF",
+"X c #000000000000",
+" ",
+" .................. ",
+" .................. ",
+"XXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXX",
+" .................. ",
+" .................. ",
+" .................. ",
+" .................. ",
+"XXX..XXXX..XXXX..XXX",
+"XXX..XXXX..XXXX..XXX",
+" .................. ",
+" .................. ",
+" .................. ",
+" .................. ",
+".XX..XX..XX..XX..XX.",
+".XX..XX..XX..XX..XX.",
+" .................. ",
+" .................. ",
+" "};
diff --git a/lib/pixmaps/ccw.gif b/lib/pixmaps/ccw.gif
new file mode 100644
index 0000000..69b98d6
--- /dev/null
+++ b/lib/pixmaps/ccw.gif
Binary files differ
diff --git a/lib/pixmaps/ccw.xpm b/lib/pixmaps/ccw.xpm
new file mode 100644
index 0000000..4ae538c
--- /dev/null
+++ b/lib/pixmaps/ccw.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * ccw_xpm[] = {
+"20 20 5 1",
+" c #FFFFFFFFFFFF",
+". c #B6DAB2CAB6DA",
+"X c #000000000000",
+"o c #79E77DF779E7",
+"O c #618565956185",
+" ",
+" . ",
+" X .. ",
+" .XXXXXXo ",
+" XXXXXXXXXo ",
+" .XXo. .XXX ",
+" XXXXXO XXo ",
+" XX... XX ",
+" .. .Xo ",
+" XX. ",
+" . XX. ",
+" XX XX ",
+" oXo .Xo ",
+" XX XX ",
+" oXX XXo ",
+" XXX. .XXX ",
+" oXXXXXXXo ",
+" XXXXo ",
+" .. ",
+" "};
diff --git a/lib/pixmaps/co.gif b/lib/pixmaps/co.gif
new file mode 100644
index 0000000..6ae97dc
--- /dev/null
+++ b/lib/pixmaps/co.gif
Binary files differ
diff --git a/lib/pixmaps/co.xpm b/lib/pixmaps/co.xpm
new file mode 100644
index 0000000..ec2616d
--- /dev/null
+++ b/lib/pixmaps/co.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * co_xpm[] = {
+"20 20 5 1",
+" c #000000000000",
+". c #FFFF00000000",
+"X c #00000000FFFF",
+"o c #FFFFFFFF0000",
+"O c #0000FFFF0000",
+" ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" .........XXXXXXXXX ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" oooooooooOOOOOOOOO ",
+" "};
diff --git a/lib/pixmaps/cp.gif b/lib/pixmaps/cp.gif
new file mode 100644
index 0000000..d05787a
--- /dev/null
+++ b/lib/pixmaps/cp.gif
Binary files differ
diff --git a/lib/pixmaps/cp.xpm b/lib/pixmaps/cp.xpm
new file mode 100644
index 0000000..b443f71
--- /dev/null
+++ b/lib/pixmaps/cp.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * cp_xpm[] = {
+"20 20 7 1",
+" c #FFFFFFFFFFFF",
+". c #000000000000",
+"X c #B6DAB2CAB6DA",
+"o c #FFFF82078617",
+"O c #FFFF00000000",
+"+ c #79E77DF779E7",
+"@ c #618565956185",
+" . ",
+" .X ",
+" X.. ooO ",
+" XXXX...XX++ OOO ",
+" ......... OO ",
+" ......+ Oo ",
+" X...+ O ",
+" X...++ O ",
+" .....+ O O o",
+" @.. ..X OOO ",
+" X@+ X@X . OO ",
+" .X O ",
+" X..o ",
+" XXXX...XX++ ",
+" ......... ",
+" ......+ ",
+" X...+ ",
+" .....++ ",
+" @.. ..+ ",
+" X@+ X+X "};
diff --git a/lib/pixmaps/cw.gif b/lib/pixmaps/cw.gif
new file mode 100644
index 0000000..07fcea9
--- /dev/null
+++ b/lib/pixmaps/cw.gif
Binary files differ
diff --git a/lib/pixmaps/cw.xpm b/lib/pixmaps/cw.xpm
new file mode 100644
index 0000000..1d4d84c
--- /dev/null
+++ b/lib/pixmaps/cw.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * cw_xpm[] = {
+"20 20 5 1",
+" c #FFFFFFFFFFFF",
+". c #B6DAB2CAB6DA",
+"X c #000000000000",
+"o c #79E77DF779E7",
+"O c #618565956185",
+" ",
+" . ",
+" .. X ",
+" oXXXXXX. ",
+" oXXXXXXXXX ",
+" XXX. .oXX. ",
+" oXX OXXXXX ",
+" XX ...XX ",
+" oX. .. ",
+" .XX ",
+" .XX . ",
+" XX XX ",
+" oX. oXo ",
+" XX XX ",
+" oXX XXo ",
+" XXX. .XXX ",
+" oXXXXXXXo ",
+" oXXXX ",
+" .. ",
+" "};
diff --git a/lib/pixmaps/d2.gif b/lib/pixmaps/d2.gif
new file mode 100644
index 0000000..963845f
--- /dev/null
+++ b/lib/pixmaps/d2.gif
Binary files differ
diff --git a/lib/pixmaps/d2.xpm b/lib/pixmaps/d2.xpm
new file mode 100644
index 0000000..277b54e
--- /dev/null
+++ b/lib/pixmaps/d2.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * d2_xpm[] = {
+"20 20 5 1",
+" c #FFFFFFFFFFFF",
+". c #FFFF00000000",
+"X c #BEFBBEFBBEFB",
+"o c #000000000000",
+"O c #79E77DF779E7",
+" .. ",
+" .. . ",
+" . .. ",
+" . . ",
+" XoX . ",
+" OoX ",
+" OoOO Xooo ",
+" XoooO Xo Xo",
+" Xooo Xo o",
+" Ooo Oo OoX",
+"ooooooooooo oooooX ",
+"XXooooooooooooo ",
+" XXXXXXXX oX ",
+" o Oo ",
+" . . Xo o ",
+" . . Xo o ",
+" .. . Xooo ",
+" . .. ",
+" .. ",
+" "};
diff --git a/lib/pixmaps/e.gif b/lib/pixmaps/e.gif
new file mode 100644
index 0000000..bb2cb44
--- /dev/null
+++ b/lib/pixmaps/e.gif
Binary files differ
diff --git a/lib/pixmaps/e.xpm b/lib/pixmaps/e.xpm
new file mode 100644
index 0000000..1cbf488
--- /dev/null
+++ b/lib/pixmaps/e.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * e_xpm[] = {
+"20 20 5 1",
+" c #FFFFFFFFFFFF",
+". c #000000000000",
+"X c #BEFBC30BFFFF",
+"o c #00000000FFFF",
+"O c #79E79658FFFF",
+" ",
+" ... .. .. .. .. ",
+" . .. . ",
+" . .. ",
+" . .. ",
+" . .. . ",
+" . .. . ",
+" . XXX. ",
+" . oooX . ",
+" . XooX . . ",
+" . XoXo . . ",
+" . XoX . ",
+" . OX . ",
+" . . . ",
+" . .. ",
+" . . ",
+" . . ",
+" . . ",
+" .................. ",
+" "};
diff --git a/lib/pixmaps/fi.gif b/lib/pixmaps/fi.gif
new file mode 100644
index 0000000..1ed48d8
--- /dev/null
+++ b/lib/pixmaps/fi.gif
Binary files differ
diff --git a/lib/pixmaps/fi.xpm b/lib/pixmaps/fi.xpm
new file mode 100644
index 0000000..9f4a86a
--- /dev/null
+++ b/lib/pixmaps/fi.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * fi_xpm[] = {
+"20 20 3 1",
+" c #FFFF00000000",
+". c #000000000000",
+"X c #FFFFFFFFFFFF",
+" ",
+" .X.X.X.X.XXXX.XXXX ",
+" X.X.X.X.XX.XXXX.XX ",
+" .X.X.X.X.XXX.XXXX. ",
+" X.X.X.X.X.XXXX.XXX ",
+" .X.X.X.X.XX.XXXX.X ",
+" X.X.X.X.XXXXX.XXXX ",
+" .X.X.X.X.X.XXXX.XX ",
+" X.X.X.X.XXXX.XXXX. ",
+" .X.X.X.X..XXXX.XXX ",
+" ..X..X..X......... ",
+" ..X..X..XXXXXXXXXX ",
+" X..X..X........... ",
+" X..X..X..XXXXXXXXX ",
+" .X..X..X.......... ",
+" .X..X..X.XXXXXXXXX ",
+" ..X..X..X......... ",
+" ..X..X..XXXXXXXXXX ",
+" X..X..X........... ",
+" "};
diff --git a/lib/pixmaps/fx.gif b/lib/pixmaps/fx.gif
new file mode 100644
index 0000000..bf0431b
--- /dev/null
+++ b/lib/pixmaps/fx.gif
Binary files differ
diff --git a/lib/pixmaps/fx.xpm b/lib/pixmaps/fx.xpm
new file mode 100644
index 0000000..d67e3f9
--- /dev/null
+++ b/lib/pixmaps/fx.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * fx_xpm[] = {
+"20 20 8 1",
+" c #FFFF00000000",
+". c #FFFFA3A3A3A3",
+"X c #FFFFFFFFFFFF",
+"o c #FFFFFFFF0000",
+"O c #FFFFD7D70000",
+"+ c #C1C1C6C6FFFF",
+"@ c #00000000FFFF",
+"# c #8E8E9999FFFF",
+" .XXXXXXXXXXXX",
+" oooooO XX++XXXXXXX",
+".Ooooooo .X@@@XXXXXX",
+"X ooooooO X+#@@XXXXX",
+"X OooooooO XXX@#X#XX",
+"X OooooooO XXXX@#+XX",
+"X ooooooO XXX+@@@+XX",
+".Ooooooo .XXXXX@@+XX",
+" oooooO XXXXXXX@+XX",
+" .XXXXXXXXX+XX",
+"XXXXXXXXXXXX. ",
+"XXXXXXXXXXX oooooo ",
+"XXXXXXXXXX. ooooooO.",
+"XXXXXXXXXX Ooooooo X",
+"XXXXXXXXX OooooooO X",
+"XXXXXXXXX OooooooO X",
+"XXXXXXXXXX Ooooooo X",
+"XXXXXXXXXX. ooooooO.",
+"XXXXXXXXXXX Oooooo ",
+"XXXXXXXXXXXX. "};
diff --git a/lib/pixmaps/fy.gif b/lib/pixmaps/fy.gif
new file mode 100644
index 0000000..98b665c
--- /dev/null
+++ b/lib/pixmaps/fy.gif
Binary files differ
diff --git a/lib/pixmaps/fy.xpm b/lib/pixmaps/fy.xpm
new file mode 100644
index 0000000..db5766c
--- /dev/null
+++ b/lib/pixmaps/fy.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * fy_xpm[] = {
+"20 20 8 1",
+" c #FFFFFFFFFFFF",
+". c #FFFF00000000",
+"X c #FFFFA3A3A3A3",
+"o c #FFFFFFFF0000",
+"O c #FFFFD7D70000",
+"+ c #C1C1C6C6FFFF",
+"@ c #00000000FFFF",
+"# c #8E8E9999FFFF",
+" ..X X.. ",
+" .oO....Oo. ++ ",
+" .oooOOooo. @@@ ",
+" .oooooooo. +#@@ ",
+" .oooooooo. @# # ",
+" .oooooooo. @#+ ",
+" .OooooooO. +@@@+ ",
+" X.oooooo.X @@+ ",
+" ..OooO.. @+ ",
+" X.OO.X .. + ",
+" .. X.OO.X ",
+" ..OooO.. ",
+" X.oooooo.X",
+" .OooooooO.",
+" .oooooooo.",
+" .oooooooo.",
+" .oooooooo.",
+" .oooOOooo.",
+" .oO....Oo.",
+" ..X X.."};
diff --git a/lib/pixmaps/i.gif b/lib/pixmaps/i.gif
new file mode 100644
index 0000000..45261ec
--- /dev/null
+++ b/lib/pixmaps/i.gif
Binary files differ
diff --git a/lib/pixmaps/i.xpm b/lib/pixmaps/i.xpm
new file mode 100644
index 0000000..fc1233f
--- /dev/null
+++ b/lib/pixmaps/i.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * i_xpm[] = {
+"20 20 6 1",
+" c #00000000FFFF",
+". c #80808080FFFF",
+"X c #FFFFFFFFFFFF",
+"o c #C0C0C0C0FFFF",
+"O c #6C6C7575FFFF",
+"+ c #40404040FFFF",
+" ",
+" .XXo ",
+" OXXXX. ",
+" oXXXXo ",
+" .XXXX ",
+" .oX. ",
+" ",
+" .oXX+ ",
+" oXXXXo ",
+" .XXXo ",
+" XXX ",
+" .XXX ",
+" oXXo ",
+" oXX. ",
+" .XXX ",
+" .XXo .o. ",
+" oXXo.Xo ",
+" oXXXXo ",
+" .XXo + ",
+" "};
diff --git a/lib/pixmaps/li.gif b/lib/pixmaps/li.gif
new file mode 100644
index 0000000..68bde95
--- /dev/null
+++ b/lib/pixmaps/li.gif
Binary files differ
diff --git a/lib/pixmaps/li.xpm b/lib/pixmaps/li.xpm
new file mode 100644
index 0000000..d031521
--- /dev/null
+++ b/lib/pixmaps/li.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * li_xpm[] = {
+"20 20 8 1",
+" c #0000FFFFFFFF",
+". c #28A2AEBAFFFF",
+"X c #000000000000",
+"o c #BEFBBEFBBEFB",
+"O c #79E77DF779E7",
+"+ c #FFFFFFFFFFFF",
+"@ c #79E765951861",
+"# c #FFFFC30B30C2",
+" ... ... ",
+"XXooOo+OXXXO++OooXX ",
+"X+ooo++++Xoo++++++@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+oooOO++OooXX++++@ ",
+"X+oXO++O+OoX++OOO+@ ",
+"X+ooo++++Ooo++++++@ ",
+"X+oooOOO+OoOOOo+++@ ",
+"XOOO####OOO####OOO@ ",
+"X########@########@ ",
+"XXXXXXXOXXXOXXXXXXX "};
diff --git a/lib/pixmaps/mk.gif b/lib/pixmaps/mk.gif
new file mode 100644
index 0000000..65e0dd3
--- /dev/null
+++ b/lib/pixmaps/mk.gif
Binary files differ
diff --git a/lib/pixmaps/mk.xpm b/lib/pixmaps/mk.xpm
new file mode 100644
index 0000000..48cdbdc
--- /dev/null
+++ b/lib/pixmaps/mk.xpm
@@ -0,0 +1,33 @@
+/* XPM */
+static char * mk_xpm[] = {
+"20 20 10 1",
+" c #FFFFFFFFFFFF",
+". c #000000000000",
+"X c #B6DAB2CAB6DA",
+"o c #FFFF82078617",
+"O c #FFFF00000000",
+"+ c #79E77DF779E7",
+"@ c #618565956185",
+"# c #BEFBBEFBBEFB",
+"$ c #FFFF92488E38",
+"% c #FFFFC30B30C2",
+" . ",
+" .X ",
+" X.. ooO ",
+" XXXX...XX++ OOO ",
+" ......... OO ",
+" ......+ Oo ",
+" X...+ O ",
+" X...++ O ",
+" .....+ O O o",
+" @.. ..X OOO ",
+" X@+ X@X OO ",
+" ... ..O ",
+" ...# .#$ ...",
+" .###+ +#+ .",
+" .#++ +# ++ .",
+" .###+ +#+ .",
+" .#++ +# ++ .",
+" .### +# .",
+" .##...+... .",
+" ...%%%.%%%..."};
diff --git a/lib/pixmaps/mv.gif b/lib/pixmaps/mv.gif
new file mode 100644
index 0000000..59a6eea
--- /dev/null
+++ b/lib/pixmaps/mv.gif
Binary files differ
diff --git a/lib/pixmaps/mv.xpm b/lib/pixmaps/mv.xpm
new file mode 100644
index 0000000..843242d
--- /dev/null
+++ b/lib/pixmaps/mv.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * mv_xpm[] = {
+"20 20 8 1",
+" c white",
+". c gray75",
+"X c gray90",
+"o c #B6DAB2CAB6DA",
+"O c gray80",
+"+ c #618565956185",
+"@ c black",
+"# c #79E77DF779E7",
+" . ",
+" .X ",
+" .. ",
+" XXXX..oXX.O ",
+" ......o..XX ",
+" ......O XXX ",
+" o....OX XX ",
+" o...oOOX XO ",
+" .....oX+ XXO ",
+" O.XXXX.XX+ XO ",
+" X.OXOX X.XX@XXo ",
+" XX XoXXXXX@oXXo ",
+" XXX XXXXXo@@XXXo ",
+" XX X#ooo@@@oo## ",
+" OX X@@@@@@@@@ ",
+" XX X@@@@@@# ",
+" O XXo@@@# ",
+" OX X@@@@@## ",
+" OX+@@ @@# ",
+" o+# o#o "};
diff --git a/lib/pixmaps/pa.gif b/lib/pixmaps/pa.gif
new file mode 100644
index 0000000..abfcb3b
--- /dev/null
+++ b/lib/pixmaps/pa.gif
Binary files differ
diff --git a/lib/pixmaps/pa.xpm b/lib/pixmaps/pa.xpm
new file mode 100644
index 0000000..2fef229
--- /dev/null
+++ b/lib/pixmaps/pa.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * pa_xpm[] = {
+"20 20 6 1",
+" c steelblue3",
+". c gray85",
+"X c pink",
+"o c red",
+"O c pink3",
+"+ c white",
+" ",
+" ........XXXX...... ",
+" oooooXOOooooOX.... ",
+" .OoooXoX.XOOoo.... ",
+" .XooooX....Xooo... ",
+" .XoooO......XooO.. ",
+" ..oooX.......ooo.. ",
+" ..ooo........ooo.. ",
+" ..oooX.......ooo.. ",
+" ..oooO......XooO.. ",
+" ..ooooX....Xooo... ",
+" ..oooXoX.XOOoo.... ",
+" ..oooXOOooooOX.... ",
+" ..ooo...XXXX...... ",
+" ooo ",
+"+++ooo++++++++++++++",
+"++XoooX+++++++++++++",
+"++OoooO+++++++++++++",
+"XoooooooX+++++++++++",
+"++++++++++++++++++++"};
diff --git a/lib/pixmaps/pl.gif b/lib/pixmaps/pl.gif
new file mode 100644
index 0000000..635ba97
--- /dev/null
+++ b/lib/pixmaps/pl.gif
Binary files differ
diff --git a/lib/pixmaps/pl.xpm b/lib/pixmaps/pl.xpm
new file mode 100644
index 0000000..3ec7e85
--- /dev/null
+++ b/lib/pixmaps/pl.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * pl_xpm[] = {
+"20 20 7 1",
+" c #A2A2B5B5CDCD",
+". c #00000000FFFF",
+"X c #3D3DC4C4FFFF",
+"o c #0000FFFFFFFF",
+"O c #000000000000",
+"+ c #FFFFFFFFFFFF",
+"@ c #79797D7D7979",
+" .... .... ",
+"Xo..oooo.O.Xooo..OO ",
+"OooooooooOXXoooooX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"Ooooo.XooOXXo.oooX. ",
+"OoX.Xoo.oOX.XoX.oX. ",
+"OooooooooOXXoooooX. ",
+"Oooo....oOX....ooX. ",
+"OX..++++.O.++++..X. ",
+" ++++++++.++++++++X ",
+"OOOOOOO@OOO@OOOOOO "};
diff --git a/lib/pixmaps/pm.gif b/lib/pixmaps/pm.gif
new file mode 100644
index 0000000..0614059
--- /dev/null
+++ b/lib/pixmaps/pm.gif
Binary files differ
diff --git a/lib/pixmaps/pm.xpm b/lib/pixmaps/pm.xpm
new file mode 100644
index 0000000..dc3ab8e
--- /dev/null
+++ b/lib/pixmaps/pm.xpm
@@ -0,0 +1,32 @@
+/* XPM */
+static char * pm_xpm[] = {
+"20 20 9 1",
+" c #000000000000",
+". c #808080808080",
+"X c #FFFF00000000",
+"o c #FFFFFFFFFFFF",
+"O c #C0C0C0C0C0C0",
+"+ c #FFFFB7B7C1C1",
+"@ c #00000000FFFF",
+"# c #B3B3CACAFFFF",
+"$ c #7F7F8E8EFFFF",
+" . XXXXXXXXX",
+" o XXXXXXXXX",
+" OoO ++XXXXXXX",
+" oOo Oooo+XXXXX",
+" .o.o. XXooX+XXX",
+" Oo oO XXXo+oXXX",
+" .ooooo. X+X+ooXXX",
+" Oo oO XX+oooXXX",
+" o. .o XXXXX+XXX",
+".ooo ooo.@@@@@@@@@",
+" ooooo#@@@",
+"XXXXXXXXX@@@o$@$$#@@",
+"XXXXXXXXX@@@o$@@@o$@",
+"XXXXXXXXX@@@o$@@$o@@",
+"XXXXXXXXX@@@oooo#@@@",
+"XXXXXXXXX@@@o$@@$o@@",
+"XXXXXXXXX@@@o$@@@o$@",
+"XXXXXXXXX@@@o$@$$#@@",
+"XXXXXXXXX@@ooooo#@@@",
+"XXXXXXXXX@@@@@@@@@@@"};
diff --git a/lib/pixmaps/pn.gif b/lib/pixmaps/pn.gif
new file mode 100644
index 0000000..73214cb
--- /dev/null
+++ b/lib/pixmaps/pn.gif
Binary files differ
diff --git a/lib/pixmaps/pn.xpm b/lib/pixmaps/pn.xpm
new file mode 100644
index 0000000..f61c00e
--- /dev/null
+++ b/lib/pixmaps/pn.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * pn_xpm[] = {
+"20 20 3 1",
+" c white",
+". c tan",
+"X c beige",
+" .. .. ",
+" .. .. .. ",
+" .. .. .. ",
+" .. .. .. ",
+" .. .. .. .. ",
+" .. .. .. .. ",
+" .. .. .. .. ",
+" .. ........ .. ",
+" ........... ... ",
+" ........... .... ",
+" .......... .... ",
+" ..........X... ",
+" .............. ",
+" ............. ",
+" ............ ",
+" .......... ",
+" .......... ",
+" ........ ",
+" ....... ",
+" ....... "};
diff --git a/lib/pixmaps/po2.gif b/lib/pixmaps/po2.gif
new file mode 100644
index 0000000..b22e271
--- /dev/null
+++ b/lib/pixmaps/po2.gif
Binary files differ
diff --git a/lib/pixmaps/po2.xpm b/lib/pixmaps/po2.xpm
new file mode 100644
index 0000000..44ef438
--- /dev/null
+++ b/lib/pixmaps/po2.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char * po2_xpm[] = {
+"20 20 4 1",
+" c #FFFFFFFFFFFF",
+". c #00000000FFFF",
+"X c #000000000000",
+"o c #28A2AEBAFFFF",
+" . ",
+" ... ",
+" ..... ",
+" ....... ",
+" ......... ",
+" ........... ",
+" ............. ",
+" ............... ",
+" ..... ",
+" ..... ",
+" ..... ",
+"XXXXXXXXXXXXXXXXXXXX",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooo "};
diff --git a/lib/pixmaps/pu2.gif b/lib/pixmaps/pu2.gif
new file mode 100644
index 0000000..9a5edbc
--- /dev/null
+++ b/lib/pixmaps/pu2.gif
Binary files differ
diff --git a/lib/pixmaps/pu2.xpm b/lib/pixmaps/pu2.xpm
new file mode 100644
index 0000000..d4e8bcc
--- /dev/null
+++ b/lib/pixmaps/pu2.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char * pu2_xpm[] = {
+"20 20 4 1",
+" c #FFFFFFFFFFFF",
+". c #00000000FFFF",
+"X c #000000000000",
+"o c #28A2AEBAFFFF",
+" ..... ",
+" ..... ",
+" ..... ",
+" ..... ",
+" ..... ",
+" ..... ",
+" ..... ",
+" ..... ",
+"XXXXXXXXXXXXXXXXXXXX",
+" ooooo ",
+" ooooo ",
+" ooooo ",
+" ooooooooooooooo ",
+" ooooooooooooo ",
+" ooooooooooo ",
+" ooooooooo ",
+" ooooooo ",
+" ooooo ",
+" ooo ",
+" o "};
diff --git a/lib/pixmaps/pz.gif b/lib/pixmaps/pz.gif
new file mode 100644
index 0000000..34b2765
--- /dev/null
+++ b/lib/pixmaps/pz.gif
Binary files differ
diff --git a/lib/pixmaps/pz.xpm b/lib/pixmaps/pz.xpm
new file mode 100644
index 0000000..7f7df05
--- /dev/null
+++ b/lib/pixmaps/pz.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * pz_xpm[] = {
+"20 20 7 1",
+" c #B0B0FFFF4C4C",
+". c #C0C0C0C0C0C0",
+"X c #000000000000",
+"o c #FFFFFFFF0000",
+"O c #7F7F7F7F0000",
+"+ c #B2B2BFBF1515",
+"@ c #808080808080",
+" .X X. ",
+" X XXX. ",
+" XoX. XoooX. ",
+" XXooX OooooX ",
+" +ooXoooo+@ ",
+". X Xoo+ooooX ",
+"X X@. Ooooo@XX ",
+" X@ooXOOoooooX .",
+".@Xooo+oooooo.X .X",
+"X Xoooooooooo.X .X ",
+" X+ooooOXXooo@X ",
+" XoooO XoX X ",
+" XXO+oooX X X",
+" XooooOooX O .",
+" XoooX +o+XO X",
+" X+ooX Xoo@ X ",
+" XX@ .@X X ",
+" X X ",
+" .X.O XX . ",
+" .X OX X XX"};
diff --git a/lib/pixmaps/q.gif b/lib/pixmaps/q.gif
new file mode 100644
index 0000000..127e302
--- /dev/null
+++ b/lib/pixmaps/q.gif
Binary files differ
diff --git a/lib/pixmaps/q.xpm b/lib/pixmaps/q.xpm
new file mode 100644
index 0000000..f4066ec
--- /dev/null
+++ b/lib/pixmaps/q.xpm
@@ -0,0 +1,28 @@
+/* "unknown" tool */
+
+static char *q_xpm[] = {
+"20 20 4 1",
+". c #FFFFFFFFFFFF",
+"X c #C2C2CECEFFFF",
+"o c #79799090FFFF",
+"O c #00000000FFFF",
+"....................",
+".......XXXX.........",
+".....XoOOOOoX.......",
+".....oOOoXOOOX......",
+"....oOOX..XOOo......",
+"...XOOX....XOO......",
+"...XOO.....XOO......",
+"....XX.....oOo......",
+"..........XOO.......",
+".........XOO........",
+"........XOOX........",
+".......XOO..........",
+".......OOX..........",
+".......oOOXo........",
+".......XOOO.........",
+"........XX..........",
+".......XOOX.........",
+".......oOOo.........",
+".......XOOX.........",
+"...................."};
diff --git a/lib/pixmaps/r.gif b/lib/pixmaps/r.gif
new file mode 100644
index 0000000..7207c90
--- /dev/null
+++ b/lib/pixmaps/r.gif
Binary files differ
diff --git a/lib/pixmaps/s.gif b/lib/pixmaps/s.gif
new file mode 100644
index 0000000..d611516
--- /dev/null
+++ b/lib/pixmaps/s.gif
Binary files differ
diff --git a/lib/pixmaps/s.xpm b/lib/pixmaps/s.xpm
new file mode 100644
index 0000000..f0aec97
--- /dev/null
+++ b/lib/pixmaps/s.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * s_xpm[] = {
+"20 20 6 1",
+" c #FFFFFFFFFFFF",
+". c #1861B2CA2081",
+"X c #618565956185",
+"o c #000000000000",
+"O c #B6DAB2CAB6DA",
+"+ c #79E77DF779E7",
+" . ",
+" . ",
+" . ",
+" . XooXO ",
+" . ooO Oo+ ",
+" .OO o ",
+" .o o ",
+" XO o ",
+" .o. Oo ",
+" o O+ ",
+" . . o ..",
+" o+ .. ",
+" ++ .. ",
+" +O .. ",
+" O+ .. ",
+" o .. ",
+" oO. ",
+". .oXO ",
+" .X. ",
+". . "};
diff --git a/lib/pixmaps/solid.xbm b/lib/pixmaps/solid.xbm
new file mode 100644
index 0000000..aae0777
--- /dev/null
+++ b/lib/pixmaps/solid.xbm
@@ -0,0 +1,26 @@
+/* Definition of a solid square the size of the other toolbar pixmaps. */
+/* This is used for drawing the "color" image on the color tool button */
+
+#define solid_width 20
+#define solid_height 20
+static char solid_bits[] = {
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f};
diff --git a/lib/pixmaps/stip12.xbm b/lib/pixmaps/stip12.xbm
new file mode 100644
index 0000000..afa7d06
--- /dev/null
+++ b/lib/pixmaps/stip12.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip12_width 20
+#define stip12_height 20
+static char stip12_bits[] = {
+ 0x00, 0x00, 0x00,
+ 0x44, 0x44, 0x04,
+ 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x01,
+ 0x00, 0x00, 0x00,
+ 0x44, 0x44, 0x04,
+ 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x01,
+ 0x00, 0x00, 0x00,
+ 0x44, 0x44, 0x04,
+ 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x01,
+ 0x00, 0x00, 0x00,
+ 0x44, 0x44, 0x04,
+ 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x01,
+ 0x00, 0x00, 0x00,
+ 0x44, 0x44, 0x04,
+ 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x01};
diff --git a/lib/pixmaps/stip25.xbm b/lib/pixmaps/stip25.xbm
new file mode 100644
index 0000000..6934863
--- /dev/null
+++ b/lib/pixmaps/stip25.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip25_width 20
+#define stip25_height 20
+static char stip25_bits[] = {
+ 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x0a};
diff --git a/lib/pixmaps/stip38.xbm b/lib/pixmaps/stip38.xbm
new file mode 100644
index 0000000..4c800f4
--- /dev/null
+++ b/lib/pixmaps/stip38.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip38_width 20
+#define stip38_height 20
+static char stip38_bits[] = {
+ 0x11, 0x11, 0x01,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0x88, 0x88, 0x08,
+ 0x11, 0x11, 0x01,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0x88, 0x88, 0x08,
+ 0x11, 0x11, 0x01,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0x88, 0x88, 0x08,
+ 0x11, 0x11, 0x01,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0x88, 0x88, 0x08,
+ 0x11, 0x11, 0x01,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0x88, 0x88, 0x08};
diff --git a/lib/pixmaps/stip50.xbm b/lib/pixmaps/stip50.xbm
new file mode 100644
index 0000000..6d214d4
--- /dev/null
+++ b/lib/pixmaps/stip50.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip50_width 20
+#define stip50_height 20
+static char stip50_bits[] = {
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a};
diff --git a/lib/pixmaps/stip62.xbm b/lib/pixmaps/stip62.xbm
new file mode 100644
index 0000000..6edd083
--- /dev/null
+++ b/lib/pixmaps/stip62.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip62_width 20
+#define stip62_height 20
+static char stip62_bits[] = {
+ 0xee, 0xee, 0x0e,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x77, 0x77, 0x07,
+ 0xee, 0xee, 0x0e,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x77, 0x77, 0x07,
+ 0xee, 0xee, 0x0e,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x77, 0x77, 0x07,
+ 0xee, 0xee, 0x0e,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x77, 0x77, 0x07,
+ 0xee, 0xee, 0x0e,
+ 0x55, 0x55, 0x05,
+ 0xaa, 0xaa, 0x0a,
+ 0x77, 0x77, 0x07};
diff --git a/lib/pixmaps/stip75.xbm b/lib/pixmaps/stip75.xbm
new file mode 100644
index 0000000..66074ce
--- /dev/null
+++ b/lib/pixmaps/stip75.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip75_width 20
+#define stip75_height 20
+static char stip75_bits[] = {
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0x55, 0x55, 0x05,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0x55, 0x55, 0x05,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0x55, 0x55, 0x05,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0x55, 0x55, 0x05,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0x55, 0x55, 0x05};
diff --git a/lib/pixmaps/stip88.xbm b/lib/pixmaps/stip88.xbm
new file mode 100644
index 0000000..3be43cf
--- /dev/null
+++ b/lib/pixmaps/stip88.xbm
@@ -0,0 +1,25 @@
+/* Definition of a stippled square the size of the toolbar pixmaps. */
+
+#define stip88_width 20
+#define stip88_height 20
+static char stip88_bits[] = {
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0xee, 0xee, 0x0e,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0xee, 0xee, 0x0e,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0xee, 0xee, 0x0e,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0xee, 0xee, 0x0e,
+ 0xff, 0xff, 0x0f,
+ 0xaa, 0xaa, 0x0a,
+ 0xff, 0xff, 0x0f,
+ 0xee, 0xee, 0x0e};
diff --git a/lib/pixmaps/t.gif b/lib/pixmaps/t.gif
new file mode 100644
index 0000000..21a6863
--- /dev/null
+++ b/lib/pixmaps/t.gif
Binary files differ
diff --git a/lib/pixmaps/t.xpm b/lib/pixmaps/t.xpm
new file mode 100644
index 0000000..f8df0da
--- /dev/null
+++ b/lib/pixmaps/t.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * t_xpm[] = {
+"20 20 6 1",
+" c #FFFFFFFFFFFF",
+". c #1A1AB3B32020",
+"X c #B3B3B3B3B3B3",
+"o c #000000000000",
+"O c #666666666666",
+"+ c #7F7F7F7F7F7F",
+" .",
+" Xoo .",
+" ooX .",
+" oo .",
+" ooX .",
+" OooO .",
+" oXoo .",
+" Oo ooX .",
+" O oo .",
+" Xo XoX .",
+" oO Xoo .",
+" Xo XoX .",
+" OX XoO .",
+" Xo++++++Xoo .",
+" OooooooooooX .",
+" Xo+ XoO .",
+" Oo+ ooX .",
+" Xoo OoOX .",
+" XooO+ +ooo+X.",
+"+ooooo+ Xoooooo."};
diff --git a/lib/pixmaps/tg.gif b/lib/pixmaps/tg.gif
new file mode 100644
index 0000000..e2ff6d3
--- /dev/null
+++ b/lib/pixmaps/tg.gif
Binary files differ
diff --git a/lib/pixmaps/tg.xpm b/lib/pixmaps/tg.xpm
new file mode 100644
index 0000000..b95b2f4
--- /dev/null
+++ b/lib/pixmaps/tg.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * tg_xpm[] = {
+"20 20 5 1",
+" c white",
+". c #1A1AB3B32020",
+"X c yellow2",
+"o c orange",
+"O c gold",
+" .",
+" Xoo .",
+" ooX .",
+" oo .",
+" ooX .",
+" OooO .",
+" oXoo .",
+" Oo ooX .",
+" O oo .",
+" Xo XoX .",
+" oO Xoo .",
+" Xo XoX .",
+" OX XoO .",
+" XoOOOOOOXoo .",
+" OooooooooooX .",
+" XoO XoO .",
+" OoO ooX .",
+" Xoo OoOX .",
+" XooOO OoooOX.",
+"OoooooO Xoooooo."};
diff --git a/lib/pixmaps/ti.gif b/lib/pixmaps/ti.gif
new file mode 100644
index 0000000..9cc1630
--- /dev/null
+++ b/lib/pixmaps/ti.gif
Binary files differ
diff --git a/lib/pixmaps/ti.xpm b/lib/pixmaps/ti.xpm
new file mode 100644
index 0000000..81cd548
--- /dev/null
+++ b/lib/pixmaps/ti.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * ti_xpm[] = {
+"20 20 6 1",
+" c white",
+". c #1A1AB3B32020",
+"X c palegreen",
+"o c yellowgreen",
+"O c green2",
+"+ c green",
+" .",
+" X.. .",
+" ..X .",
+" .. .",
+" ..X .",
+" o..o .",
+" .X.. .",
+" o. ..X .",
+" o .. .",
+" X. X.X .",
+" .o X.. .",
+" X. X.X .",
+" oX X.o .",
+" X.OOOOOOX.. .",
+" o..........X .",
+" X.O X.o .",
+" +.O ..X .",
+" X.. o.oX .",
+" X..oO O...OX.",
+"O.....O X......."};
diff --git a/lib/pixmaps/tp.gif b/lib/pixmaps/tp.gif
new file mode 100644
index 0000000..7c84d1d
--- /dev/null
+++ b/lib/pixmaps/tp.gif
Binary files differ
diff --git a/lib/pixmaps/tp.xpm b/lib/pixmaps/tp.xpm
new file mode 100644
index 0000000..0bbde3a
--- /dev/null
+++ b/lib/pixmaps/tp.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * tp_xpm[] = {
+"20 20 5 1",
+" c white",
+". c #1A1AB3B32020",
+"X c pink",
+"o c red",
+"O c pink3",
+" .",
+" Xoo .",
+" ooX .",
+" oo .",
+" ooX .",
+" OooO .",
+" oXoo .",
+" Oo ooX .",
+" O oo .",
+" Xo XoX .",
+" oO Xoo .",
+" Xo XoX .",
+" OX XoO .",
+" XoOOOOOOXoo .",
+" OooooooooooX .",
+" XoO XoO .",
+" OoO ooX .",
+" Xoo OoOX .",
+" XooOO OoooOX.",
+"OoooooO Xoooooo."};
diff --git a/lib/pixmaps/uj.gif b/lib/pixmaps/uj.gif
new file mode 100644
index 0000000..2a091a0
--- /dev/null
+++ b/lib/pixmaps/uj.gif
Binary files differ
diff --git a/lib/pixmaps/uj.xpm b/lib/pixmaps/uj.xpm
new file mode 100644
index 0000000..eb418d4
--- /dev/null
+++ b/lib/pixmaps/uj.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * uj_xpm[] = {
+"20 20 6 1",
+" c #B0B0FFFF4C4C",
+". c #7F7F7F7F0000",
+"X c #000000000000",
+"o c #8484B3B31111",
+"O c #C0C0C0C0C0C0",
+"+ c #808080808080",
+" .. Xo ",
+". Xo .. ",
+" . oXX XXX. ",
+" X oXXXX oXXXX ",
+".X ooXXXoXXXX ",
+" X XXXXXXXo ",
+" XX XXXXXoo ",
+". XXX. XXXXXX O",
+" X.XXXXXXXXXXXX OX",
+"X oXXXXXXXXXXXX OX ",
+" oXXXXX+oXXXX+X ",
+" XXXX+ XXX X ",
+" oXXXXXXo X X",
+" XXXXXoXXo o O",
+" XXXXX XXXXo ooX",
+" oXXX .XXX oX ",
+" oXo oX o ",
+" X X ",
+" OXX oXX O ",
+" OX .X X X XX"};
diff --git a/lib/pixmaps/w.gif b/lib/pixmaps/w.gif
new file mode 100644
index 0000000..9ba9b58
--- /dev/null
+++ b/lib/pixmaps/w.gif
Binary files differ
diff --git a/lib/pixmaps/w.xpm b/lib/pixmaps/w.xpm
new file mode 100644
index 0000000..27f256a
--- /dev/null
+++ b/lib/pixmaps/w.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * w_xpm[] = {
+"20 20 5 1",
+" c white",
+". c black",
+"X c #BEFBC30BFFFF",
+"o c blue",
+"O c #79E79658FFFF",
+" ",
+" . ",
+" XXX. ",
+" oooX. ",
+" XooX. ",
+" . XoXo . ",
+" .. XoX . ",
+" . OX . ",
+" .. . ",
+" .. . ",
+" . . ",
+" .. . ",
+" .. . ",
+" .. . ",
+" ... . ",
+" .. . ",
+" .... . ",
+" ........ . ",
+" ..... ",
+" "};
diff --git a/lib/pixmaps/xcircuit.gif b/lib/pixmaps/xcircuit.gif
new file mode 100644
index 0000000..e8117a2
--- /dev/null
+++ b/lib/pixmaps/xcircuit.gif
Binary files differ
diff --git a/lib/pixmaps/xcircuit.ico b/lib/pixmaps/xcircuit.ico
new file mode 100644
index 0000000..2e0ff8c
--- /dev/null
+++ b/lib/pixmaps/xcircuit.ico
Binary files differ
diff --git a/lib/pixmaps/xcircuit.xpm b/lib/pixmaps/xcircuit.xpm
new file mode 100644
index 0000000..03eb376
--- /dev/null
+++ b/lib/pixmaps/xcircuit.xpm
@@ -0,0 +1,95 @@
+/* XPM */
+static char * xcircuit_xpm[] = {
+/* width height num_colors chars_per_pixel */
+"69 79 10 1",
+/* colors */
+" c #ff0000",
+". c #efefc7",
+"X c gray40",
+"o c black",
+"O c gray80",
+"+ c gray50",
+"@ c #b88d5c",
+"# c white",
+"$ c gray90",
+"% c #eaeaea",
+/* pixels */
+" ",
+" ................... .................... .................... ..... ",
+" ................... .................... .................... ..... ",
+" ...X..X...oo..XX... ....XX.X.o.oo.OX.... .....+.o.+oOo....... ..... ",
+" ...X.X..X.Oo.XX.... ....XX..X..oo.X..... .....+Oo.o.Oo....... ..... ",
+" ................... .................... .................... ..... ",
+" ................... .................... .................... ..... ",
+" ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ ###OX+###$##XX####Ooo$############$############$#######o###$### ",
+" @@@ ####Oo###$#XX####o+oooo###########$############$#######o###$### ",
+" @@@ #####oo##$+o####oo###$o+##Oo######$############$##+o###o###$### ",
+" @@@ ######o+#$o####$o####$#####O######$############$##%+##ooo##$### ",
+" @@@ #######o#o#####oo####$#####o##oOoo$#+ooX##o####o##%X##OoO##$### ",
+" @@@ ########oo#####oO####$####oo##oo#oXOo+#+o#o####o##oo###o###$### ",
+" @@@ #######o++#####o+####$####%o##o%##$o%#####o####o##Oo###o###$### ",
+" @@@ ######Oo#oo####$o####$#####o##o###$o######o####o##Oo###o###$### ",
+" @@@ %%%%%Oo$$ oO%%%%oo%%%Oo+%%%o$$o$$$ X$%%%$$oO$$$o%%Oo%%%o%%%$%%% ",
+" @@@ #####oX##$#oX###$oo$$Xo###Oo##o###$%o+#+o#+o##oo##Oo###o%OX$### ",
+" @@@ ####oo###$#OoX####oooo####ooo#o###$#OoooO##oooOo##ooo##OoX#$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ ######+$#$###########$############$############$###########$### ",
+" @@@ ######oo$$###########$############$############$###########$### ",
+" @@@ ######o#+o$##########$############$############$###########$### ",
+" @@@ ######o##$oo#########$############$############$###########$### ",
+" @@@ ######o##$#Oo+#######%############$############$###########$### ",
+" @@@ ######o##$###+oO#####%############$############$###########$### ",
+" @@@ ######o##$####$XoO###%###########+o###o####o###$###########$### ",
+" @@@ %%%%%%o%%O$$%%%%%oo%%Ooo%%%%%%%%%oo%%%oo%%%oo%%O%%%%%$$$$%%O%%% ",
+" @@@ ######o##$########$o+o##o#######Ooo$#o#o##o#o##$#Oo+#######+XO# ",
+" @@@ ooooooo##$##########oo##ooooooo#o#$o#o#oo#o##ooooooooooooooX#X# ",
+" ... ######o##$########o+#oooO#####o$o#$ooO##oo$####$#Oo+#######OXO# ",
+" @@@ ######o##$######oo###$OO######+o##$+o###+o#####$##o########$### ",
+" @@@ ######o##$####+oO####$############$############$##o########$### ",
+" @@@ ######o##$##+o+######$############$############$##o########$### ",
+" @@@ ######o##$Oo+########$############$############$##o########$### ",
+" @@@ ######o#O+o$#########$############$############$##o########$### ",
+" @@@ ######ooo$###########$############$############$##o########$### ",
+" @@@ ######o$#$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$#########%%%$%%o%%%%%%##$### ",
+" @@@ $$$$$$$$$ $$$$$$$$$$$ $$$$$$$$$$$$ $$$$$$$$$ooooooooooooo$$ $$$ ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$#OOO#######$### ",
+" @@@ #########$###########$############$##########$+ooooooo+$###$### ",
+" @@@ #########$###########$############$#########oo#$##o####oo##$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ #########$###########$############$############$##o########$### ",
+" @@@ $$$$$$$$$ $$$$$$$$$$$ $$$$$$$$$$$$ $$$$$$$$$$$$O$$o$$$$$$$$ $$$ ",
+" @@@ #########$###########$############$#########ooooooooooooo##$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############ooooooo#####$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" @@@ #########$###########$############$############$#ooo#######$### ",
+" @@@ #########$###########$############$############$###########$### ",
+" ... #########$###########$############$############$###########$### ",
+" ... ",
+" ... .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" ... .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" ... .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" ",
+" ......................... ......................................... ",
+" ..o.o.o...o......X..X..o. ......................................... ",
+" ...oooo.X.o.oo.o.X.XX..o. ......................................... ",
+" ......................... ......................................... ",
+" "};
diff --git a/lib/pixmaps/yp.gif b/lib/pixmaps/yp.gif
new file mode 100644
index 0000000..8de2a6a
--- /dev/null
+++ b/lib/pixmaps/yp.gif
Binary files differ
diff --git a/lib/pixmaps/yp.xpm b/lib/pixmaps/yp.xpm
new file mode 100644
index 0000000..700ce33
--- /dev/null
+++ b/lib/pixmaps/yp.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * yp_xpm[] = {
+"20 20 7 1",
+" c #0000FFFFFFFF",
+". c #79E765951861",
+"X c #000000000000",
+"o c #FFFFFFFF0000",
+"O c #FFFFC30B30C2",
+"+ c #FFFFFFFFFFFF",
+"@ c #79E77DF779E7",
+" .... .... ",
+"XX..oooo.X.Oooo..XX ",
+"X+oooooooXOOoooooO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXO.ooo.oO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXO.ooo.oO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXO.ooo.oO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXO.ooo.oO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXO.ooo.oO. ",
+"X+ooo.oooXOOo.oooO. ",
+"X+o.ooo.oXOOooo.oO. ",
+"X+oooooooXOOoooooO. ",
+"X+oo....oXO....ooO. ",
+"XO..++++.X.++++..O. ",
+"X++++++++.++++++++. ",
+"XXXXXXX@XXX@XXXXXXX "};
diff --git a/lib/pixmaps/z4.gif b/lib/pixmaps/z4.gif
new file mode 100644
index 0000000..8150772
--- /dev/null
+++ b/lib/pixmaps/z4.gif
Binary files differ
diff --git a/lib/pixmaps/z4.xpm b/lib/pixmaps/z4.xpm
new file mode 100644
index 0000000..d5c905a
--- /dev/null
+++ b/lib/pixmaps/z4.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * z4_xpm[] = {
+"20 20 7 1",
+" c #FFFFFFFFFFFF",
+". c #666666666666",
+"X c #D9D9D9D9D9D9",
+"o c #000000000000",
+"O c #A2A2B5B5CDCD",
+"+ c #79797D7D7979",
+"@ c #20208989B3B3",
+" ",
+" .XX XX. ",
+" Xooo.O O+oooX ",
+" XooOX XOooX ",
+" oOoX XoOo ",
+" .XXoX XoXX. ",
+" O XoX XoX O ",
+" Xo oX ",
+" O O ",
+" XX ",
+" XX ",
+" O O ",
+" Xo oX ",
+" O XoX XoX O ",
+" .XXoX XoXX. ",
+" oOoX XoOo ",
+" Xoo@X XOooX ",
+" Xooo.O O.oooX ",
+" .XX XX. ",
+" "};
diff --git a/lib/pixmaps/z5.gif b/lib/pixmaps/z5.gif
new file mode 100644
index 0000000..5c40d5c
--- /dev/null
+++ b/lib/pixmaps/z5.gif
Binary files differ
diff --git a/lib/pixmaps/z5.xpm b/lib/pixmaps/z5.xpm
new file mode 100644
index 0000000..2a263d4
--- /dev/null
+++ b/lib/pixmaps/z5.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * z5_xpm[] = {
+"20 20 6 1",
+" c #000000000000",
+". c #FFFFFFFFFFFF",
+"X c #79797D7D7979",
+"o c #A2A2B5B5CDCD",
+"O c #D9D9D9D9D9D9",
+"+ c #666666666666",
+" ...................",
+"..X.............XX..",
+".X o............o X.",
+"..o O..........O o..",
+"...O O..o..o..O O...",
+"....O O. .. .O O....",
+".....O O .. O O.....",
+"......O OO O......",
+"....o OO o....",
+".......OOooOO.......",
+".......OOooOO.......",
+"....o OO o....",
+"......O OO O......",
+".....O O .. O O.....",
+"....O O. .. .O O....",
+"...O O..o..o..O O...",
+"..o O..........O o..",
+".+ o............o X.",
+"..X..............X..",
+"...................."};
diff --git a/lib/python/flatspice.py b/lib/python/flatspice.py
new file mode 100644
index 0000000..89d6263
--- /dev/null
+++ b/lib/python/flatspice.py
@@ -0,0 +1,127 @@
+# flatspice.py
+#-----------------------------------------------------------
+# Python script which writes a SPICE-format netlist.
+# Replaces the code formerly in "netlist.c" (deprecated).
+# Python scripting is now the preferred method for handling
+# netlist output formats.
+#-----------------------------------------------------------
+
+# Select the device string corresponding to the given prefix.
+# Return the body of the string, or an empty string if the prefix doesn't match.
+
+def select(sstr, prefix):
+ ltext = ''
+ if sstr.startswith(prefix):
+ ltext += sstr[len(prefix) + 1:]
+ return ltext
+
+# Generate an ASCII string from an xcircuit string (list)
+
+def textprint(slist, params):
+ ltext = ''
+ is_symbol = 0
+ is_iso = 0
+ for x in slist:
+ try:
+ f = x.keys()[0]
+ except AttributeError: # must be a string
+ if x == 'Return':
+ ltext += '\n'
+ elif x == 'Underline':
+ ltext += '_'
+ elif x == 'Overline':
+ ltext += '!'
+ else: # is a dictionary; will have only one key
+ if f == 'Font':
+ lfont = x[x.keys()[0]]
+ if lfont.startswith('Symbol'):
+ is_symbol = 1
+ else:
+ is_symbol = 0
+ if lfont.endswith('ISO'):
+ is_iso = 1
+ else:
+ is_iso = 0
+ elif f == 'Parameter':
+ ltext += textprint(params[x[x.keys()[0]]], [])
+ else: # text: SPICE translates "mu" to "u"
+ for y in x[x.keys()[0]]:
+ if is_symbol:
+ if y == 'f':
+ ltext += 'phi'
+ elif y == 'm':
+ ltext += 'u'
+ else:
+ ltext += y
+ else:
+ if ord(y) == 181:
+ ltext += 'u'
+ elif ord(y) > 127:
+ ltext += '/' + str(ord(y))
+ else:
+ ltext += y
+ return ltext
+
+
+# Flatten the netlist and write to the output
+
+def recurseflat(outfile, ckt, clist):
+ try:
+ v = ckt['calls'] # calls to subcircuits
+ except KeyError: # A bottom-level circuit element
+ pass
+ else:
+ for y in v:
+ for z in clist:
+ if z['name'] == y['name']:
+ # copy the object and substitute net names into subcircuit ports
+ lobj = z
+ lobj['ports'] = y['ports']
+ recurseflat(outfile, lobj, clist)
+ break;
+ try:
+ w = ckt['devices']
+ except KeyError:
+ pass
+ else:
+ for y in w:
+ for u in y:
+ lstr = select(textprint(u, []), 'spice')
+ if lstr <> '':
+ outfile.write('device: ' + lstr + '\n')
+
+# Top of the flattened-circuit writing routine
+
+def writespiceflat():
+ p=netlist()
+ g=p['globals']
+ c=p['circuit']
+ l=len(c)
+ top=c[l-1]
+ topname=top['name']
+ topname += '.spc'
+ try:
+ outfile=open(topname, 'w')
+ except IOError:
+ return
+
+ # print header line
+
+ outfile.write('*SPICE flattened circuit "' + topname + '"')
+ outfile.write(' from XCircuit v' + str(xc_version))
+ outfile.write(' (Python script "flatspice.py")\n')
+
+ # print global variables
+
+ for x in g: # 'globals' is a list of strings
+ outfile.write('.GLOBAL ' + textprint(x, []) + '\n')
+ outfile.write('\n')
+
+ recurseflat(outfile, top, c)
+ outfile.write('.end\n')
+ outfile.close()
+
+# Key binding and menu button for the spice netlist output
+# bind('Alt_F', 'writespiceflat')
+newbutton('Netlist', 'Write Flattened Spice', 'writespiceflat')
+
diff --git a/lib/python/gettext.py b/lib/python/gettext.py
new file mode 100644
index 0000000..5deda9a
--- /dev/null
+++ b/lib/python/gettext.py
@@ -0,0 +1,46 @@
+# gettext.py
+#-----------------------------------------------------------
+# Python script which creates a function "gettext(filename)"
+# that reads an ASCII file and turns the contents into a
+# text label.
+# Execute this script using menu option "File/Execute Script",
+# if Python has been compiled in.
+#
+# Also: defines a function which can be called with a key
+# macro (gets the filename via popup prompt) and binds it
+# to key "^G" (ctrl-"g"), and defines a button named "Get Text"
+# under the "Edit" menu which does the same.
+#-----------------------------------------------------------
+
+def newlabel(x, y, l):
+ h1=newelement("Label")
+ d = {"scale": 1.0, "rotation": 0, "justify": 0, "pin": 0,
+ "position": (x, y), "string": l}
+ setattr(h1, d)
+ return h1
+
+def gettext(f):
+ try:
+ fi = open(f, 'r')
+ except IOError:
+ return
+ else:
+ T = getcursor();
+ D = {'Font': 'Times-Roman'}
+ S2 = [D]
+ S = fi.readlines()
+ for X in S:
+ Y = X[0:len(X)-1]
+ D = {'Text': Y}
+ S2.append(D)
+ S2.append('Return')
+ h1 = newlabel(T[0], T[1], S2)
+ return h1
+
+def prompttext():
+ filepopup('Enter filename to import:', 'gettext')
+
+bind('Control_G', 'prompttext')
+newbutton('Edit', 'Get Text (^G)', 'prompttext')
+
+#-----------------------------------------------------------
diff --git a/lib/python/loadlgf.py b/lib/python/loadlgf.py
new file mode 100644
index 0000000..723e197
--- /dev/null
+++ b/lib/python/loadlgf.py
@@ -0,0 +1,60 @@
+# loadlgf.py
+#-----------------------------------------------------------
+# Python script which creates a function "loadlgf" that
+# replaces the code formerly in "formats.c" (deprecated).
+# Python scripting is now the preferred method for handling
+# alternate file formats.
+#-----------------------------------------------------------
+
+def loadlgf(f):
+ try:
+ fi = open(f, 'r')
+ except IOError:
+ return
+ else:
+
+ # check magic cookie to see if it's a real LGF file
+
+ S = fi.readline()
+ if (S <> '-5\n'):
+ return
+
+ S = fi.readline()
+ if (S <> 'f s\n'):
+ return
+
+ # Now go load the LGF library (required)
+ # '-1' loads at the end of the current library pages
+
+ library('lgf.lps', -1)
+
+ # clear the page
+
+ reset()
+
+ # read in the file
+
+ S = fi.readlines()
+ for X in S:
+ if (S[0] == '#'):
+ elif (S[0] == 'n'):
+ elif (S[0] == 's'):
+ elif (S[0] == 'l'):
+ elif (S[0] == 'w'):
+ elif (S[0] == 'p'):
+ elif (S[0] == 'b'):
+ elif (S[0] == 'g'):
+ elif (S[0] == 'h'):
+ elif (S[0] == '.'):
+ else:
+
+ h1 = getpage();
+ return h1
+
+def promptlgf():
+ filepopup('Enter filename to load:', 'loadlgf')
+
+bind('Control_l', 'promptlgf')
+newbutton('Edit', 'Load LGF File (^L)', 'promptlgf')
+
+#-----------------------------------------------------------
diff --git a/lib/python/pagebbox.py b/lib/python/pagebbox.py
new file mode 100644
index 0000000..c7f9f80
--- /dev/null
+++ b/lib/python/pagebbox.py
@@ -0,0 +1,68 @@
+# pagebbox.py
+#-----------------------------------------------------------
+# Python script which creates a function "pagebbox(width, height)"
+# that generates a bounding box of the specified width and height.
+#
+# Execute this script using menu option "File/Execute Script",
+# if Python has been compiled in.
+#
+# Add key 'B' for popuppromt asking for page size. Add button to
+# "Edit" menu for same. Add Ctrl-B and Ctrl-Shift-B for standard
+# 8 1/2 x 11 and 11 x 17 page bounding boxes.
+#-----------------------------------------------------------
+
+def newbox(lx, ly, ux, uy):
+ h1=newelement("Polygon")
+ plist = [(lx, ly), (ux, ly), (ux, uy), (lx, uy)]
+ d = {"points": plist}
+ setattr(h1, d)
+ return h1
+
+def pagebbox(w, h):
+ h1 = newbox(0, 0, w, h)
+ d = {"style": 512, "color": (255, 165, 0)}
+ setattr(h1, d)
+ return h1
+
+def intbbox(s):
+ slist = s.split()
+ slen = len(slist)
+ if slen > 1:
+ w = eval(slist[0])
+ else:
+ w = 8.5
+
+ if slen == 3:
+ h = eval(slist[2])
+ elif slen == 2:
+ h = eval(slist[1])
+ else:
+ h = 11
+
+ # note to self: should look at coord style, set default for A4 size
+ # if style is CM, not INCHES.
+
+ p1 = getpage()
+ oscale = p1['output scale']
+
+ inchsc = 192
+ h1 = pagebbox(w * oscale * inchsc, h * oscale * inchsc)
+ return h1
+
+def promptbbox():
+ popupprompt('Enter width x height:', 'intbbox')
+
+def stdbbox():
+ intbbox("8.5 x 11")
+
+def bigbbox():
+ intbbox("11 x 17")
+
+bind('B', 'promptbbox')
+bind('Control_b', 'stdbbox')
+bind('Control_Shift_B', 'bigbbox')
+
+newbutton('Edit', 'New BBox (B)', 'promptbbox')
+# newtool('BBox', 'promptbbox', '', 'bounding box');
+
+#-----------------------------------------------------------
diff --git a/lib/python/spice.py b/lib/python/spice.py
new file mode 100644
index 0000000..9171680
--- /dev/null
+++ b/lib/python/spice.py
@@ -0,0 +1,282 @@
+# spice.py
+#-----------------------------------------------------------------------
+# Python script which writes a SPICE-format netlist.
+# Replaces the code formerly in "netlist.c" (deprecated).
+# Python scripting is now the preferred method for handling
+# netlist output formats.
+#-----------------------------------------------------------------------
+
+import string
+
+#-----------------------------------------------------------------------
+# Parse the output string, substituting for index, ports, parameters,
+# and automatic numbering using the '?' parameter.
+#-----------------------------------------------------------------------
+
+def parsedev(lstr, portdict, devdict, classidx, paramdict):
+ rstr = lstr
+ ltext = ''
+ classname = rstr[0] # single-character SPICE element type
+ try:
+ index = classidx[classname]
+ except KeyError:
+ index = 1
+ classidx[classname] = 1
+
+ if string.find(rstr, '%i'):
+ rstr = string.replace(rstr, '%i', str(index))
+ classidx[classname] = classidx[classname] + 1
+
+ for pt in portdict.keys():
+ ptstr = '%p' + pt
+ rstr = string.replace(rstr, ptstr, portdict[pt])
+ ptstr = '%p' + '"' + pt + '"'
+ rstr = string.replace(rstr, ptstr, portdict[pt])
+
+ for vt in paramdict.keys():
+ vtvalue = paramdict[vt]
+ if vtvalue == '?':
+ vtvalue = str(index);
+ classidx[classname] = classidx[classname] + 1
+
+ vtstr = '%v' + vt
+ rstr = string.replace(rstr, vtstr, vtvalue)
+ vtstr = '%v' + '"' + vt + '"'
+ rstr = string.replace(rstr, vtstr, vtvalue)
+
+ # Simple replacements (%%, %r, %t) (all occurrences)
+ #...................................................
+ if string.find(rstr, '%%'):
+ rstr = string.replace(rstr, '%%', '%')
+ if string.find(rstr, '%n'):
+ rstr = string.replace(rstr, '%n', devdict['name'])
+ if string.find(rstr, '%r'):
+ rstr = string.replace(rstr, '%r', '\n')
+ if string.find(rstr, '%t'):
+ rstr = string.replace(rstr, '%t', '\t')
+
+ return rstr
+
+#-----------------------------------------------------------------------
+# Generate a dictionary of port substitutions and create the
+# device string for output
+#-----------------------------------------------------------------------
+
+def devwrite(calldict, devdict, classidx):
+ ltext = ''
+
+ # Resolve network connections to ports and store as a dictionary
+ #...............................................................
+ portdict = {}
+ ports_from = calldict['ports']
+ ports_to = devdict['ports']
+ for i in range(0,len(ports_from)):
+ portdict[textprint(ports_to[i], params)] = textprint(ports_from[i], [])
+
+ # Resolve instanced vs. default parameters and store as a dictionary
+ # (only for use with the "%v" statement in info labels)
+ #...............................................................
+ paramdict = {}
+ try:
+ def_params = devdict['parameters']
+ except KeyError:
+ def_params = []
+
+ try:
+ params = calldict['parameters']
+ except KeyError:
+ params = []
+
+ params += def_params[len(params):]
+
+ for i in range(0,len(params)):
+ paramdict[textprint(def_params[i], [])] = textprint(params[i], [])
+
+ # For each "spice:" info label, parse the info label
+ #...............................................................
+ w = devdict['devices']
+ for y in w:
+ for u in y:
+ lstr = select(textprint(u, params), 'spice')
+ if lstr <> '':
+ ltext += parsedev(lstr, portdict, devdict, classidx, paramdict)
+ ltext += '\n'
+ return ltext
+
+#-----------------------------------------------------------------------
+# Check if a device is "fundamental"; that is, has a "devices" dictionary
+# with at least one entry with "spice:" for SPICE output.
+#-----------------------------------------------------------------------
+
+def isfundamental(devdict):
+ try:
+ w = devdict['devices']
+ except KeyError:
+ return 0
+ else:
+ for y in w:
+ for u in y:
+ lstr = select(textprint(u, []), 'spice')
+ if lstr <> '':
+ return 1
+ return 0
+
+#-----------------------------------------------------------------------
+# Select the device string corresponding to the given prefix.
+# Return the body of the string, or an empty string if the prefix
+# doesn't match.
+#-----------------------------------------------------------------------
+
+def select(sstr, prefix):
+ ltext = ''
+ if sstr.startswith(prefix):
+ ltext += sstr[len(prefix) + 1:]
+ return ltext
+
+#-----------------------------------------------------------------------
+# Generate an ASCII string from an xcircuit string (list). Translate
+# overlines to "!" and Greek "mu" (either from Symbol font or from the
+# ISO-Latin1 encoding of any standard font) to "u".
+# String parameter substitution is performed if "params" is a non-empty
+# list and the dictionary key "Parameter" is encountered in the string
+# list "slist".
+#-----------------------------------------------------------------------
+
+def textprint(slist, params):
+ ltext = ''
+ is_symbol = 0
+ is_iso = 0
+ for x in slist:
+ try:
+ f = x.keys()[0]
+ except AttributeError: # must be a string
+ if x == 'Return':
+ ltext += '\n'
+ elif x == 'Underline':
+ ltext += '_'
+ elif x == 'Overline':
+ ltext += '!'
+ else: # is a dictionary; will have only one key
+ if f == 'Font':
+ lfont = x[x.keys()[0]]
+ if lfont.startswith('Symbol'):
+ is_symbol = 1
+ else:
+ is_symbol = 0
+ if lfont.endswith('ISO'):
+ is_iso = 1
+ else:
+ is_iso = 0
+ elif f == 'Parameter':
+ try:
+ plist = params[x[x.keys()[0]]]
+ except IndexError:
+ ltext += ' --unknown parameter %d-- ' % x[x.keys()[0]]
+ else:
+ ltext += textprint(plist, [])
+ continue;
+ else: # text: SPICE translates "mu" to "u"
+ for y in x[x.keys()[0]]:
+ if is_symbol:
+ if y == 'f':
+ ltext += 'phi'
+ elif y == 'm':
+ ltext += 'u'
+ else:
+ ltext += y
+ else:
+ if ord(y) == 181:
+ ltext += 'u'
+ elif ord(y) > 127:
+ ltext += '/' + str(ord(y))
+ else:
+ ltext += y
+ return ltext
+
+#-----------------------------------------------------------------------
+# Write netlist to the output
+#-----------------------------------------------------------------------
+
+def writespice():
+ subidx=1 # subcircuit numbering
+ devdict={} # dictionary of low-level devices
+ classidx = {} # indices of SPICE devices (other than subcircuits)
+ p=netlist() # Generate the netlist
+ g=p['globals'] # Get the list of global networks
+ c=p['circuit'] # Get the list of (sub)circuits
+ l=len(c)
+ top=c[l-1] # Top-level circuit
+ topname=top['name'] # Name of the top-level circuit
+ topname += '.spc' # Filename to write to
+ try:
+ outfile=open(topname, 'w')
+ except IOError:
+ return
+
+ # Print header line
+ #...............................................................
+
+ outfile.write('*SPICE circuit "' + topname + '"')
+ outfile.write(' from XCircuit v' + str(xc_version))
+ outfile.write(' (Python script "spice.py")\n')
+
+ # Print global variables. This is for hspice and should be
+ # commented out for spice3.
+ #...............................................................
+
+ for x in g: # 'globals' is a list of strings
+ outfile.write('.GLOBAL ' + textprint(x, []) + '\n')
+ outfile.write('\n')
+
+ # Print the (sub)circuits. Top level circuit does not get a "subckt"
+ # entry.
+ #...............................................................
+
+ for x in c: # 'circuits' is a list of dictionaries
+ is_device = 0
+ try:
+ w = x['ports'] # write circuit name and ports, if any
+ except KeyError:
+ is_top = 1
+ else:
+ is_top = 0
+ if isfundamental(x) == 0:
+ outfile.write('.subckt ' + x['name'])
+ for y in w:
+ outfile.write(' ' + textprint(y, []))
+ outfile.write('\n')
+ else:
+ is_device = 1
+ devdict[x['name']] = x
+
+ try:
+ v = x['calls'] # calls to subcircuits in xcircuit
+ except KeyError:
+ pass
+ else:
+ for y in v:
+ try:
+ d = devdict[y['name']]
+ except KeyError: # A SPICE subcircuit instance
+ outfile.write('X' + str(subidx))
+ subidx+=1
+ for z in y['ports']:
+ outfile.write(' ' + textprint(z, []))
+ outfile.write(' ' + y['name'] + '\n')
+ else: # A SPICE circuit element
+ nstr = devwrite(y, d, classidx);
+ outfile.write(nstr)
+
+ if is_top:
+ outfile.write('.end\n')
+ elif is_device == 0:
+ outfile.write('.ends\n\n')
+
+#-----------------------------------------------------------------------
+# Key binding and menu button for the spice netlist output
+# bind('Alt_S', 'writespice')
+#-----------------------------------------------------------------------
+
+newbutton('Netlist', 'Write Spice', 'writespice')
+
+#-----------------------------------------------------------------------
diff --git a/lib/python/xcstartup.py b/lib/python/xcstartup.py
new file mode 100644
index 0000000..de9ed1b
--- /dev/null
+++ b/lib/python/xcstartup.py
@@ -0,0 +1,40 @@
+# XCircuit Python startup script (xcstartup.py)
+# Does the work previously handled by "builtins.lps". Commands
+# "loadlibrary" and "loadfontencoding" should no longer be used.
+#
+# Written by Tim Edwards 1/19/01 (tim@bach.ece.jhu.edu)
+# The Johns Hopkins University
+
+font("times_roman.xfe")
+font("times_romaniso.xfe")
+font("helvetica.xfe")
+font("helveticaiso.xfe")
+font("courier.xfe")
+font("courieriso.xfe")
+font("symbol.xfe")
+
+# Alternate font encodings: Uncomment these if you want them
+# loaded by default
+#
+# font("times_romaniso2.xfe")
+# font("courieriso2.xfe")
+# font("helveticaiso2.xfe")
+# font("times_romaniso5.xfe")
+# font("courieriso5.xfe")
+# font("helveticaiso5.xfe")
+
+# First library page
+library("generic.lps", 1)
+library("analog.lps", 1)
+library("avlsi.lps", 1)
+library("digital.lps", 1)
+
+# Second library page
+library ("analoglib2.lps", 2)
+
+# Third library page
+library ("ic_templates.lps", 3)
+
+# Fourth library page
+library ("quadparts.lps", 4)
+
diff --git a/lib/quadparts.lps b/lib/quadparts.lps
new file mode 100644
index 0000000..5d4562a
--- /dev/null
+++ b/lib/quadparts.lps
@@ -0,0 +1,89 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.6
+% Library name is: quadparts
+% Author: R. Timothy Edwards <tim@khachaturian.tim.linglan.net>
+%
+
+
+% XCircuitLib library objects
+/quadparts::quadnand {
+<</@vdd (VDD) /@gnd (GND) /@part (1) (lindex {1 2 3 4} 0) pop /@pinA (1)
+(lindex {0 1 4 9 12} @part) pop /@pinB (2) (lindex {0 2 5 10 13} @part) pop /@pinO
+(3) (lindex {0 3 6 8 11} @part) pop /@index (?) /@pkg (DIP14) >> begingate
+1 1.000 0 -48 -64 -48 -64 48 0 48 4 polygon
+1 1.000 56 0 8 0.000 360.000 xcarc
+1 1.000 0 0 48 -90.000 90.000 xcarc
+0.180 0.545 0.341 scb
+mark @vdd ( 14=) @gnd ( 7=) @index (pcb:U) {/Helvetica cf} ctmk 20 0 1.000 -80
+-96 infolabel
+sce
+mark @part (7400-) {/Helvetica cf} ctmk 21 0 0.500 0 0 label
+1.000 0.000 0.000 scb
+mark @pinO {/Times-Roman cf} ctmk 4 0 1.000 64 0 pinlabel
+mark @pinA {/Times-Roman cf} ctmk 7 0 1.000 -64 32 pinlabel
+mark @pinB {/Times-Roman cf} ctmk 7 0 1.000 -64 -32 pinlabel
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-Roman cf} ctmk 16 0 0.700 -64 64 label
+endgate
+} def
+
+<</@part (2) (lindex {1 2 3 4} 1) pop >> /quadparts::quadnand libinst
+<</@part (3) (lindex {1 2 3 4} 2) pop >> /quadparts::quadnand libinst
+<</@part (4) (lindex {1 2 3 4} 3) pop >> /quadparts::quadnand libinst
+
+/quadparts::quadnor {
+<</@vdd (VDD) /@gnd (GND) /@part (1) (lindex {1 2 3 4} 0) pop /@pinA (1)
+(lindex {0 1 4 10 13} @part) pop /@pinB (2) (lindex {0 2 5 8 11} @part) pop /@pinO
+(3) (lindex {0 3 6 9 12} @part) pop /@index (?) /@pkg (DIP14) >> begingate
+1 1.000 -64 48 -35 48 2 polygon
+1 1.000 -64 -48 -35 -48 2 polygon
+1 1.000 -128 0 80 -37.000 37.000 xcarc
+1 1.000 56 0 8 0.000 360.000 xcarc
+1 1.000 -35 -48 96 30.000 90.000 xcarc
+1 1.000 -35 48 96 270.000 330.000 xcarc
+0.180 0.545 0.341 scb
+mark @vdd ( 14=) @gnd ( 7=) @index (pcb:U) {/Helvetica cf} ctmk 20 0 1.000 -64
+-96 infolabel
+sce
+mark @part (7402-) {/Helvetica cf} ctmk 21 0 0.500 0 0 label
+1.000 0.000 0.000 scb
+mark @pinO {/Times-Roman cf} ctmk 4 0 1.000 64 0 pinlabel
+mark @pinA {/Times-Roman cf} ctmk 7 0 1.000 -56 32 pinlabel
+mark @pinB {/Times-Roman cf} ctmk 7 0 1.000 -56 -32 pinlabel
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-Roman cf} ctmk 16 0 0.700 -64 64 label
+endgate
+} def
+
+<</@part (2) (lindex {1 2 3 4} 1) pop >> /quadparts::quadnor libinst
+<</@part (3) (lindex {1 2 3 4} 2) pop >> /quadparts::quadnor libinst
+<</@part (4) (lindex {1 2 3 4} 3) pop >> /quadparts::quadnor libinst
+
+/quadparts::quador {
+<</@vdd (VDD) /@gnd (GND) /@part (1) (lindex {1 2 3 4} 0) pop /@pinA (1)
+(lindex {0 1 4 9 12} @part) pop /@pinB (2) (lindex {0 2 5 10 13} @part) pop /@pinO
+(3) (lindex {0 3 6 8 11} @part) pop /@index (?) /@pkg (DIP14) >> begingate
+1 1.000 -19 -48 96 30.000 90.000 xcarc
+1 1.000 -19 48 96 270.000 330.000 xcarc
+1 1.000 -112 0 80 -37.000 37.000 xcarc
+1 1.000 -48 48 -19 48 2 polygon
+1 1.000 -48 -48 -19 -48 2 polygon
+0.180 0.545 0.341 scb
+mark @vdd ( 14=) @gnd ( 7=) @index (pcb:U) {/Helvetica cf} ctmk 20 0 1.000 -64
+-96 infolabel
+sce
+mark @part (7432-) {/Helvetica cf} ctmk 21 0 0.500 16 0 label
+1.000 0.000 0.000 scb
+mark @pinO {/Times-Roman cf} ctmk 4 0 1.000 64 0 pinlabel
+mark @pinA {/Times-Roman cf} ctmk 7 0 1.000 -40 32 pinlabel
+mark @pinB {/Times-Roman cf} ctmk 7 0 1.000 -40 -32 pinlabel
+0.000 0.000 1.000 scb
+mark @index (U) {/Times-Roman cf} ctmk 16 0 0.700 -48 64 label
+endgate
+} def
+
+<</@part (2) (lindex {1 2 3 4} 1) pop >> /quadparts::quador libinst
+<</@part (3) (lindex {1 2 3 4} 2) pop >> /quadparts::quador libinst
+<</@part (4) (lindex {1 2 3 4} 3) pop >> /quadparts::quador libinst
+
+% EndLib
diff --git a/lib/series74xx.lps b/lib/series74xx.lps
new file mode 100644
index 0000000..5aeab9f
--- /dev/null
+++ b/lib/series74xx.lps
@@ -0,0 +1,8663 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: series74xx
+% Author: R. Timothy Edwards <tim@stravinsky.jhuapl.edu>
+%
+
+
+% XCircuitLib library objects
+/Template8 {
+% hidden
+<</pin1 (1) /pin2 (2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8
+(8) /pin9 (9) /pin10 (10) /pin11 (11) /pin12 (12) /pin13 (13) /pin14 (14) /@index
+(?) /gate (74xx) /title (title) /pkg (DIP8) >> begingate
+0 1.00 -224 176 -224 464 224 464 224 176 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 336 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 384 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 496 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin5 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin6 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin7 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin8 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 256 label
+endgate
+} def
+
+/Template14 {
+% hidden
+<</pkg (DIP14) /title (title) /gate (74xx) /@index (?) /pin14 (14) /pin13
+(13) /pin12 (12) /pin11 (11) /pin10 (10) /pin9 (9) /pin8 (8) /pin7 (7) /pin6
+(6) /pin5 (5) /pin4 (4) /pin3 (3) /pin2 (2) /pin1 (1) >> begingate
+0 1.00 -224 0 -224 448 224 448 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 272 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 320 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 464 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin8 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin9 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin10 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+endgate
+} def
+
+/Template16 {
+% hidden
+<</pkg (DIP16) /title (title) /gate (74xx) /@index (?) /pin14 (14) /pin13
+(13) /pin12 (12) /pin11 (11) /pin10 (10) /pin9 (9) /pin8 (8) /pin7 (7) /pin6
+(6) /pin5 (5) /pin4 (4) /pin3 (3) /pin2 (2) /pin1 (1) /pin15 (15) /pin16 (16) >>
+begingate
+0 1.00 -224 0 -224 512 224 512 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 272 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 320 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 544 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin9 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin10 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+endgate
+} def
+
+/Template20 {
+% hidden
+<</pin1 (1) /pin2 (2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8
+(8) /pin9 (9) /pin10 (10) /pin11 (11) /pin12 (12) /pin13 (13) /pin14 (14) /@index
+(?) /gate (74xx) /title (title) /pkg (DIP20) /pin15 (15) /pin16 (16) /pin17
+(17) /pin18 (18) /pin19 (19) /pin20 (20) >> begingate
+0 1.00 -224 0 -224 640 224 640 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 400 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 448 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 656 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin11 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin12 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+endgate
+} def
+
+/Template24 {
+% hidden
+<</pkg (DIP24) /title (title) /gate (74xx) /@index (?) /pin14 (14) /pin13
+(13) /pin12 (12) /pin11 (11) /pin10 (10) /pin9 (9) /pin8 (8) /pin7 (7) /pin6
+(6) /pin5 (5) /pin4 (4) /pin3 (3) /pin2 (2) /pin1 (1) /pin15 (15) /pin16 (16) /pin17
+(17) /pin18 (18) /pin19 (19) /pin20 (20) /pin21 (21) /pin22 (22) /pin23
+(23) /pin24 (24) >> begingate
+0 1.00 -224 0 -224 768 224 768 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 528 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 576 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 784 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 736 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 672 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin11 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin12 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin13 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin14 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin21 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin22 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark pin23 {/Helvetica cf} ctmk 23 0 1.00 208 672 label
+mark pin24 {/Helvetica cf} ctmk 23 0 1.00 208 736 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+endgate
+} def
+
+/Template28 {
+% hidden
+<</pin1 (1) /pin2 (2) /pin3 (3) /pin4 (4) /pin5 (5) /pin6 (6) /pin7 (7) /pin8
+(8) /pin9 (9) /pin10 (10) /pin11 (11) /pin12 (12) /pin13 (13) /pin14 (14) /@index
+(?) /gate (74xx) /title (title) /pkg (DIP28) /pin15 (15) /pin16 (16) /pin17
+(17) /pin18 (18) /pin19 (19) /pin20 (20) /pin21 (21) /pin22 (22) /pin23
+(23) /pin24 (24) /pin25 (25) /pin26 (26) /pin27 (27) /pin28 (28) >> begingate
+0 1.00 -224 0 -224 896 224 896 224 0 4 polygon
+mark title {/Helvetica-Bold cf} ctmk 29 0 1.00 0 592 label
+mark gate {/Helvetica-Bold cf} ctmk 21 0 1.00 0 640 label
+mark @index (U) {/Helvetica cf} ctmk 17 0 1.00 0 912 label
+mark pin1 {/Helvetica cf} ctmk 20 0 1.00 -208 864 label
+mark pin2 {/Helvetica cf} ctmk 20 0 1.00 -208 800 label
+mark pin3 {/Helvetica cf} ctmk 20 0 1.00 -208 736 label
+mark pin4 {/Helvetica cf} ctmk 20 0 1.00 -208 672 label
+mark pin5 {/Helvetica cf} ctmk 20 0 1.00 -208 608 label
+mark pin6 {/Helvetica cf} ctmk 20 0 1.00 -208 544 label
+mark pin7 {/Helvetica cf} ctmk 20 0 1.00 -208 480 label
+mark pin8 {/Helvetica cf} ctmk 20 0 1.00 -208 416 label
+mark pin9 {/Helvetica cf} ctmk 20 0 1.00 -208 352 label
+mark pin10 {/Helvetica cf} ctmk 20 0 1.00 -208 288 label
+mark pin11 {/Helvetica cf} ctmk 20 0 1.00 -208 224 label
+mark pin12 {/Helvetica cf} ctmk 20 0 1.00 -208 160 label
+mark pin13 {/Helvetica cf} ctmk 20 0 1.00 -208 96 label
+mark pin14 {/Helvetica cf} ctmk 20 0 1.00 -208 32 label
+mark pin15 {/Helvetica cf} ctmk 23 0 1.00 208 32 label
+mark pin16 {/Helvetica cf} ctmk 23 0 1.00 208 96 label
+mark pin17 {/Helvetica cf} ctmk 23 0 1.00 208 160 label
+mark pin18 {/Helvetica cf} ctmk 23 0 1.00 208 224 label
+mark pin19 {/Helvetica cf} ctmk 23 0 1.00 208 288 label
+mark pin20 {/Helvetica cf} ctmk 23 0 1.00 208 352 label
+mark pin21 {/Helvetica cf} ctmk 23 0 1.00 208 416 label
+mark pin22 {/Helvetica cf} ctmk 23 0 1.00 208 480 label
+mark pin23 {/Helvetica cf} ctmk 23 0 1.00 208 544 label
+mark pin24 {/Helvetica cf} ctmk 23 0 1.00 208 608 label
+mark pin25 {/Helvetica cf} ctmk 23 0 1.00 208 672 label
+mark pin26 {/Helvetica cf} ctmk 23 0 1.00 208 736 label
+mark pin27 {/Helvetica cf} ctmk 23 0 1.00 208 800 label
+mark pin28 {/Helvetica cf} ctmk 23 0 1.00 208 864 label
+mark (\)) pkg (\() {/Helvetica cf} ctmk 21 0 1.00 0 64 label
+endgate
+} def
+
+
+
+% Depend dil_7400 Template14
+
+/dil_7400 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7400) /title {(4 dual-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3B) /pin10 (3A) /pin11 (4Y) /pin12 (4B) /pin13 (4A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7401 Template14
+
+/dil_7401 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7401) /title {(OC) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7402 Template14
+
+/dil_7402 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7402) /title {(4 dual-NOR)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7403 Template14
+
+/dil_7403 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7403) /title {(OC) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7404 Template14
+
+/dil_7404 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7404) /title {(6 inverters)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7405 Template14
+
+/dil_7405 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7405) /title {(OC) {CR} (6 inverters)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7406 Template14
+
+/dil_7406 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7406) /title {(voltage) {CR} (OC high-) {CR} (6 inverters)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7407 Template14
+
+/dil_7407 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7407) /title {(6 buffers OC)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7408 Template14
+
+/dil_7408 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7408) /title {(4 dual-AND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7409 Template14
+
+/dil_7409 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7409) /title {(OC) {CR} (4 dual-AND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7410 Template14
+
+/dil_7410 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7410) /title {(NAND) {CR} (3 triple-)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A2) /pin4 (B2) /pin5 (C2) /pin6 (Y2) /pin7 (Gnd) /pin8 (Y3) /pin9 (A3) /pin10 (B3) /pin11 (C3) /pin12 (Y1) /pin13 (C1) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7411 Template14
+
+/dil_7411 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7411) /title {(3 triple-AND)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A2) /pin4 (B2) /pin5 (C2) /pin6 (Y2) /pin7 (Gnd) /pin8 (Y3) /pin9 (A3) /pin10 (B3) /pin11 (C3) /pin12 (Y1) /pin13 (C1) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7412 Template14
+
+/dil_7412 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7412) /title {(NAND OC) {CR} (3 triple-)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A2) /pin4 (B2) /pin5 (C2) /pin6 (Y2) /pin7 (Gnd) /pin8 (Y3) /pin9 (A3) /pin10 (B3) /pin11 (C3) /pin12 (Y1) /pin13 (C1) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7413 Template14
+
+/dil_7413 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7413) /title {(trigger) {CR} (Schmitt) {CR} (NAND) {CR} (2 quad-input)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7414 Template14
+
+/dil_7414 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7414) /title {(inverter) {CR} (trigger) {CR} (6 Schmitt)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7415 Template14
+
+/dil_7415 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7415) /title {(OC) {CR} (3 triple-AND)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A2) /pin4 (B2) /pin5 (C2) /pin6 (Y2) /pin7 (Gnd) /pin8 (Y3) /pin9 (A3) /pin10 (B3) /pin11 (C3) /pin12 (Y1) /pin13 (C1) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7416 Template14
+
+/dil_7416 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7416) /title {(voltage) {CR} (OC high-) {CR} (6 inverters)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7418 Template14
+
+/dil_7418 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7418) /title {(trigger) {CR} (Schmitt) {CR} (2 quad-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7419 Template14
+
+/dil_7419 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7419) /title {(trigger) {CR} (Schmitt) {CR} (6 inverter)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3Y) /pin7 (Gnd) /pin8 (4Y) /pin9 (4A) /pin10 (5Y) /pin11 (5A) /pin12 (6Y) /pin13 (6A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7420 Template14
+
+/dil_7420 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7420) /title {(2 quad-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7421 Template14
+
+/dil_7421 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7421) /title {(2 quad-AND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7422 Template14
+
+/dil_7422 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7422) /title {(OC) {CR} (2 quad-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7423 Template16
+
+/dil_7423 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7423) /title {(with strobe) {CR} (2 quad-NOR)} /@index @index /pkg pkg /pin1 (1X) /pin2 (1A) /pin3 (1B) /pin4 (1G) /pin5 (1C) /pin6 (1D) /pin7 (1Y) /pin8 (Gnd) /pin9 (2Y) /pin10 (2A) /pin11 (2B) /pin12 (2G) /pin13 (2C) /pin14 (2D) /pin15 {(X) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7424 Template14
+
+/dil_7424 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7424) /title {(trigger) {CR} (Schmitt) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7425 Template14
+
+/dil_7425 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7425) /title {(w. strobe) {CR} (2 quad-NOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1G) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (2G) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7426 Template14
+
+/dil_7426 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7426) /title {(voltage) {CR} (high-) {CR} (4 dual NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7427 Template14
+
+/dil_7427 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7427) /title {(3 triple-NOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (2A) /pin4 (2B) /pin5 (2C) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (3C) /pin12 (1Y) /pin13 (1C) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7428 Template14
+
+/dil_7428 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7428) /title {(buffer) {CR} (4 dual-NOR)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7430 Template14
+
+/dil_7430 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7430) /title (octal-NAND) /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 (D) /pin5 (E) /pin6 (F) /pin7 (Gnd) /pin8 (Y) /pin9 (NC) /pin10 (NC) /pin11 (G) /pin12 (H) /pin13 (NC) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7431 Template16
+
+/dil_7431 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7431) /title {(elements) {CR} (delay)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1Y) /pin3 (2A) /pin4 (2Y) /pin5 (3A) /pin6 (3B) /pin7 (3Y) /pin8 (Gnd) /pin9 (4Y) /pin10 (4A) /pin11 (4B) /pin12 (5Y) /pin13 (5A) /pin14 (6Y) /pin15 (6A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7432 Template14
+
+/dil_7432 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7432) /title {(4 dual-OR)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (Y1) /pin4 (A2) /pin5 (B2) /pin6 (Y2) /pin7 (Gnd) /pin8 (Y3) /pin9 (A3) /pin10 (B3) /pin11 (Y4) /pin12 (A4) /pin13 (B4) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7433 Template14
+
+/dil_7433 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7433) /title {(buffer OC) {CR} (4 dual-NOR)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7437 Template14
+
+/dil_7437 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7437) /title {(buffer) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7438 Template14
+
+/dil_7438 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7438) /title {(buffer OC) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7439 Template14
+
+/dil_7439 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7439) /title {(buffer OC) {CR} (4 dual-NAND)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7440 Template14
+
+/dil_7440 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7440) /title {(buffer) {CR} (2 quad-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7442 Template16
+
+/dil_7442 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7442) /title {(decoder) {CR} (4-to-10)} /@index @index /pkg pkg /pin1 (0) /pin2 (1) /pin3 (2) /pin4 (3) /pin5 (4) /pin6 (5) /pin7 (6) /pin8 (Gnd) /pin9 (7) /pin10 (8) /pin11 (9) /pin12 (D) /pin13 (C) /pin14 (B) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7445 Template16
+
+/dil_7445 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7445) /title {(driver) {CR} (decoder/) {CR} (decimal) {CR} (BCD to)} /@index @index /pkg pkg /pin1 (0) /pin2 (1) /pin3 (2) /pin4 (3) /pin5 (4) /pin6 (5) /pin7 (6) /pin8 (Gnd) /pin9 (7) /pin10 (8) /pin11 (9) /pin12 (D) /pin13 (C) /pin14 (B) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7446 Template16
+
+/dil_7446 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7446) /title {(driver OC) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(LT) {ol}} /pin4 {(RBO) {ol} (BI-) {ol}} /pin5 {(RBI) {ol}} /pin6 (D) /pin7 (A) /pin8 (Gnd) /pin9 (e) /pin10 (d) /pin11 (c) /pin12 (b) /pin13 (a) /pin14 (g) /pin15 (f) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7447 Template16
+
+/dil_7447 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7447) /title {(driver OC) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(LT) {ol}} /pin4 {(RBO) {ol} (BI-) {ol}} /pin5 {(RBI) {ol}} /pin6 (D) /pin7 (A) /pin8 (Gnd) /pin9 (e) /pin10 (d) /pin11 (c) /pin12 (b) /pin13 (a) /pin14 (g) /pin15 (f) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7448 Template16
+
+/dil_7448 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7448) /title {(pullup) {CR} (driver w.) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(LT) {ol}} /pin4 {(RBO) {ol} (BI-) {ol}} /pin5 {(RBI) {ol}} /pin6 (D) /pin7 (A) /pin8 (Gnd) /pin9 (e) /pin10 (d) /pin11 (c) /pin12 (b) /pin13 (a) /pin14 (g) /pin15 (f) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7449 Template14
+
+/dil_7449 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7449) /title {(input) {CR} (w. blanking) {CR} (driver OC) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(BI) {ol}} /pin4 (D) /pin5 (A) /pin6 (e) /pin7 (Gnd) /pin8 (d) /pin9 (c) /pin10 (b) /pin11 (a) /pin12 (g) /pin13 (f) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7450 Template14
+
+/dil_7450 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7450) /title {(inputs\)) {CR} (\(2x2) {CR} (inverters) {CR} (2 AND-OR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (2A) /pin3 (2B) /pin4 (2C) /pin5 (2D) /pin6 (2Y) /pin7 (Gnd) /pin8 (1Y) /pin9 (1C) /pin10 (1D) /pin11 (1X) /pin12 (1/X) /pin13 (1B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7451L Template14
+
+/dil_7451L {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7451L) /title {(inputs\)) {CR} (\(2x2,2x3) {CR} (inverters) {CR} (2 AND-OR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (2A) /pin3 (2B) /pin4 (2C) /pin5 (2D) /pin6 (2Y) /pin7 (Gnd) /pin8 (1Y) /pin9 (1D) /pin10 (1E) /pin11 (1F) /pin12 (1B) /pin13 (1C) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7451S Template14
+
+/dil_7451S {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7451S) /title {(inputs\)) {CR} (\(2x2) {CR} (inverters) {CR} (2 AND-OR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (2A) /pin3 (2B) /pin4 (2C) /pin5 (2D) /pin6 (2Y) /pin7 (Gnd) /pin8 (1Y) /pin9 (1C) /pin10 (1D) /pin11 (NC) /pin12 (NC) /pin13 (1B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7453 Template14
+
+/dil_7453 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7453) /title {(inputs\)) {CR} (\(4x2) {CR} (inverter) {CR} (AND-OR)} /@index @index /pkg pkg /pin1 (A) /pin2 (C) /pin3 (D) /pin4 (E) /pin5 (F) /pin6 (NC) /pin7 (Gnd) /pin8 (Y) /pin9 (G) /pin10 (H) /pin11 (X) /pin12 {(X) {ol}} /pin13 (B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7454 Template14
+
+/dil_7454 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7454) /title {(inputs\)) {CR} (\(4x2) {CR} (inverter) {CR} (AND-OR)} /@index @index /pkg pkg /pin1 (A) /pin2 (C) /pin3 (D) /pin4 (E) /pin5 (F) /pin6 (NC) /pin7 (Gnd) /pin8 (Y) /pin9 (G) /pin10 (H) /pin11 (NC) /pin12 (NC) /pin13 (B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7455 Template14
+
+/dil_7455 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7455) /title {(inputs\)) {CR} (\(2x4) {CR} (inverter) {CR} (AND-OR)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 (D) /pin5 (NC) /pin6 (NC) /pin7 (Gnd) /pin8 (Y) /pin9 (NC) /pin10 (E) /pin11 (F) /pin12 (G) /pin13 (H) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7457 Template8
+
+/dil_7457 {
+<</@index (?) /pkg (DIP) >> begingate
+1.00 0 0 -240 << /gate (7457) /title {(divider) {CR} (frequency)} /@index @index /pkg pkg /pin1 (ClkB) /pin2 (Vcc) /pin3 (Qa) /pin4 (Gnd) /pin5 (ClkA) /pin6 (Clr) /pin7 (Qb) /pin8 (Qc) >> Template8
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(6) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(7) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 128 infolabel
+sce
+endgate
+} def
+
+
+% Depend dil_7464 Template14
+
+/dil_7464 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7464) /title {(inputs\)) {CR} (\(4-2-3-2) {CR} (inverter) {CR} (AND-OR)} /@index @index /pkg pkg /pin1 (A) /pin2 (E) /pin3 (F) /pin4 (G) /pin5 (H) /pin6 (I) /pin7 (Gnd) /pin8 (Y) /pin9 (J) /pin10 (K) /pin11 (B) /pin12 (C) /pin13 (D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7465 Template14
+
+/dil_7465 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7465) /title {(inputs\)) {CR} (\(4-2-3-2) {CR} (inverter OC) {CR} (AND-OR)} /@index @index /pkg pkg /pin1 (A) /pin2 (E) /pin3 (F) /pin4 (G) /pin5 (H) /pin6 (I) /pin7 (Gnd) /pin8 (Y) /pin9 (J) /pin10 (K) /pin11 (B) /pin12 (C) /pin13 (D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7468 Template16
+
+/dil_7468 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7468) /title {(counter) {CR} (decade) {CR} (2 4bit)} /@index @index /pkg pkg /pin1 (1ClkA) /pin2 (1Qb) /pin3 (1Qd) /pin4 {(1Clr) {ol}} /pin5 (2Qc) /pin6 (NC) /pin7 (2Qa) /pin8 (Gnd) /pin9 (2Clk) /pin10 (2Qb) /pin11 {(2Clr) {ol}} /pin12 (2Qd) /pin13 (1Qc) /pin14 (1Qa) /pin15 (1ClkB) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7469 Template16
+
+/dil_7469 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7469) /title {(counter) {CR} (binary) {CR} (2 4bit)} /@index @index /pkg pkg /pin1 (1ClkA) /pin2 (1Qb) /pin3 (1Qd) /pin4 {(1Clr) {ol}} /pin5 (2Qc) /pin6 (NC) /pin7 (2Qa) /pin8 (Gnd) /pin9 (2Clk) /pin10 (2Qb) /pin11 {(2Clr) {ol}} /pin12 (2Qd) /pin13 (1Qc) /pin14 (1Qa) /pin15 (1ClkB) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7470 Template14
+
+/dil_7470 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7470) /title {(clear) {CR} (w. preset/) {CR} (pos-edge-FF) {CR} (AND-gated JK)} /@index @index /pkg pkg /pin1 (NC) /pin2 {(Clr) {ol}} /pin3 (J1) /pin4 (J2) /pin5 {(J) {ol}} /pin6 {(Q) {ol}} /pin7 (Gnd) /pin8 (Q) /pin9 {(K) {ol}} /pin10 (K1) /pin11 (K2) /pin12 (Clk) /pin13 {(Pre) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7472 Template14
+
+/dil_7472 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7472) /title {(clear) {CR} (preset/) {CR} (FF w.) {CR} (AND-gated MS-)} /@index @index /pkg pkg /pin1 (NC) /pin2 {(Clr) {ol}} /pin3 (J1) /pin4 (J2) /pin5 (J3) /pin6 {(Q) {ol}} /pin7 (Gnd) /pin8 (Q) /pin9 (K1) /pin10 (K2) /pin11 (K3) /pin12 (Clk) /pin13 {(Pre) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7473 Template14
+
+/dil_7473 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7473) /title {(clear) {CR} (2 JK FF w.)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 {(1Clr) {ol}} /pin3 (1K) /pin4 (Vcc) /pin5 (2Clk) /pin6 {(2Clr) {ol}} /pin7 (2J) /pin8 {(2Q) {ol}} /pin9 (2Q) /pin10 (2K) /pin11 (Gnd) /pin12 (1Q) /pin13 {(1Q) {ol}} /pin14 (1J) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7474 Template14
+
+/dil_7474 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7474) /title {(clear) {CR} (preset/) {CR} (edge FF w.) {CR} (2 D-type pos-)} /@index @index /pkg pkg /pin1 {(1Clr) {ol}} /pin2 (1D) /pin3 (1Clk) /pin4 {(1Pre) {ol}} /pin5 (1Q) /pin6 {(1Q) {ol}} /pin7 (Gnd) /pin8 {(2Q) {ol}} /pin9 (2Q) /pin10 {(2Pre) {ol}} /pin11 (2Clk) /pin12 (2D) /pin13 {(2Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7475 Template16
+
+/dil_7475 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7475) /title {(outputs) {CR} (compl.) {CR} (latch w.) {CR} (stable) {CR} (4bit bi-)} /@index @index /pkg pkg /pin1 {(1Q) {ol}} /pin2 (1D) /pin3 (2D) /pin4 (3C-4C) /pin5 (Vcc) /pin6 (3D) /pin7 (4D) /pin8 {(4Q) {ol}} /pin9 (4Q) /pin10 (3Q) /pin11 {(3Q) {ol}} /pin12 (Gnd) /pin13 (1C-2C) /pin14 {(2Q) {ol}} /pin15 (2Q) /pin16 (1Q) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7476 Template16
+
+/dil_7476 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7476) /title {(clear) {CR} (preset/) {CR} (2 JK FF w.)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 {(1Pre) {ol}} /pin3 {(1Clr) {ol}} /pin4 (1J) /pin5 (Vcc) /pin6 (2Clk) /pin7 {(2Pre) {ol}} /pin8 {(2Clr) {ol}} /pin9 (2J) /pin10 {(2Q) {ol}} /pin11 (2Q) /pin12 (2K) /pin13 (Gnd) /pin14 {(1Q) {ol}} /pin15 (1Q) /pin16 (1K) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7478 Template14
+
+/dil_7478 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7478) /title {(Clr) {CR} (common Clk/) {CR} (preset and) {CR} (2 JK FF w.)} /@index @index /pkg pkg /pin1 (Clk) /pin2 {(1Pre) {ol}} /pin3 (1J) /pin4 (Vcc) /pin5 {(Clr) {ol}} /pin6 {(2Pre) {ol}} /pin7 (2K) /pin8 (2Q) /pin9 {(2Q) {ol}} /pin10 (2J) /pin11 (Gnd) /pin12 {(1Q) {ol}} /pin13 (1Q) /pin14 (1K) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7483 Template16
+
+/dil_7483 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7483) /title {(fast carry) {CR} (adder w.) {CR} (4bit binary)} /@index @index /pkg pkg /pin1 (A4) /pin2 (Sum3) /pin3 (A3) /pin4 (B3) /pin5 (Vcc) /pin6 (Sum2) /pin7 (B2) /pin8 (A2) /pin9 (Sum1) /pin10 (A1) /pin11 (B1) /pin12 (Gnd) /pin13 (C0) /pin14 (C4) /pin15 (Sum4) /pin16 (B4) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7485 Template16
+
+/dil_7485 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7485) /title {(comperator) {CR} (magnitude) {CR} (4bit)} /@index @index /pkg pkg /pin1 (B3) /pin2 {(A\<Bin)} /pin3 (A=Bin) /pin4 {(A\>Bin)} /pin5 {(A\>Bout)} /pin6 (A=Bout) /pin7 {(A\<Bout)} /pin8 (Gnd) /pin9 (B0) /pin10 (A0) /pin11 (B1) /pin12 (A1) /pin13 (A2) /pin14 (B2) /pin15 (A3) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7486 Template14
+
+/dil_7486 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7486) /title {(4 dual-XOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7490 Template14
+
+/dil_7490 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7490) /title {(to-9) {CR} (clear/set-) {CR} (counter w.) {CR} (decade)} /@index @index /pkg pkg /pin1 (ClkB) /pin2 {(R0\(1\))} /pin3 {(R0\(2\))} /pin4 (NC) /pin5 (Vcc) /pin6 {(R9\(1\))} /pin7 {(R9\(2\))} /pin8 (Qc) /pin9 (Qb) /pin10 (Gnd) /pin11 (Qd) /pin12 (Qa) /pin13 (NC) /pin14 (ClkA) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7491 Template14
+
+/dil_7491 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7491) /title {(register) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (NC) /pin2 (NC) /pin3 (NC) /pin4 (NC) /pin5 (Vcc) /pin6 (NC) /pin7 (NC) /pin8 (NC) /pin9 (Clk) /pin10 (Gnd) /pin11 (B) /pin12 (A) /pin13 (Q) /pin14 {(Q) {ol}} >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7492 Template14
+
+/dil_7492 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7492) /title {(clear) {CR} (counter w.) {CR} (divide by 12)} /@index @index /pkg pkg /pin1 (ClkB) /pin2 (NC) /pin3 (NC) /pin4 (NC) /pin5 (Vcc) /pin6 {(R0\(1\))} /pin7 {(R0\(2\))} /pin8 (Qd) /pin9 (Qc) /pin10 (Gnd) /pin11 (Qb) /pin12 (Qa) /pin13 (NC) /pin14 (ClkA) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7493 Template14
+
+/dil_7493 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7493) /title {(clear) {CR} (counter w.) {CR} (4bit binary)} /@index @index /pkg pkg /pin1 (ClkB) /pin2 {(R0\(1\))} /pin3 {(R0\(2\))} /pin4 (NC) /pin5 (Vcc) /pin6 (NC) /pin7 (NC) /pin8 (Qc) /pin9 (Qb) /pin10 (Gnd) /pin11 (Qd) /pin12 (Qa) /pin13 (NC) /pin14 (ClkA) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7495 Template14
+
+/dil_7495 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (7495) /title {(register) {CR} (shift) {CR} (access) {CR} (parallel-) {CR} (4bit)} /@index @index /pkg pkg /pin1 (Ser) /pin2 (A) /pin3 (B) /pin4 (C) /pin5 (D) /pin6 (Mode) /pin7 (Gnd) /pin8 (Clk2) /pin9 (Clk1) /pin10 (Qd) /pin11 (Qc) /pin12 (Qb) /pin13 (Qa) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_7496 Template16
+
+/dil_7496 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7496) /title {(register) {CR} (5bit shift)} /@index @index /pkg pkg /pin1 (Clk) /pin2 (A) /pin3 (B) /pin4 (C) /pin5 (Vcc) /pin6 (D) /pin7 (E) /pin8 (Pre) /pin9 (Ser) /pin10 (Qe) /pin11 (Qd) /pin12 (Gnd) /pin13 (Qc) /pin14 (Qb) /pin15 (Qa) /pin16 {(Clr) {ol}} >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_7497 Template16
+
+/dil_7497 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (7497) /title {(multiplier) {CR} (rate) {CR} (6bit binary) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (B1) /pin2 (B4) /pin3 (B5) /pin4 (B0) /pin5 (Z) /pin6 (Y) /pin7 (ENout) /pin8 (Gnd) /pin9 (Clk) /pin10 (StrB) /pin11 (ENin) /pin12 (Unity/CAS) /pin13 (Clr) /pin14 (B2) /pin15 (B3) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74107 Template14
+
+/dil_74107 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74107) /title {(clear) {CR} (2 JK FF w.)} /@index @index /pkg pkg /pin1 (1J) /pin2 {(1Q) {ol}} /pin3 (1Q) /pin4 (1K) /pin5 (2Q) /pin6 {(2Q) {ol}} /pin7 (Gnd) /pin8 (2J) /pin9 (2Clk) /pin10 {(2Clr) {ol}} /pin11 (2K) /pin12 (1Clk) /pin13 {(1Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74109 Template16
+
+/dil_74109 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74109) /title {(clear) {CR} (preset/) {CR} (edge FF w.) {CR} (K pos-) {ol} (2 J-)} /@index @index /pkg pkg /pin1 {(1Clr) {ol}} /pin2 (1J) /pin3 {(1K) {ol}} /pin4 (1Clk) /pin5 {(1Pre) {ol}} /pin6 (1Q) /pin7 {(1Q) {ol}} /pin8 (Gnd) /pin9 {(2Q) {ol}} /pin10 (2Q) /pin11 {(2Pre) {ol}} /pin12 (2Clk) /pin13 {(2K) {ol}} /pin14 (2J) /pin15 {(2Clr) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74111 Template16
+
+/dil_74111 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74111) /title {(lockout) {CR} (w. data) {CR} (2 JK-MS FF)} /@index @index /pkg pkg /pin1 (1K) /pin2 {(1Pre) {ol}} /pin3 {(1Clr) {ol}} /pin4 (1J) /pin5 (1Clk) /pin6 {(1Q) {ol}} /pin7 (1Q) /pin8 (Gnd) /pin9 (2Q) /pin10 {(2Q) {ol}} /pin11 (2Clk) /pin12 (2J) /pin13 {(2Clr) {ol}} /pin14 {(2Pre) {ol}} /pin15 (2K) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74112 Template16
+
+/dil_74112 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74112) /title {(clear) {CR} (w. preset/) {CR} (2 JK edge FF)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 (1K) /pin3 (1J) /pin4 {(1Pre) {ol}} /pin5 (1Q) /pin6 {(1Q) {ol}} /pin7 {(2Q) {ol}} /pin8 (Gnd) /pin9 (2Q) /pin10 {(2Pre) {ol}} /pin11 (2J) /pin12 (2K) /pin13 (2Clk) /pin14 {(2Clr) {ol}} /pin15 {(1Clr) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74113 Template14
+
+/dil_74113 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74113) /title {(w. preset) {CR} (2 JK edge FF)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 (1K) /pin3 (1J) /pin4 {(1Pre) {ol}} /pin5 (1Q) /pin6 {(1Q) {ol}} /pin7 (Gnd) /pin8 {(2Q) {ol}} /pin9 (2Q) /pin10 {(2Pre) {ol}} /pin11 (2J) /pin12 (2K) /pin13 (2Clk) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74114 Template14
+
+/dil_74114 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74114) /title {(Clr/Clk) {CR} (and common) {CR} (w. preset) {CR} (2 JK edge FF)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1K) /pin3 (1J) /pin4 {(1Pre) {ol}} /pin5 (1Q) /pin6 {(1Q) {ol}} /pin7 (Gnd) /pin8 {(2Q) {ol}} /pin9 (2Q) /pin10 {(2Pre) {ol}} /pin11 (2J) /pin12 (2K) /pin13 (Clk) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74116 Template24
+
+/dil_74116 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74116) /title {(clear) {CR} (lacthes w.) {CR} (2 4bit)} /@index @index /pkg pkg /pin1 {(1Clr) {ol}} /pin2 {(1C1) {ol}} /pin3 {(1C2) {ol}} /pin4 (1D1) /pin5 (1Q1) /pin6 (1D2) /pin7 (1Q2) /pin8 (1D3) /pin9 (1Q3) /pin10 (1D4) /pin11 (1Q4) /pin12 (Gnd) /pin13 {(2Clr) {ol}} /pin14 {(2C1) {ol}} /pin15 {(2C2) {ol}} /pin16 (2D1) /pin17 (2Q1) /pin18 (2D2) /pin19 (2Q2) /pin20 (2D3) /pin21 (2Q3) /pin22 (2D4) /pin23 (2Q4) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74120 Template16
+
+/dil_74120 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74120) /title {(driver) {CR} (synchronizer/) {CR} (2 pulse)} /@index @index /pkg pkg /pin1 (1M) /pin2 {(1S1) {ol}} /pin3 {(1S2) {ol}} /pin4 {(1R) {ol}} /pin5 (1C) /pin6 (1Y) /pin7 {(1Y) {ol}} /pin8 (Gnd) /pin9 {(2Y) {ol}} /pin10 (2Y) /pin11 (2C) /pin12 {(2R) {ol}} /pin13 {(2S1) {ol}} /pin14 {(2S2) {ol}} /pin15 (2M) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74121 Template14
+
+/dil_74121 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74121) /title {(input) {CR} (trigger) {CR} (w. Schmitt) {CR} (multivibrator) {CR} (monostable)} /@index @index /pkg pkg /pin1 {(Q) {ol}} /pin2 (NC) /pin3 (A1) /pin4 (A2) /pin5 (B) /pin6 (Q) /pin7 (Gnd) /pin8 (NC) /pin9 (Rint) /pin10 (Cext) /pin11 (Rext-Cext) /pin12 (NC) /pin13 (NC) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74122 Template14
+
+/dil_74122 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74122) /title {(resistors) {CR} (w. internal) {CR} (multivibrator) {CR} (monostable) {CR} (retriggerable)} /@index @index /pkg pkg /pin1 (A1) /pin2 (A2) /pin3 (B1) /pin4 (B2) /pin5 {(Clr) {ol}} /pin6 {(Q) {ol}} /pin7 (Gnd) /pin8 (Q) /pin9 (Rint) /pin10 (NC) /pin11 (Cext) /pin12 (NC) /pin13 (Rext-Cext) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74123 Template16
+
+/dil_74123 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74123) /title {(multivibrator) {CR} (monostable) {CR} (retriggerable)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 {(1Clr) {ol}} /pin4 {(1Q) {ol}} /pin5 (2Q) /pin6 (2Cext) /pin7 (2Rext-Cext) /pin8 (Gnd) /pin9 (2A) /pin10 (2B) /pin11 {(2Clr) {ol}} /pin12 {(2Q) {ol}} /pin13 (1Q) /pin14 (1Cext) /pin15 (1Rext-Cext) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74124 Template16
+
+/dil_74124 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74124) /title {(oszillators) {CR} (controlled) {CR} (2 voltage)} /@index @index /pkg pkg /pin1 (2FC) /pin2 (1FC) /pin3 (1Rng) /pin4 (1CX1) /pin5 (1CX2) /pin6 {(1En) {ol}} /pin7 (1Y) /pin8 (Osc-Gnd) /pin9 (Gnd) /pin10 (2Y) /pin11 {(2En) {ol}} /pin12 (2CX1) /pin13 (2CX2) /pin14 (2Rng) /pin15 (Osc-Vcc) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74125 Template14
+
+/dil_74125 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74125) /title {(control) {CR} (inverted) {CR} (state) {CR} (buffers 3-) {CR} (4 bus)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A) /pin3 (1Y) /pin4 {(2G) {ol}} /pin5 (2A) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 {(3G) {ol}} /pin11 (4Y) /pin12 (4A) /pin13 {(4G) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74126 Template14
+
+/dil_74126 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74126) /title {(control) {CR} (positive) {CR} (state) {CR} (4 buffers 3-)} /@index @index /pkg pkg /pin1 (1G) /pin2 (1A) /pin3 (1Y) /pin4 (2G) /pin5 (2A) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3G) /pin11 (4Y) /pin12 (4A) /pin13 (4G) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74128 Template14
+
+/dil_74128 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74128) /title {(drivers) {CR} (4 line)} /@index @index /pkg pkg /pin1 (1Y) /pin2 (1A) /pin3 (1B) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4A) /pin12 (4B) /pin13 (4Y) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74132 Template14
+
+/dil_74132 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74132) /title {(trigger) {CR} (Schmitt) {CR} (4 dual NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74133 Template16
+
+/dil_74133 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74133) /title {(NAND) {CR} (13 input)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 (D) /pin5 (E) /pin6 (F) /pin7 (G) /pin8 (Gnd) /pin9 (Y) /pin10 (H) /pin11 (I) /pin12 (J) /pin13 (K) /pin14 (L) /pin15 (M) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74134 Template16
+
+/dil_74134 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74134) /title {(state) {CR} (NAND 3-) {CR} (12 input)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 (D) /pin5 (E) /pin6 (F) /pin7 (G) /pin8 (Gnd) /pin9 (Y) /pin10 (H) /pin11 (I) /pin12 (J) /pin13 (K) /pin14 (L) /pin15 {(OC) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74135 Template16
+
+/dil_74135 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74135) /title {(XNOR) {CR} (4 dual-XOR-)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (1C-2C) /pin5 (2A) /pin6 (2B) /pin7 (2Y) /pin8 (Gnd) /pin9 (3Y) /pin10 (3A) /pin11 (3B) /pin12 (3c-4c) /pin13 (4Y) /pin14 (4A) /pin15 (4B) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74136 Template14
+
+/dil_74136 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74136) /title {(OC) {CR} (4 dual-XOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2Y) /pin7 (Gnd) /pin8 (3Y) /pin9 (3A) /pin10 (3B) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74137 Template16
+
+/dil_74137 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74137) /title {(latch) {CR} (address) {CR} (decoder w.) {CR} (3-to-8)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 {(GL) {ol}} /pin5 {(G2) {ol}} /pin6 (G1) /pin7 (Y7) /pin8 (Gnd) /pin9 (Y6) /pin10 (Y5) /pin11 (Y4) /pin12 (Y3) /pin13 (Y2) /pin14 (Y1) /pin15 (Y0) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74138 Template16
+
+/dil_74138 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74138) /title {(decoder) {CR} (3-to-8)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (C) /pin4 {(G2A) {ol}} /pin5 {(G2B) {ol}} /pin6 (G1) /pin7 (Y7) /pin8 (Gnd) /pin9 (Y6) /pin10 (Y5) /pin11 (Y4) /pin12 (Y3) /pin13 (Y2) /pin14 (Y1) /pin15 (Y0) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74139 Template16
+
+/dil_74139 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74139) /title {(decoder) {CR} (2 2-to-4)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (A1) /pin3 (B1) /pin4 (Y10) /pin5 (Y11) /pin6 (Y12) /pin7 (Y13) /pin8 (Gnd) /pin9 (Y23) /pin10 (Y22) /pin11 (Y21) /pin12 (Y20) /pin13 (B2) /pin14 (A2) /pin15 {(G2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74140 Template14
+
+/dil_74140 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74140) /title {(driver) {CR} (50Ohm) {CR} (2 quad-NAND)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (NC) /pin4 (1C) /pin5 (1D) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2A) /pin10 (2B) /pin11 (NC) /pin12 (2C) /pin13 (2D) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74143 Template24
+
+/dil_74143 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74143) /title {(driver) {CR} (segment) {CR} (latch 7-) {CR} (4bit counter/)} /@index @index /pkg pkg /pin1 {(SCEI) {ol}} /pin2 (Clk) /pin3 {(Clr) {ol}} /pin4 {(RBI) {ol}} /pin5 (BI) /pin6 {(RBO) {ol} (BI-) {ol}} /pin7 (Dp) /pin8 (dp) /pin9 (d) /pin10 (f) /pin11 (e) /pin12 (Gnd) /pin13 (g) /pin14 (c) /pin15 (a) /pin16 (b) /pin17 (Qa) /pin18 (Qb) /pin19 (Qc) /pin20 (Qd) /pin21 {(StrB) {ol}} /pin22 (Max) /pin23 {(PECI) {ol}} /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74145 Template16
+
+/dil_74145 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74145) /title {(decoder) {CR} (decimal) {CR} (BCD to)} /@index @index /pkg pkg /pin1 (0) /pin2 (1) /pin3 (2) /pin4 (3) /pin5 (4) /pin6 (5) /pin7 (6) /pin8 (Gnd) /pin9 (7) /pin10 (8) /pin11 (9) /pin12 (D) /pin13 (C) /pin14 (B) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74147 Template16
+
+/dil_74147 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74147) /title {(encoder) {CR} (10-to-4)} /@index @index /pkg pkg /pin1 (4) /pin2 (5) /pin3 (6) /pin4 (7) /pin5 (8) /pin6 (C) /pin7 (B) /pin8 (Gnd) /pin9 (A) /pin10 (9) /pin11 (1) /pin12 (2) /pin13 (3) /pin14 (D) /pin15 (NC) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74148 Template16
+
+/dil_74148 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74148) /title {(encoder) {CR} (8-to-3)} /@index @index /pkg pkg /pin1 (4) /pin2 (5) /pin3 (6) /pin4 (7) /pin5 {(Ei) {ol}} /pin6 (A2) /pin7 (A1) /pin8 (Gnd) /pin9 (A0) /pin10 (0) /pin11 (1) /pin12 (2) /pin13 (3) /pin14 {(Gs) {ol}} /pin15 {(Eo) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74150 Template24
+
+/dil_74150 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74150) /title {(selector) {CR} (1-of-16)} /@index @index /pkg pkg /pin1 (E7) /pin2 (E6) /pin3 (E5) /pin4 (E4) /pin5 (E3) /pin6 (E2) /pin7 (E1) /pin8 (E0) /pin9 {(G) {ol}} /pin10 (W) /pin11 (D) /pin12 (Gnd) /pin13 (C) /pin14 (B) /pin15 (A) /pin16 (E15) /pin17 (E14) /pin18 (E13) /pin19 (E12) /pin20 (E11) /pin21 (E10) /pin22 (E9) /pin23 (E8) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74151 Template16
+
+/dil_74151 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74151) /title {(selector) {CR} (1-of-8)} /@index @index /pkg pkg /pin1 (D3) /pin2 (D2) /pin3 (D1) /pin4 (D0) /pin5 (Y) /pin6 (W) /pin7 {(G) {ol}} /pin8 (Gnd) /pin9 (C) /pin10 (B) /pin11 (A) /pin12 (D7) /pin13 (D6) /pin14 (D5) /pin15 (D4) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74153 Template16
+
+/dil_74153 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74153) /title {(selectors) {CR} (2 4-to-1)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (B) /pin3 (1C3) /pin4 (1C2) /pin5 (1C1) /pin6 (1C0) /pin7 (1Y) /pin8 (Gnd) /pin9 (2Y) /pin10 (2C0) /pin11 (2C1) /pin12 (2C2) /pin13 (2C3) /pin14 (A) /pin15 {(2G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74154 Template24
+
+/dil_74154 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74154) /title {(decoder) {CR} (4-to-16)} /@index @index /pkg pkg /pin1 (0) /pin2 (1) /pin3 (2) /pin4 (3) /pin5 (4) /pin6 (5) /pin7 (6) /pin8 (7) /pin9 (8) /pin10 (9) /pin11 (10) /pin12 (Gnd) /pin13 (11) /pin14 (12) /pin15 (13) /pin16 (14) /pin17 (15) /pin18 {(G1) {ol}} /pin19 {(G2) {ol}} /pin20 (D) /pin21 (C) /pin22 (B) /pin23 (A) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74155 Template16
+
+/dil_74155 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74155) /title {(decoder) {CR} (2 2-to-4)} /@index @index /pkg pkg /pin1 (1C) /pin2 {(1G) {ol}} /pin3 (B) /pin4 (1Y3) /pin5 (1Y2) /pin6 (1Y1) /pin7 (1Y0) /pin8 (Gnd) /pin9 (2Y0) /pin10 (2Y1) /pin11 (2Y2) /pin12 (2Y3) /pin13 (A) /pin14 {(2G) {ol}} /pin15 {(2C) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74156 Template16
+
+/dil_74156 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74156) /title {(decoder OC) {CR} (2 2-to-4)} /@index @index /pkg pkg /pin1 (1C) /pin2 {(1G) {ol}} /pin3 (B) /pin4 (1Y3) /pin5 (1Y2) /pin6 (1Y1) /pin7 (1Y0) /pin8 (Gnd) /pin9 (2Y0) /pin10 (2Y1) /pin11 (2Y2) /pin12 (2Y3) /pin13 (A) /pin14 {(2G) {ol}} /pin15 {(2C) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74157 Template16
+
+/dil_74157 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74157) /title {(selector) {CR} (4 2-to-1)} /@index @index /pkg pkg /pin1 {(A-B) {ol}} /pin2 (1A) /pin3 (1B) /pin4 (1Y) /pin5 (2A) /pin6 (2B) /pin7 (2Y) /pin8 (Gnd) /pin9 (3Y) /pin10 (3B) /pin11 (3A) /pin12 (4Y) /pin13 (4Y) /pin14 (4A) /pin15 {(G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74158 Template16
+
+/dil_74158 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74158) /title {(output) {CR} (inverted) {CR} (selector) {CR} (4 2-to-1)} /@index @index /pkg pkg /pin1 {(A-B) {ol}} /pin2 (1A) /pin3 (1B) /pin4 {(1Y) {ol}} /pin5 (2A) /pin6 (2B) /pin7 {(2Y) {ol}} /pin8 (Gnd) /pin9 {(3Y) {ol}} /pin10 (3B) /pin11 (3A) /pin12 (4Y) /pin13 {(4Y) {ol}} /pin14 (4A) /pin15 {(G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74159 Template24
+
+/dil_74159 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74159) /title {(decoder OC) {CR} (4-to-16)} /@index @index /pkg pkg /pin1 (0) /pin2 (1) /pin3 (2) /pin4 (3) /pin5 (4) /pin6 (5) /pin7 (6) /pin8 (7) /pin9 (8) /pin10 (9) /pin11 (10) /pin12 (Gnd) /pin13 (11) /pin14 (12) /pin15 (13) /pin16 (14) /pin17 (15) /pin18 {(G1) {ol}} /pin19 {(G2) {ol}} /pin20 (D) /pin21 (C) /pin22 (B) /pin23 (A) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74160 Template16
+
+/dil_74160 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74160) /title {(clear) {CR} (async.) {CR} (counter w.) {CR} (decade) {CR} (syncronous)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 (ENT) /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 (RCO) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74161 Template16
+
+/dil_74161 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74161) /title {(clear) {CR} (async.) {CR} (counter w.) {CR} (4bit binary) {CR} (syncronous)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 (ENT) /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 (RCO) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74162 Template16
+
+/dil_74162 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74162) /title {(sync. clear) {CR} (counter w.) {CR} (decade) {CR} (syncronous)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 (ENT) /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 (RCO) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74163 Template16
+
+/dil_74163 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74163) /title {(sync. clear) {CR} (counter w.) {CR} (4bit binary) {CR} (syncronous)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 (ENT) /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 (RCO) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74164 Template14
+
+/dil_74164 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74164) /title {(register) {CR} (out shift) {CR} (parallel-) {CR} (8bit)} /@index @index /pkg pkg /pin1 (A) /pin2 (B) /pin3 (Qa) /pin4 (Qb) /pin5 (Qc) /pin6 (Qd) /pin7 (Gnd) /pin8 (Clk) /pin9 {(Clr) {ol}} /pin10 (Qe) /pin11 (Qf) /pin12 (Qg) /pin13 (Qh) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74165 Template16
+
+/dil_74165 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74165) /title {(register) {CR} (shift) {CR} (load 8bit) {CR} (parallel-)} /@index @index /pkg pkg /pin1 {(LD) {ol} (SH-)} /pin2 (Clk) /pin3 (E) /pin4 (F) /pin5 (G) /pin6 (H) /pin7 {(Qh) {ol}} /pin8 (Gnd) /pin9 (Qh) /pin10 (SER) /pin11 (A) /pin12 (B) /pin13 (C) /pin14 (D) /pin15 (Clk_Inh) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74166 Template16
+
+/dil_74166 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74166) /title {(register) {CR} (shift) {CR} (load 8bit) {CR} (parallel-)} /@index @index /pkg pkg /pin1 (SER) /pin2 (A) /pin3 (B) /pin4 (C) /pin5 (D) /pin6 (Clk_Inh) /pin7 (Clk) /pin8 (Gnd) /pin9 {(Clr) {ol}} /pin10 (E) /pin11 (F) /pin12 (G) /pin13 (Qh) /pin14 (H) /pin15 {(LD) {ol} (SH-)} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74167 Template16
+
+/dil_74167 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74167) /title {(multiplier) {CR} (decade rate) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (NC) /pin2 (B2) /pin3 (B3) /pin4 (Set-to-9) /pin5 (Z) /pin6 (Y) /pin7 (ENout) /pin8 (Gnd) /pin9 (Clk) /pin10 (StrB) /pin11 (ENin) /pin12 (Unity-CAS) /pin13 (Clr) /pin14 (Bo) /pin15 (B1) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74169 Template16
+
+/dil_74169 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74169) /title {(counter) {CR} (up/down) {CR} (sync. 4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 {(ENT) {ol}} /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 {(RCO) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74170 Template16
+
+/dil_74170 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74170) /title {(files OC) {CR} (register) {CR} (4-by-4)} /@index @index /pkg pkg /pin1 (D2) /pin2 (D3) /pin3 (D4) /pin4 (Rb) /pin5 (Ra) /pin6 (Q4) /pin7 (Q3) /pin8 (Gnd) /pin9 (Q2) /pin10 (Q1) /pin11 {(Gr) {ol}} /pin12 {(Gw) {ol}} /pin13 (Wb) /pin14 (Wa) /pin15 (D1) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74171 Template16
+
+/dil_74171 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74171) /title {(w. clear) {CR} (4 D-type FF)} /@index @index /pkg pkg /pin1 {(1Q) {ol}} /pin2 {(2Q) {ol}} /pin3 (2Q) /pin4 (2D) /pin5 (3D) /pin6 (3Q) /pin7 {(3Q) {ol}} /pin8 (Gnd) /pin9 {(4Q) {ol}} /pin10 (4Q) /pin11 (4D) /pin12 (Clk) /pin13 {(Clr) {ol}} /pin14 (1D) /pin15 (1Q) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74172 Template24
+
+/dil_74172 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74172) /title {(state) {CR} (file 3-) {CR} (register) {CR} (port) {CR} (multiple-) {CR} (16bit)} /@index @index /pkg pkg /pin1 (1W1) /pin2 (1W0) /pin3 {(1Gw) {ol}} /pin4 (1DB) /pin5 (2DB) /pin6 (Clk) /pin7 (1R2) /pin8 (1R1) /pin9 (1R0) /pin10 (1Qb) /pin11 (2Qb) /pin12 (Gnd) /pin13 (2Qa) /pin14 (1Qa) /pin15 {(1Gr) {ol}} /pin16 {(2Gr) {ol}} /pin17 (2W-R0) /pin18 (2W-R1) /pin19 (2W-R2) /pin20 {(2Gw) {ol}} /pin21 (2Da) /pin22 (1Da) /pin23 (1W2) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74173 Template16
+
+/dil_74173 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74173) /title {(state) {CR} (register 3-) {CR} (4bit D-type)} /@index @index /pkg pkg /pin1 (M) /pin2 (N) /pin3 (1Q) /pin4 (2Q) /pin5 (3Q) /pin6 (4Q) /pin7 (Clk) /pin8 (Gnd) /pin9 {(G1) {ol}} /pin10 {(G2) {ol}} /pin11 (4D) /pin12 (3D) /pin13 (2D) /pin14 (1D) /pin15 (Clr) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74174 Template16
+
+/dil_74174 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74174) /title {(output) {CR} (single-rail) {CR} (6 D-type FF)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3D) /pin7 (3Q) /pin8 (Gnd) /pin9 (Clk) /pin10 (4Q) /pin11 (4D) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74175 Template16
+
+/dil_74175 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74175) /title {(output) {CR} (double-rail) {CR} (4 D-type FF)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1Q) /pin3 {(1Q) {ol}} /pin4 (1D) /pin5 (2D) /pin6 {(2Q) {ol}} /pin7 (2Q) /pin8 (Gnd) /pin9 (Clk) /pin10 (3Q) /pin11 {(3Q) {ol}} /pin12 (3D) /pin13 (4D) /pin14 {(4Q) {ol}} /pin15 (4Q) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74176 Template14
+
+/dil_74176 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74176) /title {(2/5\)) {CR} (\(divide by) {CR} (latch) {CR} (counter/) {CR} (decade) {CR} (presettable)} /@index @index /pkg pkg /pin1 {(Load) {ol}} /pin2 (Qc) /pin3 (C) /pin4 (A) /pin5 (Qa) /pin6 (Clk2) /pin7 (Gnd) /pin8 (Clk1) /pin9 (Qb) /pin10 (B) /pin11 (D) /pin12 (Qd) /pin13 {(Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74177 Template14
+
+/dil_74177 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74177) /title {(2/8\)) {CR} (\(divide by) {CR} (latch) {CR} (counter/) {CR} (binary) {CR} (presettable)} /@index @index /pkg pkg /pin1 {(Load) {ol}} /pin2 (Qc) /pin3 (C) /pin4 (A) /pin5 (Qa) /pin6 (Clk2) /pin7 (Gnd) /pin8 (Clk1) /pin9 (Qb) /pin10 (B) /pin11 (D) /pin12 (Qd) /pin13 {(Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74178 Template14
+
+/dil_74178 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74178) /title {(register) {CR} (shift) {CR} (access) {CR} (parallel-) {CR} (4bit)} /@index @index /pkg pkg /pin1 (B) /pin2 (A) /pin3 (SER) /pin4 (Qa) /pin5 (Clk) /pin6 (Qb) /pin7 (Gnd) /pin8 (Qc) /pin9 (Load) /pin10 (Qd) /pin11 (Shift) /pin12 (D) /pin13 (C) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74180 Template14
+
+/dil_74180 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74180) /title {(checker) {CR} (generator/) {CR} (odd parity) {CR} (even/) {ol} (9bit )} /@index @index /pkg pkg /pin1 (G) /pin2 (H) /pin3 (Even) /pin4 (Odd) /pin5 (SumEven) /pin6 (SumOdd) /pin7 (Gnd) /pin8 (A) /pin9 (B) /pin10 (C) /pin11 (D) /pin12 (E) /pin13 (F) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74181 Template24
+
+/dil_74181 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74181) /title {(generator) {CR} (ALU function)} /@index @index /pkg pkg /pin1 {(B0) {ol}} /pin2 {(A0) {ol}} /pin3 (S3) /pin4 (S2) /pin5 (S1) /pin6 (S0) /pin7 (Cn) /pin8 (M) /pin9 {(F0) {ol}} /pin10 {(F1) {ol}} /pin11 {(F2) {ol}} /pin12 (Gnd) /pin13 {(F3) {ol}} /pin14 (A=B) /pin15 {(P) {ol}} /pin16 {(Cn+4) {ol}} /pin17 {(G) {ol}} /pin18 {(B3) {ol}} /pin19 {(A3) {ol}} /pin20 {(B2) {ol}} /pin21 {(A2) {ol}} /pin22 {(B1) {ol}} /pin23 {(A1) {ol}} /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74182 Template16
+
+/dil_74182 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74182) /title {(generator) {CR} (carry) {CR} (look-ahead)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 {(P1) {ol}} /pin3 {(G0) {ol}} /pin4 {(P0) {ol}} /pin5 {(G3) {ol}} /pin6 {(P3) {ol}} /pin7 {(P) {ol}} /pin8 (Gnd) /pin9 (Cn+Z) /pin10 {(G) {ol}} /pin11 (Cn+Y) /pin12 (Cn+X) /pin13 (Cn) /pin14 {(G2) {ol}} /pin15 {(P2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74183 Template14
+
+/dil_74183 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74183) /title {(full adders) {CR} (2 carry-save)} /@index @index /pkg pkg /pin1 (1A) /pin2 (NC) /pin3 (1B) /pin4 (1Cn) /pin5 (1Cn+1) /pin6 (1Sum) /pin7 (Gnd) /pin8 (2Sum) /pin9 (NC) /pin10 (2Cn+1) /pin11 (2Cn) /pin12 (2B) /pin13 (2A) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74190 Template16
+
+/dil_74190 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74190) /title {(counter) {CR} (down) {CR} (4bit BCD up/) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (B) /pin2 (Qb) /pin3 (Qa) /pin4 {(CTEN) {ol}} /pin5 {(U) {ol} (D-)} /pin6 (Qc) /pin7 (Qd) /pin8 (Gnd) /pin9 (D) /pin10 (C) /pin11 {(Load) {ol}} /pin12 (Max-Min) /pin13 {(RCO) {ol}} /pin14 (Clk) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74191 Template16
+
+/dil_74191 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74191) /title {(counter) {CR} (up/down) {CR} (4bit binary) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (B) /pin2 (Qb) /pin3 (Qa) /pin4 {(CTEN) {ol}} /pin5 {(U) {ol} (D-)} /pin6 (Qc) /pin7 (Qd) /pin8 (Gnd) /pin9 (D) /pin10 (C) /pin11 {(Load) {ol}} /pin12 (Max-Min) /pin13 {(RCO) {ol}} /pin14 (Clk) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74192 Template16
+
+/dil_74192 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74192) /title {(and clear) {CR} (dual-clock) {CR} (counter w.) {CR} (down) {CR} (4bit BCD up/) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (B) /pin2 (Qb) /pin3 (Qa) /pin4 (Down) /pin5 (Up) /pin6 (Qc) /pin7 (Qd) /pin8 (Gnd) /pin9 (D) /pin10 (C) /pin11 {(Load) {ol}} /pin12 {(CO) {ol}} /pin13 {(BO) {ol}} /pin14 (Clr) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74193 Template16
+
+/dil_74193 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74193) /title {(and clear) {CR} (dual-clock) {CR} (counter w.) {CR} (up/down) {CR} (4bit binary) {CR} (syncronous)} /@index @index /pkg pkg /pin1 (B) /pin2 (Qb) /pin3 (Qa) /pin4 (Down) /pin5 (Up) /pin6 (Qc) /pin7 (Qd) /pin8 (Gnd) /pin9 (D) /pin10 (C) /pin11 {(Load) {ol}} /pin12 {(CO) {ol}} /pin13 {(BO) {ol}} /pin14 (Clr) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74194 Template16
+
+/dil_74194 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74194) /title {(register) {CR} (shift) {CR} (directional) {CR} (4bit bi-)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (SRSer) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (SLSer) /pin8 (Gnd) /pin9 (S0) /pin10 (S1) /pin11 (Clk) /pin12 (Qd) /pin13 (Qc) /pin14 (Qb) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74195 Template16
+
+/dil_74195 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74195) /title {(register) {CR} (shift) {CR} (access) {CR} (parallel-) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (J) /pin3 {(K) {ol}} /pin4 (A) /pin5 (B) /pin6 (C) /pin7 (D) /pin8 (Gnd) /pin9 {(Ld) {ol} (SH-)} /pin10 (Clk) /pin11 {(Qd) {ol}} /pin12 (Qd) /pin13 (Qc) /pin14 (Qb) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74196 Template14
+
+/dil_74196 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74196) /title {(2/5\)) {CR} (\(divide by) {CR} (latch) {CR} (counter/) {CR} (decade) {CR} (presettable)} /@index @index /pkg pkg /pin1 {(Load) {ol}} /pin2 (Qc) /pin3 (C) /pin4 (A) /pin5 (Qa) /pin6 (Clk2) /pin7 (Gnd) /pin8 (Clk1) /pin9 (Qb) /pin10 (B) /pin11 (D) /pin12 (Qd) /pin13 {(Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74197 Template14
+
+/dil_74197 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74197) /title {(2/8\)) {CR} (\(divide by) {CR} (latch) {CR} (counter/) {CR} (binary) {CR} (presettable)} /@index @index /pkg pkg /pin1 {(Load) {ol}} /pin2 (Qc) /pin3 (C) /pin4 (A) /pin5 (Qa) /pin6 (Clk2) /pin7 (Gnd) /pin8 (Clk1) /pin9 (Qb) /pin10 (B) /pin11 (D) /pin12 (Qd) /pin13 {(Clr) {ol}} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74198 Template24
+
+/dil_74198 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74198) /title {(register) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (S0) /pin2 (SPSer) /pin3 (A) /pin4 (Qa) /pin5 (B) /pin6 (Qb) /pin7 (C) /pin8 (Qc) /pin9 (D) /pin10 (Qd) /pin11 (Clk) /pin12 (Gnd) /pin13 {(Clr) {ol}} /pin14 (Qe) /pin15 (E) /pin16 (Qf) /pin17 (F) /pin18 (Qg) /pin19 (G) /pin20 (Qh) /pin21 (H) /pin22 (SLSer) /pin23 (S1) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74199 Template24
+
+/dil_74199 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74199) /title {(input) {CR} (output/JK-) {CR} (input/) {CR} (parallel) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 {(K) {ol}} /pin2 (J) /pin3 (A) /pin4 (Qa) /pin5 (B) /pin6 (Qb) /pin7 (C) /pin8 (Qc) /pin9 (D) /pin10 (Qd) /pin11 (ClkInh) /pin12 (Gnd) /pin13 (Clk) /pin14 {(Clr) {ol}} /pin15 (Qe) /pin16 (E) /pin17 (Qf) /pin18 (F) /pin19 (Qg) /pin20 (G) /pin21 (Qh) /pin22 (H) /pin23 {(LD) {ol} (SH-)} /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74221 Template16
+
+/dil_74221 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74221) /title {(input) {CR} (trigger) {CR} (w. Schmitt) {CR} (multivibrator) {CR} (2 monostable)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1A) /pin3 {(1Clr) {ol}} /pin4 {(1Q) {ol}} /pin5 (2Q) /pin6 (2Cext) /pin7 (2Rext-Cext) /pin8 (Gnd) /pin9 (2A) /pin10 (2B) /pin11 {(2Clr) {ol}} /pin12 {(2Q) {ol}} /pin13 (1Q) /pin14 (1Cext) /pin15 (1Rext-Cext) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74240 Template20
+
+/dil_74240 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74240) /title {(output) {CR} (inverted) {CR} (state w.) {CR} (driver 3-) {CR} (8 buffer/)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A1) /pin3 (2Y4) /pin4 (1A2) /pin5 (2Y3) /pin6 (1A3) /pin7 (2Y2) /pin8 (1A4) /pin9 (2Y1) /pin10 (Gnd) /pin11 (2A1) /pin12 (1Y4) /pin13 (2A2) /pin14 (1Y3) /pin15 (2A3) /pin16 (1Y2) /pin17 (2A4) /pin18 (1Y1) /pin19 {(2G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74241 Template20
+
+/dil_74241 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74241) /title {(enable) {CR} (pos/neg) {CR} (state w.) {CR} (driver 3-) {CR} (8 buffer/)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A1) /pin3 (2Y4) /pin4 (1A2) /pin5 (2Y3) /pin6 (1A3) /pin7 (2Y2) /pin8 (1A4) /pin9 (2Y1) /pin10 (Gnd) /pin11 (2A1) /pin12 (1Y4) /pin13 (2A2) /pin14 (1Y3) /pin15 (2A3) /pin16 (1Y2) /pin17 (2A4) /pin18 (1Y1) /pin19 {(2G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74242 Template14
+
+/dil_74242 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74242) /title {(tranceiver) {CR} (4 bus)} /@index @index /pkg pkg /pin1 {(Gab) {ol}} /pin2 (NC) /pin3 (A1) /pin4 (A2) /pin5 (A3) /pin6 (A4) /pin7 (Gnd) /pin8 (B4) /pin9 (B3) /pin10 (B2) /pin11 (B1) /pin12 (NC) /pin13 (Gba) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74243 Template14
+
+/dil_74243 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74243) /title {(outputs) {CR} (inverting) {CR} (w.) {CR} (tranceiver) {CR} (4 bus)} /@index @index /pkg pkg /pin1 {(Gab) {ol}} /pin2 (NC) /pin3 (A1) /pin4 (A2) /pin5 (A3) /pin6 (A4) /pin7 (Gnd) /pin8 (B4) /pin9 (B3) /pin10 (B2) /pin11 (B1) /pin12 (NC) /pin13 (Gba) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74244 Template20
+
+/dil_74244 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74244) /title {(state) {CR} (driver 3-) {CR} (8 buffer/)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A1) /pin3 (2Y4) /pin4 (1A2) /pin5 (2Y3) /pin6 (1A3) /pin7 (2Y2) /pin8 (1A4) /pin9 (2Y1) /pin10 (Gnd) /pin11 (2A1) /pin12 (1Y4) /pin13 (2A2) /pin14 (1Y3) /pin15 (2A3) /pin16 (1Y2) /pin17 (2A4) /pin18 (1Y1) /pin19 {(2G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74245 Template20
+
+/dil_74245 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74245) /title {(3-state) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (Dir) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74247 Template16
+
+/dil_74247 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74247) /title {(driver OC) {CR} (decoder/) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(LT) {ol}} /pin4 {(RBO) {ol} (BI-) {ol}} /pin5 {(RBI) {ol}} /pin6 (D) /pin7 (A) /pin8 (Gnd) /pin9 (e) /pin10 (d) /pin11 (c) /pin12 (b) /pin13 (a) /pin14 (g) /pin15 (f) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74248 Template16
+
+/dil_74248 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74248) /title {(up) {CR} (output pull-) {CR} (driver w.) {CR} (decoder/) {CR} (segment) {CR} (BCD to 7-)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 {(LT) {ol}} /pin4 {(RBO) {ol} (BI-) {ol}} /pin5 {(RBI) {ol}} /pin6 (D) /pin7 (A) /pin8 (Gnd) /pin9 (e) /pin10 (d) /pin11 (c) /pin12 (b) /pin13 (a) /pin14 (g) /pin15 (f) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74251 Template16
+
+/dil_74251 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74251) /title {(3-state) {CR} (multiplexor) {CR} (selector/) {CR} (data)} /@index @index /pkg pkg /pin1 (D3) /pin2 (D2) /pin3 (D1) /pin4 (D0) /pin5 (Y) /pin6 (W) /pin7 {(G) {ol}} /pin8 (Gnd) /pin9 (C) /pin10 (B) /pin11 (A) /pin12 (D7) /pin13 (D6) /pin14 (D5) /pin15 (D4) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74253 Template16
+
+/dil_74253 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74253) /title {(3-state) {CR} (multiplexor) {CR} (selector/) {CR} (2 4-to-1)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (N) /pin3 (1C3) /pin4 (1C2) /pin5 (1C1) /pin6 (1C0) /pin7 (1Y) /pin8 (Gnd) /pin9 (2Y) /pin10 (2C0) /pin11 (2C1) /pin12 (2C2) /pin13 (2C3) /pin14 (A) /pin15 {(2G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74257 Template16
+
+/dil_74257 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74257) /title {(demultiplexors) {CR} (selectors/) {CR} (4 2-to-1)} /@index @index /pkg pkg /pin1 {(A-B) {ol}} /pin2 (1A) /pin3 (1B) /pin4 (1Y) /pin5 (2A) /pin6 (2B) /pin7 (2Y) /pin8 (Gnd) /pin9 (3Y) /pin10 (3B) /pin11 (3A) /pin12 (4Y) /pin13 (4B) /pin14 (4A) /pin15 {(G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74258 Template16
+
+/dil_74258 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74258) /title {(outputs) {CR} (inverting) {CR} (w.) {CR} (demultiplexors) {CR} (selectors/) {CR} (4 2-to-1)} /@index @index /pkg pkg /pin1 {(A-B) {ol}} /pin2 (1A) /pin3 (1B) /pin4 (1Y) /pin5 (2A) /pin6 (2B) /pin7 (2Y) /pin8 (Gnd) /pin9 (3Y) /pin10 (3B) /pin11 (3A) /pin12 (4Y) /pin13 (4B) /pin14 (4A) /pin15 {(G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74259 Template16
+
+/dil_74259 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74259) /title {(latches) {CR} (addressable) {CR} (8bit)} /@index @index /pkg pkg /pin1 (S0) /pin2 (S1) /pin3 (S2) /pin4 (Q0) /pin5 (Q1) /pin6 (Q2) /pin7 (Q3) /pin8 (Gnd) /pin9 (Q4) /pin10 (Q5) /pin11 (Q6) /pin12 (Q7) /pin13 (D) /pin14 {(G) {ol}} /pin15 {(Clr) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74260 Template14
+
+/dil_74260 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74260) /title {(2 pent-NOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1C) /pin4 (2A) /pin5 (1Y) /pin6 (2Y) /pin7 (Gnd) /pin8 (2B) /pin9 (2C) /pin10 (2D) /pin11 (2E) /pin12 (1D) /pin13 (1E) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74261 Template16
+
+/dil_74261 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74261) /title {(multiplexors) {CR} (binary) {CR} (parallel) {CR} (2bit by 4bit)} /@index @index /pkg pkg /pin1 (B3) /pin2 (B4) /pin3 (C) /pin4 (M2) /pin5 {(Q4) {ol}} /pin6 (Q3) /pin7 (Q2) /pin8 (Gnd) /pin9 (Q1) /pin10 (Q0) /pin11 (M0) /pin12 (M1) /pin13 (B0) /pin14 (B1) /pin15 (B2) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74265 Template16
+
+/dil_74265 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74265) /title {(gates) {CR} (output) {CR} (complementary) {CR} (4)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1W) /pin3 (1Y) /pin4 (2A) /pin5 (2B) /pin6 (2W) /pin7 (2Y) /pin8 (Gnd) /pin9 (3Y) /pin10 (3W) /pin11 (3A) /pin12 (3B) /pin13 (4Y) /pin14 (4W) /pin15 (4A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74266 Template14
+
+/dil_74266 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74266) /title {(OC) {CR} (4 dual-XOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74273 Template20
+
+/dil_74273 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74273) /title {(w. clear) {CR} (8 D-type FF)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3Q) /pin7 (3D) /pin8 (4D) /pin9 (4Q) /pin10 (Gnd) /pin11 (Clk) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (7Q) /pin17 (7D) /pin18 (8D) /pin19 (8Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74276 Template20
+
+/dil_74276 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74276) /title {(K FF) {ol} (4 J-)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1J) /pin3 (1Clk) /pin4 {(1K) {ol}} /pin5 (1Q) /pin6 (2Q) /pin7 {(2K) {ol}} /pin8 (2Clk) /pin9 (2J) /pin10 (Gnd) /pin11 {(Pre) {ol}} /pin12 (3J) /pin13 (3Clk) /pin14 {(3K) {ol}} /pin15 (3Q) /pin16 (4Q) /pin17 {(4K) {ol}} /pin18 (4Clk) /pin19 (4J) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74278 Template14
+
+/dil_74278 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74278) /title {(registers) {CR} (priority) {CR} (cascadable) {CR} (4bit)} /@index @index /pkg pkg /pin1 (Strb) /pin2 (D3) /pin3 (D4) /pin4 (P0) /pin5 (P1) /pin6 (Y4) /pin7 (Gnd) /pin8 (Y3) /pin9 (Y2) /pin10 (Y1) /pin11 (NC) /pin12 (D1) /pin13 (D2) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74279 Template16
+
+/dil_74279 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74279) /title {(latches) {CR} (R) {ol} (S-) {ol} (4 )} /@index @index /pkg pkg /pin1 {(1R) {ol}} /pin2 {(1S1) {ol}} /pin3 {(1S2) {ol}} /pin4 (1Q) /pin5 {(2R) {ol}} /pin6 {(2S) {ol}} /pin7 (2Q) /pin8 (Gnd) /pin9 (3Q) /pin10 {(3R) {ol}} /pin11 {(3S1) {ol}} /pin12 {(3S2) {ol}} /pin13 (4Q) /pin14 {(4R) {ol}} /pin15 {(4S) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74280 Template14
+
+/dil_74280 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74280) /title {(checker) {CR} (generator/) {CR} (even parity) {CR} (9bit odd/)} /@index @index /pkg pkg /pin1 (G) /pin2 (H) /pin3 (NC) /pin4 (I) /pin5 (SumEven) /pin6 (SumOdd) /pin7 (Gnd) /pin8 (A) /pin9 (B) /pin10 (C) /pin11 (D) /pin12 (E) /pin13 (F) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74283 Template16
+
+/dil_74283 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74283) /title {(carry) {CR} (w. fast) {CR} (full adders) {CR} (4bit binary)} /@index @index /pkg pkg /pin1 (Sum2) /pin2 (B2) /pin3 (A2) /pin4 (Sum1) /pin5 (A1) /pin6 (B1) /pin7 (C0) /pin8 (Gnd) /pin9 (C4) /pin10 (Sum4) /pin11 (B4) /pin12 (A4) /pin13 (Sum3) /pin14 (A3) /pin15 (B3) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74285 Template16
+
+/dil_74285 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74285) /title {(multipliers) {CR} (binary) {CR} (parallel) {CR} (4bit by 4bit)} /@index @index /pkg pkg /pin1 (2C) /pin2 (2B) /pin3 (2A) /pin4 (1D) /pin5 (1A) /pin6 (1B) /pin7 (1C) /pin8 (Gnd) /pin9 (Y3) /pin10 (Y2) /pin11 (Y1) /pin12 (Y0) /pin13 {(GB) {ol}} /pin14 {(GA) {ol}} /pin15 (2D) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74290 Template14
+
+/dil_74290 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74290) /title {(to-9) {CR} (clear/set-) {CR} (counter w.) {CR} (decade)} /@index @index /pkg pkg /pin1 {(R9\(1\))} /pin2 (NC) /pin3 {(R9\(2\))} /pin4 (Qc) /pin5 (Qb) /pin6 (NC) /pin7 (Gnd) /pin8 (Qd) /pin9 (Qa) /pin10 (CKA) /pin11 (CKB) /pin12 {(R0\(1\))} /pin13 {(R0\(2\))} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74292 Template16
+
+/dil_74292 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74292) /title {(power 31\)) {CR} (timer \(2) {CR} (divider/) {CR} (programmable)} /@index @index /pkg pkg /pin1 (B) /pin2 (E) /pin3 (Tp1) /pin4 (Clk1) /pin5 (Clk2) /pin6 (Tp2) /pin7 (Q) /pin8 (Gnd) /pin9 (NC) /pin10 (A) /pin11 {(Clr) {ol}} /pin12 (NC) /pin13 (Tp3) /pin14 (D) /pin15 (C) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74293 Template14
+
+/dil_74293 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74293) /title {(clear) {CR} (counter w.) {CR} (4bit binary)} /@index @index /pkg pkg /pin1 (NC) /pin2 (NC) /pin3 (NC) /pin4 (Qc) /pin5 (Qb) /pin6 (NC) /pin7 (Gnd) /pin8 (Qd) /pin9 (Qa) /pin10 (CKA) /pin11 (CKB) /pin12 {(R0\(1\))} /pin13 {(R0\(2\))} /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74294 Template16
+
+/dil_74294 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74294) /title {(power 15\)) {CR} (timer \(2) {CR} (divider/) {CR} (programmable)} /@index @index /pkg pkg /pin1 (B) /pin2 (A) /pin3 (Tp) /pin4 (Clk1) /pin5 (Clk2) /pin6 (NC) /pin7 (Q) /pin8 (Gnd) /pin9 (NC) /pin10 (NC) /pin11 {(Clr) {ol}} /pin12 (NC) /pin13 (NC) /pin14 (D) /pin15 (C) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74295 Template14
+
+/dil_74295 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74295) /title {(state) {CR} (registers 3-) {CR} (right-shift) {CR} (4bit left/)} /@index @index /pkg pkg /pin1 (Ser) /pin2 (A) /pin3 (B) /pin4 (C) /pin5 (D) /pin6 {(SH) {ol} (LD-)} /pin7 (Gnd) /pin8 (OC) /pin9 (Clk) /pin10 (Qd) /pin11 (Qc) /pin12 (Qb) /pin13 (Qa) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74297 Template16
+
+/dil_74297 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74297) /title {(filters) {CR} (digital PLL)} /@index @index /pkg pkg /pin1 (B) /pin2 (A) /pin3 (ENCTR) /pin4 (K-Clk) /pin5 (I-D-Clk) /pin6 {(U) {ol} (d-)} /pin7 (I-D-Out) /pin8 (Gnd) /pin9 (Phase-A1) /pin10 (Phase-B) /pin11 (XORPD-Out) /pin12 (ECPD-Out) /pin13 (Pahse-A2) /pin14 (D) /pin15 (C) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74298 Template16
+
+/dil_74298 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74298) /title {(w. storage) {CR} (multiplexors) {CR} (4 dual-input)} /@index @index /pkg pkg /pin1 (B2) /pin2 (A2) /pin3 (A1) /pin4 (B1) /pin5 (C2) /pin6 (D2) /pin7 (D1) /pin8 (Gnd) /pin9 (C1) /pin10 (WS) /pin11 (Clk) /pin12 (Qd) /pin13 (Qc) /pin14 (Qb) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74299 Template20
+
+/dil_74299 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74299) /title {(registers) {CR} (storage) {CR} (shift/) {CR} (universal) {CR} (8bit)} /@index @index /pkg pkg /pin1 (S0) /pin2 {(G1) {ol}} /pin3 {(G2) {ol}} /pin4 (G-Qg) /pin5 (E-Qe) /pin6 (C-Qc) /pin7 (A-Qa) /pin8 (Qa2) /pin9 {(Clr) {ol}} /pin10 (Gnd) /pin11 (SR) /pin12 (Clk) /pin13 (B-Qb) /pin14 (D-Qd) /pin15 (F-Qf) /pin16 (H-Qh) /pin17 (Qh2) /pin18 (SL) /pin19 (S1) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74320 Template16
+
+/dil_74320 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74320) /title {(oscillator) {CR} (controlled) {CR} (crystal-)} /@index @index /pkg pkg /pin1 (Tank1) /pin2 (Tank2) /pin3 (Gnd1) /pin4 (FFQ) /pin5 (FFD) /pin6 (NC) /pin7 (F) /pin8 (Gnd2) /pin9 {(F+) {ol}} /pin10 (F+) /pin11 (Vcc+) /pin12 {(F) {ol}} /pin13 (NC) /pin14 (Xtal1) /pin15 (Xtal2) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74321 Template16
+
+/dil_74321 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74321) /title {(outputs) {CR} (w. F/2,F/4) {CR} (oscillator) {CR} (controlled) {CR} (crystal-)} /@index @index /pkg pkg /pin1 (Tank1) /pin2 (Tank2) /pin3 (Gnd1) /pin4 (FFQ) /pin5 (FFD) /pin6 (F/4) /pin7 (F) /pin8 (Gnd2) /pin9 {(F+) {ol}} /pin10 (F+) /pin11 (Vcc+) /pin12 {(F) {ol}} /pin13 (F/2) /pin14 (Xtal1) /pin15 (Xtal2) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74322 Template20
+
+/dil_74322 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74322) /title {(sign extend) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 {(P) {ol} (S-)} /pin3 (D0) /pin4 (a-Qa) /pin5 (C-Qc) /pin6 (E-Qe) /pin7 (G-Qg) /pin8 {(OE) {ol}} /pin9 {(Clr) {ol}} /pin10 (Gnd) /pin11 (Clk) /pin12 (Qh+) /pin13 (H-Qh) /pin14 (F-Qf) /pin15 (D-Qd) /pin16 (B-Qb) /pin17 (D1) /pin18 {(SE) {ol}} /pin19 (DS) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74323 Template20
+
+/dil_74323 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74323) /title {(register) {CR} (storage) {CR} (shift/) {CR} (universal) {CR} (8bit)} /@index @index /pkg pkg /pin1 (S0) /pin2 {(G1) {ol}} /pin3 {(G2) {ol}} /pin4 (G-Qg) /pin5 (E-Qe) /pin6 (C-Qc) /pin7 (A-Qa) /pin8 (Qa+) /pin9 {(Clr) {ol}} /pin10 (Gnd) /pin11 (SR) /pin12 (Clk) /pin13 (B-Qb) /pin14 (D-Qd) /pin15 (F-Qf) /pin16 (H-Qh) /pin17 (Qh+) /pin18 (SL) /pin19 (S1) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74348 Template16
+
+/dil_74348 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74348) /title {(state) {CR} (encode 3-) {CR} (priority) {CR} (8-to-3)} /@index @index /pkg pkg /pin1 (4) /pin2 (5) /pin3 (6) /pin4 (7) /pin5 (W1) /pin6 (A2) /pin7 (A1) /pin8 (Gnd) /pin9 (A0) /pin10 (0) /pin11 (1) /pin12 (2) /pin13 (3) /pin14 (GS) /pin15 (E0) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74352 Template16
+
+/dil_74352 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74352) /title {(multiplexor) {CR} (selector/) {CR} (data) {CR} (2 4-to-1)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (B) /pin3 (1C3) /pin4 (1C2) /pin5 (1C1) /pin6 (1C0) /pin7 (1Y) /pin8 (Gnd) /pin9 (2Y) /pin10 (2C0) /pin11 (2C1) /pin12 (2C2) /pin13 (2C3) /pin14 (A) /pin15 {(2G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74353 Template16
+
+/dil_74353 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74353) /title {(3-state) {CR} (multiplexor) {CR} (selector/) {CR} (data) {CR} (2 4-to-1)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (B) /pin3 (1C3) /pin4 (1C2) /pin5 (1C1) /pin6 (1C0) /pin7 (1Y) /pin8 (Gnd) /pin9 (2Y) /pin10 (2C0) /pin11 (2C1) /pin12 (2C2) /pin13 (2C3) /pin14 (A) /pin15 {(2G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74354 Template20
+
+/dil_74354 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74354) /title {(3-state) {CR} (transparent) {CR} (register) {CR} (multiplexor/) {CR} (selector/) {CR} (8-to-1 data)} /@index @index /pkg pkg /pin1 (D7) /pin2 (D6) /pin3 (D5) /pin4 (D4) /pin5 (D3) /pin6 (D2) /pin7 (D1) /pin8 (D0) /pin9 {(DC) {ol}} /pin10 (Gnd) /pin11 {(SC) {ol}} /pin12 (S2) /pin13 (S1) /pin14 (S0) /pin15 {(G1) {ol}} /pin16 {(G2) {ol}} /pin17 (G3) /pin18 (W) /pin19 (Y) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74355 Template20
+
+/dil_74355 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74355) /title {(OC) {CR} (transparent) {CR} (register) {CR} (multiplexor/) {CR} (selector/) {CR} (8-to-1 data)} /@index @index /pkg pkg /pin1 (D7) /pin2 (D6) /pin3 (D5) /pin4 (D4) /pin5 (D3) /pin6 (D2) /pin7 (D1) /pin8 (D0) /pin9 {(DC) {ol}} /pin10 (Gnd) /pin11 {(SC) {ol}} /pin12 (S2) /pin13 (S1) /pin14 (S0) /pin15 {(G1) {ol}} /pin16 {(G2) {ol}} /pin17 (G3) /pin18 (W) /pin19 (Y) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74356 Template20
+
+/dil_74356 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74356) /title {(state) {CR} (triggered 3-) {CR} (edge-) {CR} (register) {CR} (multiplexor/) {CR} (selector/) {CR} (8-to-1 data)} /@index @index /pkg pkg /pin1 (D7) /pin2 (D6) /pin3 (D5) /pin4 (D4) /pin5 (D3) /pin6 (D2) /pin7 (D1) /pin8 (D0) /pin9 (Clk) /pin10 (Gnd) /pin11 {(SC) {ol}} /pin12 (S2) /pin13 (S1) /pin14 (S0) /pin15 {(G1) {ol}} /pin16 {(G2) {ol}} /pin17 (G3) /pin18 (W) /pin19 (Y) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74365 Template16
+
+/dil_74365 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74365) /title {(drivers OC) {CR} (6 bus)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (1A) /pin3 (1Y) /pin4 (2A) /pin5 (2Y) /pin6 (3A) /pin7 (3Y) /pin8 (Gnd) /pin9 (4Y) /pin10 (4A) /pin11 (5Y) /pin12 (5A) /pin13 (6Y) /pin14 (6A) /pin15 {(G2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74366 Template16
+
+/dil_74366 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74366) /title {(output) {CR} (inverting) {CR} (w.) {CR} (drivers OC) {CR} (6 bus)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (1A) /pin3 (1Y) /pin4 (2A) /pin5 (2Y) /pin6 (3A) /pin7 (3Y) /pin8 (Gnd) /pin9 (4Y) /pin10 (4A) /pin11 (5Y) /pin12 (5A) /pin13 (6Y) /pin14 (6A) /pin15 {(G2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74367 Template16
+
+/dil_74367 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74367) /title {(drivers OC) {CR} (6 bus)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (1A1) /pin3 (1Y1) /pin4 (1A2) /pin5 (1Y2) /pin6 (1A3) /pin7 (1Y3) /pin8 (Gnd) /pin9 (1Y4) /pin10 (1A4) /pin11 (2Y1) /pin12 (2A1) /pin13 (2Y2) /pin14 (2A2) /pin15 {(G2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74368 Template16
+
+/dil_74368 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74368) /title {(output) {CR} (inverting) {CR} (w.) {CR} (drivers OC) {CR} (6 bus)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (1A1) /pin3 (1Y1) /pin4 (1A2) /pin5 (1Y2) /pin6 (1A3) /pin7 (1Y3) /pin8 (Gnd) /pin9 (1Y4) /pin10 (1A4) /pin11 (2Y1) /pin12 (2A1) /pin13 (2Y2) /pin14 (2A2) /pin15 {(G2) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74373 Template20
+
+/dil_74373 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74373) /title {(state) {CR} (latches 3-) {CR} (transparent) {CR} (8 D-type)} /@index @index /pkg pkg /pin1 {(OC) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3Q) /pin7 (3D) /pin8 (4D) /pin9 (4Q) /pin10 (Gnd) /pin11 (C) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (7Q) /pin17 (7D) /pin18 (8D) /pin19 (8Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74374 Template20
+
+/dil_74374 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74374) /title {(state) {CR} (8 edge FF 3-)} /@index @index /pkg pkg /pin1 {(OC) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3Q) /pin7 (3D) /pin8 (4D) /pin9 (4Q) /pin10 (Gnd) /pin11 (C) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (7Q) /pin17 (7D) /pin18 (8D) /pin19 (8Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74375 Template16
+
+/dil_74375 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74375) /title {(latch) {CR} (bistable) {CR} (4bit)} /@index @index /pkg pkg /pin1 (1D) /pin2 {(1Q) {ol}} /pin3 (1Q) /pin4 (1C-2C) /pin5 (2Q) /pin6 {(2Q) {ol}} /pin7 (2D) /pin8 (Gnd) /pin9 (3D) /pin10 {(3Q) {ol}} /pin11 (3Q) /pin12 (3C-4C) /pin13 (4Q) /pin14 {(4Q) {ol}} /pin15 (4D) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74376 Template16
+
+/dil_74376 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74376) /title {(4 JK FF)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (1J) /pin3 {(1K) {ol}} /pin4 (1Q) /pin5 (2Q) /pin6 {(2K) {ol}} /pin7 (2J) /pin8 (Gnd) /pin9 (Clk) /pin10 (3J) /pin11 {(3K) {ol}} /pin12 (3Q) /pin13 (4Q) /pin14 {(4K) {ol}} /pin15 (4J) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74377 Template20
+
+/dil_74377 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74377) /title {(output) {CR} (single rail) {CR} (8 FF w.)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3Q) /pin7 (3D) /pin8 (4D) /pin9 (4Q) /pin10 (Gnd) /pin11 (Clk) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (7Q) /pin17 (7D) /pin18 (8D) /pin19 (8Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74378 Template16
+
+/dil_74378 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74378) /title {(output) {CR} (single rail) {CR} (6 FF w.)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 (1Q) /pin3 (1D) /pin4 (2D) /pin5 (2Q) /pin6 (3D) /pin7 (3Q) /pin8 (Gnd) /pin9 (Clk) /pin10 (4Q) /pin11 (4D) /pin12 (5Q) /pin13 (5D) /pin14 (6D) /pin15 (6Q) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74379 Template16
+
+/dil_74379 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74379) /title {(output) {CR} (double rail) {CR} (4 FF w.)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 (1Q) /pin3 {(1Q) {ol}} /pin4 (1D) /pin5 (2D) /pin6 {(2Q) {ol}} /pin7 (2Q) /pin8 (Gnd) /pin9 (Clk) /pin10 (3Q) /pin11 {(3Q) {ol}} /pin12 (3D) /pin13 (4D) /pin14 {(4Q) {ol}} /pin15 (4Q) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74381 Template20
+
+/dil_74381 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74381) /title {(ahead carry) {CR} (w. look-) {CR} (generator) {CR} (ALU function)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A0) /pin4 (B0) /pin5 (S0) /pin6 (S1) /pin7 (S2) /pin8 (F0) /pin9 (F1) /pin10 (Gnd) /pin11 (F2) /pin12 (F3) /pin13 {(G) {ol}} /pin14 {(P) {ol}} /pin15 (Cn) /pin16 (B3) /pin17 (A3) /pin18 (B2) /pin19 (A2) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74382 Template20
+
+/dil_74382 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74382) /title {(carry) {CR} (ripple-) {CR} (w. overflow/) {CR} (generator) {CR} (ALU function)} /@index @index /pkg pkg /pin1 (A1) /pin2 (B1) /pin3 (A0) /pin4 (B0) /pin5 (S0) /pin6 (S1) /pin7 (S2) /pin8 (F0) /pin9 (F1) /pin10 (Gnd) /pin11 (F2) /pin12 (F3) /pin13 (Ovr) /pin14 (Cn+4) /pin15 (Cn) /pin16 (B3) /pin17 (A3) /pin18 (B2) /pin19 (A2) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74384 Template16
+
+/dil_74384 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74384) /title {(multiplier) {CR} (complement) {CR} (twos-) {CR} (8bit by 1bit)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (X3) /pin3 (X2) /pin4 (X1) /pin5 (X0) /pin6 (Prod) /pin7 (Clk) /pin8 (Gnd) /pin9 (Mode) /pin10 (K) /pin11 (X7) /pin12 (X6) /pin13 (X5) /pin14 (X4) /pin15 (Y) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74385 Template20
+
+/dil_74385 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74385) /title {(substractor) {CR} (adder/) {CR} (4 serial)} /@index @index /pkg pkg /pin1 (Clk) /pin2 (1Sum) /pin3 {(A) {ol} (1S-)} /pin4 (1B) /pin5 (1A) /pin6 (2A) /pin7 (2B) /pin8 {(A) {ol} (2S-)} /pin9 (2Sum) /pin10 (Gnd) /pin11 (Clr) /pin12 (3Sum) /pin13 {(A) {ol} (3S-)} /pin14 (3B) /pin15 (3A) /pin16 (4A) /pin17 (4B) /pin18 {(A) {ol} (4S-)} /pin19 (4Sum) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74386 Template14
+
+/dil_74386 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74386) /title {(4 dual-XOR)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 (1Y) /pin4 (2Y) /pin5 (2A) /pin6 (2B) /pin7 (Gnd) /pin8 (3A) /pin9 (3B) /pin10 (3Y) /pin11 (4Y) /pin12 (4A) /pin13 (4B) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74390 Template16
+
+/dil_74390 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74390) /title {(2/5\)) {CR} (\(divide by) {CR} (clear) {CR} (clocks/) {CR} (individual) {CR} (counter w.) {CR} (2 decade)} /@index @index /pkg pkg /pin1 (1ClkA) /pin2 (1Clr) /pin3 (1Qa) /pin4 (1ClkB) /pin5 (1Qb) /pin6 (1Qc) /pin7 (1Qd) /pin8 (Gnd) /pin9 (2Qd) /pin10 (2Qc) /pin11 (2Qb) /pin12 (2ClkB) /pin13 (2Qa) /pin14 (2Clr) /pin15 (2ClkA) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74393 Template14
+
+/dil_74393 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74393) /title {(clear) {CR} (clocks/) {CR} (individual) {CR} (counter w.) {CR} (binary) {CR} (2 4bit)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 (1Clr) /pin3 (1Qa) /pin4 (1Qb) /pin5 (1Qc) /pin6 (1Qd) /pin7 (Gnd) /pin8 (2Qd) /pin9 (2Qc) /pin10 (2Qb) /pin11 (2Qa) /pin12 (2Clr) /pin13 (2Clk) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74395 Template16
+
+/dil_74395 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74395) /title {(state) {CR} (register 3-) {CR} (shift) {CR} (cascadable) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(Clr) {ol}} /pin2 (Ser) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(Sh) {ol} (Ld-)} /pin8 (Gnd) /pin9 {(OC) {ol}} /pin10 (Clk) /pin11 (Qd+) /pin12 (Qd) /pin13 (Qc) /pin14 (Qb) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74396 Template16
+
+/dil_74396 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74396) /title {(register) {CR} (8 storage)} /@index @index /pkg pkg /pin1 (2Q1) /pin2 (1Q1) /pin3 (D1) /pin4 (2Q2) /pin5 (1Q2) /pin6 (D2) /pin7 (Clk) /pin8 (Gnd) /pin9 (D3) /pin10 (1Q3) /pin11 (2Q3) /pin12 (D4) /pin13 (1Q4) /pin14 (2Q4) /pin15 {(G) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74399 Template16
+
+/dil_74399 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74399) /title {(w. storage) {CR} (multiplexor) {CR} (4 dual-input)} /@index @index /pkg pkg /pin1 (WS) /pin2 (Qa) /pin3 (A1) /pin4 (A2) /pin5 (B2) /pin6 (B1) /pin7 (Qb) /pin8 (Gnd) /pin9 (Clk) /pin10 (Qc) /pin11 (C1) /pin12 (C2) /pin13 (D2) /pin14 (D1) /pin15 (Qd) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74422 Template14
+
+/dil_74422 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74422) /title {(resistor) {CR} (w. internal) {CR} (multivibrator) {CR} (monostable) {CR} (retriggerable)} /@index @index /pkg pkg /pin1 (A1) /pin2 (A2) /pin3 (B1) /pin4 (B2) /pin5 {(Clr) {ol}} /pin6 {(Q) {ol}} /pin7 (Gnd) /pin8 (Q) /pin9 (Rint) /pin10 (NC) /pin11 (Cext) /pin12 (NC) /pin13 (Rext-Cext) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74423 Template16
+
+/dil_74423 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74423) /title {(multivibrator) {CR} (monostable) {CR} (retriggerable)} /@index @index /pkg pkg /pin1 (1A) /pin2 (1B) /pin3 {(1Clr) {ol}} /pin4 {(1Q) {ol}} /pin5 (2Q) /pin6 (2Cext) /pin7 (2Rext-Cext) /pin8 (Gnd) /pin9 (2A) /pin10 (2B) /pin11 {(2Clr) {ol}} /pin12 {(2Q) {ol}} /pin13 (1Q) /pin14 (1Cext) /pin15 (1Rext-Cext) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74440 Template20
+
+/dil_74440 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74440) /title {(OC) {CR} (tranceiver) {CR} (bus) {CR} (tridirectional) {CR} (4)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (B1) /pin3 (C1) /pin4 (C2) /pin5 (B2) /pin6 (B3) /pin7 (C3) /pin8 (C4) /pin9 (B4) /pin10 (Gnd) /pin11 (S0) /pin12 (S1) /pin13 (A4) /pin14 (A3) /pin15 (A2) /pin16 (A1) /pin17 {(GA) {ol}} /pin18 {(GB) {ol}} /pin19 {(GC) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74441 Template20
+
+/dil_74441 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74441) /title {(OC) {CR} (tranceiver) {CR} (bus) {CR} (inverting) {CR} (tridirectional) {CR} (4)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (B1) /pin3 (C1) /pin4 (C2) /pin5 (B2) /pin6 (B3) /pin7 (C3) /pin8 (C4) /pin9 (B4) /pin10 (Gnd) /pin11 (S0) /pin12 (S1) /pin13 (A4) /pin14 (A3) /pin15 (A2) /pin16 (A1) /pin17 {(GA) {ol}} /pin18 {(GB) {ol}} /pin19 {(GC) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74442 Template20
+
+/dil_74442 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74442) /title {(3-state) {CR} (tranceiver) {CR} (bus) {CR} (tridirectional) {CR} (4)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (B1) /pin3 (C1) /pin4 (C2) /pin5 (B2) /pin6 (B3) /pin7 (C3) /pin8 (C4) /pin9 (B4) /pin10 (Gnd) /pin11 (S0) /pin12 (S1) /pin13 (A4) /pin14 (A3) /pin15 (A2) /pin16 (A1) /pin17 {(GA) {ol}} /pin18 {(GB) {ol}} /pin19 {(GC) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74443 Template20
+
+/dil_74443 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74443) /title {(3-state) {CR} (tranceiver) {CR} (bus) {CR} (inverting) {CR} (tridirectional) {CR} (4)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (B1) /pin3 (C1) /pin4 (C2) /pin5 (B2) /pin6 (B3) /pin7 (C3) /pin8 (C4) /pin9 (B4) /pin10 (Gnd) /pin11 (S0) /pin12 (S1) /pin13 (A4) /pin14 (A3) /pin15 (A2) /pin16 (A1) /pin17 {(GA) {ol}} /pin18 {(GB) {ol}} /pin19 {(GC) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74444 Template20
+
+/dil_74444 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74444) /title {(3-state) {CR} (tranceiver) {CR} (bus) {CR} (inverting) {CR} (true/) {CR} (tridirectional) {CR} (4)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (B1) /pin3 (C1) /pin4 (C2) /pin5 (B2) /pin6 (B3) /pin7 (C3) /pin8 (C4) /pin9 (B4) /pin10 (Gnd) /pin11 (S0) /pin12 (S1) /pin13 (A4) /pin14 (A3) /pin15 (A2) /pin16 (A1) /pin17 {(GA) {ol}} /pin18 {(GB) {ol}} /pin19 {(GC) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74446 Template16
+
+/dil_74446 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74446) /title {(control) {CR} (direction) {CR} (individual) {CR} (w.) {CR} (tranceiver) {CR} (bus) {CR} (4 inverting)} /@index @index /pkg pkg /pin1 {(GBA) {ol}} /pin2 (A1) /pin3 (Dir2) /pin4 (A2) /pin5 (A3) /pin6 (Dir3) /pin7 (A4) /pin8 (Gnd) /pin9 (B4) /pin10 (Dir4) /pin11 (B3) /pin12 (B2) /pin13 (Dir1) /pin14 (B1) /pin15 {(GAB) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74449 Template16
+
+/dil_74449 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74449) /title {(control) {CR} (direction) {CR} (individual) {CR} (w.) {CR} (tranceiver) {CR} (4 bus)} /@index @index /pkg pkg /pin1 {(GBA) {ol}} /pin2 (A1) /pin3 (Dir2) /pin4 (A2) /pin5 (A3) /pin6 (Dir3) /pin7 (A4) /pin8 (Gnd) /pin9 (B4) /pin10 (Dir4) /pin11 (B3) /pin12 (B2) /pin13 (Dir1) /pin14 (B1) /pin15 {(GAB) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74465 Template20
+
+/dil_74465 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74465) /title {(state) {CR} (8 buffer 3-)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (A1) /pin3 (Y1) /pin4 (A2) /pin5 (Y2) /pin6 (A3) /pin7 (Y3) /pin8 (A4) /pin9 (Y4) /pin10 (Gnd) /pin11 (Y5) /pin12 (A5) /pin13 (Y6) /pin14 (A6) /pin15 (Y7) /pin16 (A7) /pin17 (Y8) /pin18 (A8) /pin19 {(G2) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74466 Template20
+
+/dil_74466 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74466) /title {(state) {CR} (buffer 3-) {CR} (8 invering)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (A1) /pin3 (Y1) /pin4 (A2) /pin5 (Y2) /pin6 (A3) /pin7 (Y3) /pin8 (A4) /pin9 (Y4) /pin10 (Gnd) /pin11 (Y5) /pin12 (A5) /pin13 (Y6) /pin14 (A6) /pin15 (Y7) /pin16 (A7) /pin17 (Y8) /pin18 (A8) /pin19 {(G2) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74467 Template20
+
+/dil_74467 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74467) /title {(signals) {CR} (enable) {CR} (seperate) {CR} (state w.) {CR} (8 buffer 3-)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A1) /pin3 (1Y1) /pin4 (1A2) /pin5 (1Y2) /pin6 (1A3) /pin7 (1Y3) /pin8 (1A4) /pin9 (1Y4) /pin10 (Gnd) /pin11 (2Y1) /pin12 (2A1) /pin13 (2Y2) /pin14 (2A2) /pin15 (2Y3) /pin16 (2A3) /pin17 (2Y4) /pin18 (2A4) /pin19 {(2G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74468 Template20
+
+/dil_74468 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74468) /title {(signals) {CR} (enable) {CR} (seperate) {CR} (state w.) {CR} (buffer 3-) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 {(1G) {ol}} /pin2 (1A1) /pin3 (1Y1) /pin4 (1A2) /pin5 (1Y2) /pin6 (1A3) /pin7 (1Y3) /pin8 (1A4) /pin9 (1Y4) /pin10 (Gnd) /pin11 (2Y1) /pin12 (2A1) /pin13 (2Y2) /pin14 (2A2) /pin15 (2Y3) /pin16 (2A3) /pin17 (2Y4) /pin18 (2A4) /pin19 {(2G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74490 Template16
+
+/dil_74490 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74490) /title {(counter) {CR} (decade) {CR} (4 4bit)} /@index @index /pkg pkg /pin1 (1Clk) /pin2 (1Clr) /pin3 (1Qa) /pin4 (1Set9) /pin5 (1Qb) /pin6 (1Qc) /pin7 (1Qd) /pin8 (Gnd) /pin9 (2Qd) /pin10 (2Qc) /pin11 (2Qb) /pin12 (2Set9) /pin13 (2Qa) /pin14 (2Clr) /pin15 (2Clk) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74518 Template20
+
+/dil_74518 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74518) /title {(pull-up) {CR} (OC w. input) {CR} (comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(OEN) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 (P=Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74519 Template20
+
+/dil_74519 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74519) /title {(OC) {CR} (comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(OEN) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 (P=Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74520 Template20
+
+/dil_74520 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74520) /title {(pull-up) {CR} (w. input) {CR} (comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(OEN) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74521 Template20
+
+/dil_74521 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74521) /title {(comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(OEN) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74522 Template20
+
+/dil_74522 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74522) /title {(pull-up) {CR} (OC w. input) {CR} (comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(OEN) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74538 Template20
+
+/dil_74538 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74538) /title {(state) {CR} (decoder 3-) {CR} (3-to-8)} /@index @index /pkg pkg /pin1 (Y2) /pin2 (Y1) /pin3 (Y0) /pin4 {(OE1) {ol}} /pin5 {(OE2) {ol}} /pin6 (A) /pin7 (B) /pin8 (Y5) /pin9 (Y6) /pin10 (Gnd) /pin11 (Y7) /pin12 (AL) /pin13 (G1) /pin14 (G2) /pin15 {(G3) {ol}} /pin16 {(G4) {ol}} /pin17 (C) /pin18 (Y4) /pin19 (Y3) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74540 Template20
+
+/dil_74540 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74540) /title {(state) {CR} (driver 3-) {CR} (buffer/) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (Y8) /pin12 (Y7) /pin13 (Y6) /pin14 (Y5) /pin15 (Y4) /pin16 (Y3) /pin17 (Y2) /pin18 (Y1) /pin19 {(G2) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74541 Template20
+
+/dil_74541 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74541) /title {(state) {CR} (driver 3-) {CR} (8 buffer/)} /@index @index /pkg pkg /pin1 {(G1) {ol}} /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (Y8) /pin12 (Y7) /pin13 (Y6) /pin14 (Y5) /pin15 (Y4) /pin16 (Y3) /pin17 (Y2) /pin18 (Y1) /pin19 {(G2) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74573 Template20
+
+/dil_74573 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74573) /title {(state) {CR} (latch 3-) {CR} (transparent) {CR} (8 D-type)} /@index @index /pkg pkg /pin1 {(Oe) {ol}} /pin2 (1D) /pin3 (2D) /pin4 (3D) /pin5 (4D) /pin6 (5D) /pin7 (6D) /pin8 (7D) /pin9 (8D) /pin10 (Gnd) /pin11 (Le) /pin12 (8Q) /pin13 (7Q) /pin14 (6Q) /pin15 (5Q) /pin16 (4Q) /pin17 (3Q) /pin18 (2Q) /pin19 (1Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74574 Template20
+
+/dil_74574 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74574) /title {(state) {CR} (edge FF 3-) {CR} (8 D-type)} /@index @index /pkg pkg /pin1 {(Oe) {ol}} /pin2 (1D) /pin3 (2D) /pin4 (3D) /pin5 (4D) /pin6 (5D) /pin7 (6D) /pin8 (7D) /pin9 (8D) /pin10 (Gnd) /pin11 (Clk) /pin12 (8Q) /pin13 (7Q) /pin14 (6Q) /pin15 (5Q) /pin16 (4Q) /pin17 (3Q) /pin18 (2Q) /pin19 (1Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74575 Template20
+
+/dil_74575 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74575) /title {(sync. clear) {CR} (state w.) {CR} (edge FF 3-) {CR} (8 D-type)} /@index @index /pkg pkg /pin1 {(Oe) {ol}} /pin2 (1D) /pin3 (2D) /pin4 (3D) /pin5 (4D) /pin6 (5D) /pin7 (6D) /pin8 (7D) /pin9 (8D) /pin10 (Gnd) /pin11 (Clk) /pin12 (8Q) /pin13 (7Q) /pin14 (6Q) /pin15 (5Q) /pin16 (4Q) /pin17 (3Q) /pin18 (2Q) /pin19 (1Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74580 Template20
+
+/dil_74580 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74580) /title {(output) {CR} (inverted) {CR} (state w.) {CR} (latch 3-) {CR} (transparent) {CR} (8 D-type)} /@index @index /pkg pkg /pin1 {(Oe) {ol}} /pin2 (1D) /pin3 (2D) /pin4 (3D) /pin5 (4D) /pin6 (5D) /pin7 (6D) /pin8 (7D) /pin9 (8D) /pin10 (Gnd) /pin11 (Le) /pin12 (8Q) /pin13 (7Q) /pin14 (6Q) /pin15 (5Q) /pin16 (4Q) /pin17 (3Q) /pin18 (2Q) /pin19 (1Q) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74590 Template16
+
+/dil_74590 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74590) /title {(state) {CR} (register 3-) {CR} (output) {CR} (counter w.) {CR} (8bit binary)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 {(RCO) {ol}} /pin10 {(CClr) {ol}} /pin11 (CCK) /pin12 {(CCKEn) {ol}} /pin13 (RCK) /pin14 {(G) {ol}} /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74591 Template16
+
+/dil_74591 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74591) /title {(register OC) {CR} (output) {CR} (counter w.) {CR} (8bit binary)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 {(RCO) {ol}} /pin10 {(CClr) {ol}} /pin11 (CCK) /pin12 {(CCKEn) {ol}} /pin13 (RCK) /pin14 {(G) {ol}} /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74592 Template16
+
+/dil_74592 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74592) /title {(clear) {CR} (w. load/) {CR} (8bit counter)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 (D) /pin4 (E) /pin5 (F) /pin6 (G) /pin7 (H) /pin8 (Gnd) /pin9 {(Rc0) {ol}} /pin10 {(Clr) {ol}} /pin11 (Clk) /pin12 {(ClkEn) {ol}} /pin13 (RClk) /pin14 {(Load) {ol}} /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74593 Template20
+
+/dil_74593 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74593) /title {(IO) {CR} (and 3-state) {CR} (load/clear) {CR} (counter w.) {CR} (8bit binary)} /@index @index /pkg pkg /pin1 (A-Qa) /pin2 (B-Qb) /pin3 (C-Qc) /pin4 (D-Qd) /pin5 (E-Qe) /pin6 (F-Qf) /pin7 (G-Qf) /pin8 (H-Qh) /pin9 {(CLoad) {ol}} /pin10 (Gnd) /pin11 {(RCO) {ol}} /pin12 {(CClr) {ol}} /pin13 (CCK) /pin14 {(CCKEn) {ol}} /pin15 (CCKEn) /pin16 (RCK) /pin17 {(RCKEn) {ol}} /pin18 {(G) {ol}} /pin19 (G) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74594 Template16
+
+/dil_74594 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74594) /title {(latch) {CR} (output) {CR} (buffered) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 (Qh+) /pin10 {(SRClr) {ol}} /pin11 {(SRCK) {ol}} /pin12 (RCK) /pin13 {(RClr) {ol}} /pin14 (SER) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74595 Template16
+
+/dil_74595 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74595) /title {(state) {CR} (latch 3-) {CR} (output) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 (Qh+) /pin10 {(SRClr) {ol}} /pin11 (SRCK) /pin12 (RCK) /pin13 {(G) {ol}} /pin14 (SER) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74596 Template16
+
+/dil_74596 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74596) /title {(latch OC) {CR} (output) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 (Qh+) /pin10 {(SRClr) {ol}} /pin11 (SRCK) /pin12 (RCK) /pin13 {(G) {ol}} /pin14 (SER) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74597 Template16
+
+/dil_74597 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74597) /title {(input latch) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (B) /pin2 (C) /pin3 (D) /pin4 (E) /pin5 (F) /pin6 (G) /pin7 (H) /pin8 (Gnd) /pin9 (Qh+) /pin10 {(SRClr) {ol}} /pin11 (SRCK) /pin12 (RCK) /pin13 {(SRLoad) {ol}} /pin14 (SER) /pin15 (A) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74598 Template20
+
+/dil_74598 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74598) /title {(state IO) {CR} (parallel 3-) {CR} (register/) {CR} (input) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (A-Qa) /pin2 (B-Qb) /pin3 (C-Qc) /pin4 (D-Qd) /pin5 (E-Qe) /pin6 (F-Qf) /pin7 (G-Qg) /pin8 (H-Qh) /pin9 {(SRLoad) {ol}} /pin10 (Gnd) /pin11 (Qh+) /pin12 {(SRClr) {ol}} /pin13 (SRCK) /pin14 {(SRCKEn) {ol}} /pin15 (RCK) /pin16 {(G) {ol}} /pin17 (Ser1) /pin18 (Ser0) /pin19 (DS) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74599 Template16
+
+/dil_74599 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74599) /title {(latch OC) {CR} (output) {CR} (register w.) {CR} (8bit shift)} /@index @index /pkg pkg /pin1 (Qb) /pin2 (Qc) /pin3 (Qd) /pin4 (Qe) /pin5 (Qf) /pin6 (Qg) /pin7 (Qh) /pin8 (Gnd) /pin9 (Qh+) /pin10 {(SRClr) {ol}} /pin11 {(SRCK) {ol}} /pin12 (RCK) /pin13 {(RClr) {ol}} /pin14 (SER) /pin15 (Qa) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74604 Template28
+
+/dil_74604 {
+<</@index (?) /pkg (DIP28) >> begingate
+1.00 0 0 0 << /gate (74604) /title {(state) {CR} (latch 3-) {CR} (multiplexed) {CR} (speed) {CR} (maximum) {CR} (8 2-input)} /@index @index /pkg pkg /pin1 (Clk) /pin2 {(B) {ol} (A-)} /pin3 (A1) /pin4 (B1) /pin5 (A2) /pin6 (B2) /pin7 (A3) /pin8 (B3) /pin9 (A4) /pin10 (B4) /pin11 (Y4) /pin12 (Y3) /pin13 (Y2) /pin14 (Gnd) /pin15 (Y1) /pin16 (Y5) /pin17 (Y6) /pin18 (Y7) /pin19 (Y8) /pin20 (B8) /pin21 (A8) /pin22 (B7) /pin23 (A7) /pin24 (B6) /pin25 (A6) /pin26 (B5) /pin27 (A5) /pin28 (Vcc) >> Template28
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74606 Template28
+
+/dil_74606 {
+<</@index (?) /pkg (DIP28) >> begingate
+1.00 0 0 0 << /gate (74606) /title {(state) {CR} (latch 3-) {CR} (multiplexed) {CR} (glitch-free) {CR} (8 2-input)} /@index @index /pkg pkg /pin1 (Clk) /pin2 {(B) {ol} (A-)} /pin3 (A1) /pin4 (B1) /pin5 (A2) /pin6 (B2) /pin7 (A3) /pin8 (B3) /pin9 (A4) /pin10 (B4) /pin11 (Y4) /pin12 (Y3) /pin13 (Y2) /pin14 (Gnd) /pin15 (Y1) /pin16 (Y5) /pin17 (Y6) /pin18 (Y7) /pin19 (Y8) /pin20 (B8) /pin21 (A8) /pin22 (B7) /pin23 (A7) /pin24 (B6) /pin25 (A6) /pin26 (B5) /pin27 (A5) /pin28 (Vcc) >> Template28
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74607 Template28
+
+/dil_74607 {
+<</@index (?) /pkg (DIP28) >> begingate
+1.00 0 0 0 << /gate (74607) /title {(latch OC) {CR} (multiplexed) {CR} (glitch-free) {CR} (8 2-input)} /@index @index /pkg pkg /pin1 (Clk) /pin2 {(B) {ol} (A-)} /pin3 (A1) /pin4 (B1) /pin5 (A2) /pin6 (B2) /pin7 (A3) /pin8 (B3) /pin9 (A4) /pin10 (B4) /pin11 (Y4) /pin12 (Y3) /pin13 (Y2) /pin14 (Gnd) /pin15 (Y1) /pin16 (Y5) /pin17 (Y6) /pin18 (Y7) /pin19 (Y8) /pin20 (B8) /pin21 (A8) /pin22 (B7) /pin23 (A7) /pin24 (B6) /pin25 (A6) /pin26 (B5) /pin27 (A5) /pin28 (Vcc) >> Template28
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74620 Template20
+
+/dil_74620 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74620) /title {(3-state) {CR} (tranceivers) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (GAB) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(GBA) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74621 Template20
+
+/dil_74621 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74621) /title {(OC) {CR} (tranceivers) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (GAB) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(GBA) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74623 Template20
+
+/dil_74623 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74623) /title {(3-state) {CR} (tranceivers) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (GAB) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(GBA) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74624 Template14
+
+/dil_74624 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74624) /title {(output) {CR} (complement) {CR} (and) {CR} (w. enable) {CR} (oscillator) {CR} (controlled) {CR} (voltage)} /@index @index /pkg pkg /pin1 (Osc-Gnd) /pin2 (RNG) /pin3 (CX1) /pin4 (CX2) /pin5 {(En) {ol}} /pin6 (Y) /pin7 (Gnd) /pin8 (Z) /pin9 (Vcc) /pin10 (NC) /pin11 (NC) /pin12 (NC) /pin13 (FreqCont) /pin14 (Osc-Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74625 Template16
+
+/dil_74625 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74625) /title {(output) {CR} (complement) {CR} (w.) {CR} (oscillator) {CR} (controlled) {CR} (2 voltage)} /@index @index /pkg pkg /pin1 (Gnd) /pin2 (1Z) /pin3 (1Y) /pin4 (1CX1) /pin5 (1CX2) /pin6 (1FC) /pin7 (1Osc-Vcc) /pin8 (1Osc-Gnd) /pin9 (2Osc-Gnd) /pin10 (2Osc-Vcc) /pin11 (2FC) /pin12 (2CX2) /pin13 (2CX1) /pin14 (2Y) /pin15 (2Z) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74626 Template16
+
+/dil_74626 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74626) /title {(output) {CR} (complement) {CR} (and) {CR} (w. enable) {CR} (oscillator) {CR} (controlled) {CR} (2 voltage)} /@index @index /pkg pkg /pin1 (Gnd) /pin2 (1Z) /pin3 (1Y) /pin4 {(1EN) {ol}} /pin5 (1CX1) /pin6 (1CX2) /pin7 (Osc-Vcc) /pin8 (Osc-Gnd) /pin9 (1FC) /pin10 (2FC) /pin11 (2CX2) /pin12 (2CX1) /pin13 {(2EN) {ol}} /pin14 (2Y) /pin15 (2Z) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74627 Template14
+
+/dil_74627 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74627) /title {(oscillator) {CR} (controlled) {CR} (2 voltage)} /@index @index /pkg pkg /pin1 (1Osc-Vcc) /pin2 (1FC) /pin3 (1CX1) /pin4 (1CX2) /pin5 (1Osc-Gnd) /pin6 (1Y) /pin7 (Gnd) /pin8 (2Y) /pin9 (2Osc-Gnd) /pin10 (2CX2) /pin11 (2CX1) /pin12 (2FC) /pin13 (2Osc-Vcc) /pin14 (Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74628 Template14
+
+/dil_74628 {
+<</@index (?) /pkg (DIP14) >> begingate
+1.00 0 0 0 << /gate (74628) /title {(output) {CR} (complement) {CR} (and) {CR} (w. enable) {CR} (oscillator) {CR} (controlled) {CR} (voltage)} /@index @index /pkg pkg /pin1 (Osc-Gnd) /pin2 (RNG) /pin3 (CX1) /pin4 (CX2) /pin5 {(EN) {ol}} /pin6 (Y) /pin7 (Gnd) /pin8 (Z) /pin9 (Vcc) /pin10 (NC) /pin11 (RX) /pin12 (RX) /pin13 (FC) /pin14 (Osc-Vcc) >> Template14
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(8) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+endgate
+} def
+
+
+% Depend dil_74629 Template16
+
+/dil_74629 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74629) /title {(w. enable) {CR} (oscillator) {CR} (2 controlled)} /@index @index /pkg pkg /pin1 (2FC) /pin2 (1FC) /pin3 (1RNG) /pin4 (1CX1) /pin5 (1CX2) /pin6 {(1EN) {ol}} /pin7 (1Y) /pin8 (Osc-Gnd) /pin9 (Gnd) /pin10 (2Y) /pin11 {(2EN) {ol}} /pin12 (2CX1) /pin13 (2CX2) /pin14 (2RNG) /pin15 (Osc-Vcc) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74630 Template28
+
+/dil_74630 {
+<</@index (?) /pkg (DIP28) >> begingate
+1.00 0 0 0 << /gate (74630) /title {(3-state) {CR} (correction) {CR} (detection/) {CR} (error) {CR} (parallel) {CR} (16bit)} /@index @index /pkg pkg /pin1 (DEF) /pin2 (DB0) /pin3 (DB1) /pin4 (DB2) /pin5 (DB3) /pin6 (DB4) /pin7 (DB5) /pin8 (DB6) /pin9 (DB7) /pin10 (DB8) /pin11 (DB9) /pin12 (DB10) /pin13 (DB11) /pin14 (Gnd) /pin15 (DB12) /pin16 (DB13) /pin17 (DB14) /pin18 (DB15) /pin19 (CB5) /pin20 (CB4) /pin21 (CB3) /pin22 (CB2) /pin23 (CB1) /pin24 (CB0) /pin25 (S0) /pin26 (S1) /pin27 (SEF) /pin28 (Vcc) >> Template28
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74631 Template28
+
+/dil_74631 {
+<</@index (?) /pkg (DIP28) >> begingate
+1.00 0 0 0 << /gate (74631) /title {(OC) {CR} (correction) {CR} (detection/) {CR} (error) {CR} (parallel) {CR} (16bit)} /@index @index /pkg pkg /pin1 (DEF) /pin2 (DB0) /pin3 (DB1) /pin4 (DB2) /pin5 (DB3) /pin6 (DB4) /pin7 (DB5) /pin8 (DB6) /pin9 (DB7) /pin10 (DB8) /pin11 (DB9) /pin12 (DB10) /pin13 (DB11) /pin14 (Gnd) /pin15 (DB12) /pin16 (DB13) /pin17 (DB14) /pin18 (DB15) /pin19 (CB5) /pin20 (CB4) /pin21 (CB3) /pin22 (CB2) /pin23 (CB1) /pin24 (CB0) /pin25 (S0) /pin26 (S1) /pin27 (SEF) /pin28 (Vcc) >> Template28
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 864 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 800 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(13) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(14) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(25) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(26) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+(27) {/Helvetica cf} 2 20 0 1.00 224 800 pinlabel
+(28) {/Helvetica cf} 2 20 0 1.00 224 864 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74636 Template20
+
+/dil_74636 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74636) /title {(3-state) {CR} (correction) {CR} (detection/) {CR} (error) {CR} (parallel) {CR} (8bit)} /@index @index /pkg pkg /pin1 (DEF) /pin2 (DB0) /pin3 (DB1) /pin4 (DB2) /pin5 (DB3) /pin6 (DB4) /pin7 (DB5) /pin8 (DB6) /pin9 (Db7) /pin10 (Gnd) /pin11 (CB4) /pin12 (NC) /pin13 (CB3) /pin14 (CB2) /pin15 (CB1) /pin16 (CB0) /pin17 (S0) /pin18 (S1) /pin19 (SEF) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74637 Template20
+
+/dil_74637 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74637) /title {(OC) {CR} (correction) {CR} (detection/) {CR} (error) {CR} (parallel) {CR} (8bit)} /@index @index /pkg pkg /pin1 (DEF) /pin2 (DB0) /pin3 (DB1) /pin4 (DB2) /pin5 (DB3) /pin6 (DB4) /pin7 (DB5) /pin8 (DB6) /pin9 (Db7) /pin10 (Gnd) /pin11 (CB4) /pin12 (NC) /pin13 (CB3) /pin14 (CB2) /pin15 (CB1) /pin16 (CB0) /pin17 (S0) /pin18 (S1) /pin19 (SEF) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74638 Template20
+
+/dil_74638 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74638) /title {(output) {CR} (state B-) {CR} (output, 3-) {CR} (OC A-) {CR} (tranceiver) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74639 Template20
+
+/dil_74639 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74639) /title {(output) {CR} (state B-) {CR} (output, 3-) {CR} (OC A-) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(G) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74640 Template20
+
+/dil_74640 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74640) /title {(logic) {CR} (inverting) {CR} (3-state w.) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(EN) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74641 Template20
+
+/dil_74641 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74641) /title {(OC) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(EN) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74642 Template20
+
+/dil_74642 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74642) /title {(logic) {CR} (inverting) {CR} (OC w.) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(EN) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74644 Template20
+
+/dil_74644 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74644) /title {(logic) {CR} (normal) {CR} (inverting/) {CR} (OC w.) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(EN) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74645 Template20
+
+/dil_74645 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74645) /title {(3-state) {CR} (tranceiver) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (DIR) /pin2 (A1) /pin3 (A2) /pin4 (A3) /pin5 (A4) /pin6 (A5) /pin7 (A6) /pin8 (A7) /pin9 (A8) /pin10 (Gnd) /pin11 (B8) /pin12 (B7) /pin13 (B6) /pin14 (B5) /pin15 (B4) /pin16 (B3) /pin17 (B2) /pin18 (B1) /pin19 {(EN) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74646 Template24
+
+/dil_74646 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74646) /title {(state) {CR} (register 3-) {CR} (tranceiver/) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (DIR) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(G) {ol}} /pin22 (SBA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74647 Template24
+
+/dil_74647 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74647) /title {(register OC) {CR} (tranceiver/) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (DIR) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(G) {ol}} /pin22 (SBA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74648 Template24
+
+/dil_74648 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74648) /title {(state) {CR} (register 3-) {CR} (tranceiver/) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (DIR) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(G) {ol}} /pin22 (SBA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74649 Template24
+
+/dil_74649 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74649) /title {(register OC) {CR} (tranceiver/) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (DIR) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(G) {ol}} /pin22 (SBA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74651 Template24
+
+/dil_74651 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74651) /title {(output) {CR} (state B-) {CR} (output, 3-) {CR} (state A-) {CR} (register 3-) {CR} (tranceiver/) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (GAB) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(GBA) {ol}} /pin22 (SA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74652 Template24
+
+/dil_74652 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74652) /title {(output) {CR} (state B-) {CR} (output, 3-) {CR} (state A-) {CR} (register 3-) {CR} (tranceiver/) {CR} (8 bus)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (GAB) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(GBA) {ol}} /pin22 (SA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74653 Template24
+
+/dil_74653 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74653) /title {(output) {CR} (state B-) {CR} (A-output, 3-) {CR} (register OC) {CR} (tranceiver/) {CR} (bus) {CR} (8 inverting)} /@index @index /pkg pkg /pin1 (CAB) /pin2 (SAB) /pin3 (GAB) /pin4 (A1) /pin5 (A2) /pin6 (A3) /pin7 (A4) /pin8 (A5) /pin9 (A6) /pin10 (A7) /pin11 (A8) /pin12 (Gnd) /pin13 (B8) /pin14 (B7) /pin15 (B6) /pin16 (B5) /pin17 (B4) /pin18 (B3) /pin19 (B2) /pin20 (B1) /pin21 {(GBA) {ol}} /pin22 (SA) /pin23 (CBA) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74668 Template16
+
+/dil_74668 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74668) /title {(counter) {CR} (down) {CR} (decade up/) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 {(ENT) {ol}} /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 {(RCO) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74669 Template16
+
+/dil_74669 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74669) /title {(counter) {CR} (down) {CR} (binary up/) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (Clk) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 (Gnd) /pin9 {(Load) {ol}} /pin10 {(ENT) {ol}} /pin11 (Qd) /pin12 (Qc) /pin13 (Qb) /pin14 (Qa) /pin15 {(RCO) {ol}} /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74670 Template16
+
+/dil_74670 {
+<</@index (?) /pkg (DIP16) >> begingate
+1.00 0 0 0 << /gate (74670) /title {(state) {CR} (file 3-) {CR} (register) {CR} (4-by-4)} /@index @index /pkg pkg /pin1 (D2) /pin2 (D3) /pin3 (D4) /pin4 (Rb) /pin5 (Ra) /pin6 (Q4) /pin7 (Q3) /pin8 (Gnd) /pin9 (Q2) /pin10 (Q1) /pin11 {(Gr) {ol}} /pin12 {(Gw) {ol}} /pin13 (Wb) /pin14 (Wa) /pin15 (D1) /pin16 (Vcc) >> Template16
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(9) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(10) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(15) {/Helvetica cf} 2 20 360 1.00 224 416 pinlabel
+(16) {/Helvetica cf} 2 20 360 1.00 224 480 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74671 Template20
+
+/dil_74671 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74671) /title {(clear) {CR} (direct) {CR} (state w.) {CR} (latch 3-) {CR} (register/) {CR} (shift) {CR} (universal) {CR} (4bit)} /@index @index /pkg pkg /pin1 (Ser-R) /pin2 (SRCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (Ser-L) /pin8 {(SRClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(S) {ol} (R-)} /pin12 {(G) {ol}} /pin13 (S1) /pin14 (S0) /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 (CASC) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74672 Template20
+
+/dil_74672 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74672) /title {(sync. clear) {CR} (state w.) {CR} (latch 3-) {CR} (register/) {CR} (shift) {CR} (universal) {CR} (4bit)} /@index @index /pkg pkg /pin1 (Ser-R) /pin2 (SRCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (Ser-L) /pin8 {(SRClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(S) {ol} (R-)} /pin12 {(G) {ol}} /pin13 (S1) /pin14 (S0) /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 (CASC) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74673 Template24
+
+/dil_74673 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74673) /title {(out) {CR} (parallel) {CR} (16bit) {CR} (register w.) {CR} (16bit shift)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (SH-Clk) /pin3 {(W) {ol} (R-)} /pin4 {(StrClr) {ol}} /pin5 (Mode-StrClr) /pin6 (SER/Q15) /pin7 (Y0) /pin8 (Y1) /pin9 (Y2) /pin10 (Y3) /pin11 (Y4) /pin12 (Gnd) /pin13 (Y5) /pin14 (Y6) /pin15 (Y7) /pin16 (Y8) /pin17 (Y9) /pin18 (Y10) /pin19 (Y11) /pin20 (Y12) /pin21 (Y13) /pin22 (Y14) /pin23 (Y15) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74674 Template24
+
+/dil_74674 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74674) /title {(parallel in) {CR} (16bit) {CR} (register w.) {CR} (16bit shift)} /@index @index /pkg pkg /pin1 {(CS) {ol}} /pin2 (Clk) /pin3 {(W) {ol} (R-)} /pin4 (NC) /pin5 (Mode) /pin6 (SER/Q15) /pin7 (P0) /pin8 (P1) /pin9 (P2) /pin10 (P3) /pin11 (P4) /pin12 (Gnd) /pin13 (P5) /pin14 (P6) /pin15 (P7) /pin16 (P8) /pin17 (P9) /pin18 (P10) /pin19 (P11) /pin20 (P12) /pin21 (P13) /pin22 (P14) /pin23 (P15) /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74681 Template20
+
+/dil_74681 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74681) /title {(accumulator) {CR} (binary) {CR} (parallel) {CR} (4bit)} /@index @index /pkg pkg /pin1 (Clk) /pin2 (RS2) /pin3 (RS1) /pin4 (RS0) /pin5 (LI-RO) /pin6 (Cn) /pin7 {(G) {ol}} /pin8 (Cn+4) /pin9 {(P) {ol}} /pin10 (Gnd) /pin11 (I-O3) /pin12 (I-O2) /pin13 (I-O1) /pin14 (I-O0) /pin15 (M) /pin16 (AS2) /pin17 (AS1) /pin18 (AS0) /pin19 (RI-LO) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74682 Template20
+
+/dil_74682 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74682) /title {(pull-up) {CR} (w. input) {CR} (comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74683 Template20
+
+/dil_74683 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74683) /title {(pull-up) {CR} (OC w. input) {CR} (comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74684 Template20
+
+/dil_74684 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74684) /title {(comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74685 Template20
+
+/dil_74685 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74685) /title {(OC) {CR} (comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74686 Template24
+
+/dil_74686 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74686) /title {(w. enable) {CR} (comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 {(G1) {ol}} /pin3 (P0) /pin4 (Q0) /pin5 (P1) /pin6 (Q1) /pin7 (NC) /pin8 (P2) /pin9 (Q2) /pin10 (P3) /pin11 (Q3) /pin12 (Gnd) /pin13 (P4) /pin14 (Q4) /pin15 (P5) /pin16 (Q5) /pin17 (P6) /pin18 (Q6) /pin19 (NC) /pin20 (P7) /pin21 (Q7) /pin22 {(P=Q) {ol}} /pin23 {(G2) {ol}} /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74687 Template24
+
+/dil_74687 {
+<< /@index (?) /pkg (DIP24) >> begingate
+1.00 0 0 0 << /gate (74687) /title {(enable) {CR} (OC w.) {CR} (comperator) {CR} (magnitute) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(P\>Q) {ol}} /pin2 {(G1) {ol}} /pin3 (P0) /pin4 (Q0) /pin5 (P1) /pin6 (Q1) /pin7 (NC) /pin8 (P2) /pin9 (Q2) /pin10 (P3) /pin11 (Q3) /pin12 (Gnd) /pin13 (P4) /pin14 (Q4) /pin15 (P5) /pin16 (Q5) /pin17 (P6) /pin18 (Q6) /pin19 (NC) /pin20 (P7) /pin21 (Q7) /pin22 {(P=Q) {ol}} /pin23 {(G2) {ol}} /pin24 (Vcc) >> Template24
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 736 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 672 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(11) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(12) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(21) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(22) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+(23) {/Helvetica cf} 2 20 0 1.00 224 672 pinlabel
+(24) {/Helvetica cf} 2 20 0 1.00 224 736 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74688 Template20
+
+/dil_74688 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74688) /title {(comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74689 Template20
+
+/dil_74689 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74689) /title {(OC) {CR} (comperator) {CR} (identity) {CR} (8bit)} /@index @index /pkg pkg /pin1 {(G) {ol}} /pin2 (P0) /pin3 (Q0) /pin4 (P1) /pin5 (Q1) /pin6 (P2) /pin7 (Q2) /pin8 (P3) /pin9 (Q3) /pin10 (Gnd) /pin11 (P4) /pin12 (Q4) /pin13 (P5) /pin14 (Q5) /pin15 (P6) /pin16 (Q6) /pin17 (P7) /pin18 (Q7) /pin19 {(P=Q) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74690 Template20
+
+/dil_74690 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74690) /title {(state) {CR} (register 3-) {CR} (output) {CR} (clear,) {CR} (direct) {CR} (counter w.) {CR} (decade) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(CClr) {ol}} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 {(RClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 (ENT) /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 (RCO) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74691 Template20
+
+/dil_74691 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74691) /title {(state) {CR} (register 3-) {CR} (output) {CR} (clear,) {CR} (direct) {CR} (counter w.) {CR} (binary) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(CClr) {ol}} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 {(RClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 (ENT) /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 (RCO) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74693 Template20
+
+/dil_74693 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74693) /title {(state) {CR} (register 3-) {CR} (output) {CR} (clear,) {CR} (sync.) {CR} (counter w.) {CR} (binary) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(CClr) {ol}} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 (ENP) /pin8 {(RClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 (ENT) /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 (RCO) /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74696 Template20
+
+/dil_74696 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74696) /title {(state) {CR} (clear 3-) {CR} (direct) {CR} (counter w.) {CR} (decade) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 {(CClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 {(ENT) {ol}} /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 {(RCO) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74697 Template20
+
+/dil_74697 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74697) /title {(state) {CR} (clear 3-) {CR} (direct) {CR} (counter w.) {CR} (binary) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 {(CClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 {(ENT) {ol}} /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 {(RCO) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+% Depend dil_74699 Template20
+
+/dil_74699 {
+<</@index (?) /pkg (DIP20) >> begingate
+1.00 0 0 0 << /gate (74699) /title {(3-state) {CR} (sync. clear) {CR} (counter w.) {CR} (binary) {CR} (synchronous) {CR} (4bit)} /@index @index /pkg pkg /pin1 {(D) {ol} (U-)} /pin2 (CCK) /pin3 (A) /pin4 (B) /pin5 (C) /pin6 (D) /pin7 {(ENP) {ol}} /pin8 {(CClr) {ol}} /pin9 (RCK) /pin10 (Gnd) /pin11 {(C) {ol} (R-)} /pin12 {(G) {ol}} /pin13 {(Load) {ol}} /pin14 {(ENT) {ol}} /pin15 (Qd) /pin16 (Qc) /pin17 (Qb) /pin18 (Qa) /pin19 {(RCO) {ol}} /pin20 (Vcc) >> Template20
+1.000 0.000 0.000 scb
+(1) {/Helvetica cf} 2 23 0 1.00 -224 608 pinlabel
+(2) {/Helvetica cf} 2 23 0 1.00 -224 544 pinlabel
+(3) {/Helvetica cf} 2 23 0 1.00 -224 480 pinlabel
+(4) {/Helvetica cf} 2 23 0 1.00 -224 416 pinlabel
+(5) {/Helvetica cf} 2 23 0 1.00 -224 352 pinlabel
+(6) {/Helvetica cf} 2 23 0 1.00 -224 288 pinlabel
+(7) {/Helvetica cf} 2 23 0 1.00 -224 224 pinlabel
+(8) {/Helvetica cf} 2 23 0 1.00 -224 160 pinlabel
+(9) {/Helvetica cf} 2 23 0 1.00 -224 96 pinlabel
+(10) {/Helvetica cf} 2 23 0 1.00 -224 32 pinlabel
+(11) {/Helvetica cf} 2 20 0 1.00 224 32 pinlabel
+(12) {/Helvetica cf} 2 20 0 1.00 224 96 pinlabel
+(13) {/Helvetica cf} 2 20 0 1.00 224 160 pinlabel
+(14) {/Helvetica cf} 2 20 0 1.00 224 224 pinlabel
+(15) {/Helvetica cf} 2 20 0 1.00 224 288 pinlabel
+(16) {/Helvetica cf} 2 20 0 1.00 224 352 pinlabel
+(17) {/Helvetica cf} 2 20 0 1.00 224 416 pinlabel
+(18) {/Helvetica cf} 2 20 0 1.00 224 480 pinlabel
+(19) {/Helvetica cf} 2 20 0 1.00 224 544 pinlabel
+(20) {/Helvetica cf} 2 20 0 1.00 224 608 pinlabel
+0.180 0.545 0.341 scb
+mark @index (pcb:U) {/Helvetica cf} ctmk 21 0 1.00 0 -32 infolabel
+1.000 0.000 0.000 scb
+endgate
+} def
+
+
+% EndLib
diff --git a/lib/signal.lps b/lib/signal.lps
new file mode 100644
index 0000000..4790230
--- /dev/null
+++ b/lib/signal.lps
@@ -0,0 +1,67 @@
+%! PostScript set of library objects for XCircuit
+% Version: 3.2
+% Library name is: signal
+% Author: R. Timothy Edwards <tim@opencircuitdesign.com>
+%
+
+% Depend sum circle2
+% Depend times circle2
+% Depend delta square
+% Depend integrate square
+% Depend integ2 square
+
+% XCircuitLib library objects
+/triangle {
+begingate
+0 1.35 -32 36 32 0 -32 -36 3 polygon
+endgate
+} def
+
+/square {
+begingate
+0 1.35 -32 -32 -32 32 32 32 32 -32 4 polygon
+endgate
+} def
+
+/circle2 {
+begingate
+1 1.35 0 0 32 0.00 360.00 xcarc
+endgate
+} def
+
+/sum {
+begingate
+(S) {/Symbol cf} 2 21 0 1.30 0 0 label
+1.00 0 0 0 circle2
+endgate
+} def
+
+/times {
+begingate
+1.00 0 0 0 circle2
+(\264) {/Symbol cf} 2 21 0 1.75 2 4 label
+endgate
+} def
+
+/delta {
+begingate
+1.00 0 0 0 square
+(D) {/Symbol cf} 2 21 0 1.30 0 0 label
+endgate
+} def
+
+/integrate {
+begingate
+1.00 0 0 0 square
+(s) {/Symbol cf} 2 21 0 1.30 0 0 label
+endgate
+} def
+
+/integ2 {
+begingate
+1.00 0 0 0 square
+(\362) {/Symbol cf} 2 21 0 1.30 0 -2 label
+endgate
+} def
+
+% EndLib
diff --git a/lib/standard_cells.cir b/lib/standard_cells.cir
new file mode 100644
index 0000000..73d2aff
--- /dev/null
+++ b/lib/standard_cells.cir
@@ -0,0 +1,108 @@
+* standard_cells.cir, netlists for verifying standard cells
+* Conrad Ziesler and Tim Edwards, MultiGiG, Inc.
+* Standard cells are from the IIT standard cell library.
+
+.subckt MUX2X1 vdd gnd A B Y S
+M1 x1 A gnd gnd nfet l=180n w=1.80u m=1
+M2 x2 A vdd vdd pfet l=180n w=3.60u m=1
+M3 x2 S Y vdd pfet l=180n w=3.60u m=1
+M4 x1 sbar Y gnd nfet l=180n w=1.80u m=1
+M5 sbar S vdd vdd pfet l=180n w=1.80u m=1
+M6 sbar S gnd gnd nfet l=180n w=0.90u m=1
+M7 Y sbar x3 vdd pfet l=180n w=3.60u m=1
+M8 Y S x4 gnd nfet l=180n w=1.80u m=1
+M9 x3 B vdd vdd pfet l=180n w=3.60u m=1
+M10 x4 B gnd gnd nfet l=180n w=1.80u m=1
+.ends
+
+.subckt TBUFX2 vdd gnd A Y En
+M1 enb En gnd gnd nfet l=180n w=1.80u m=1
+M2 enb En vdd vdd pfet l=180n w=3.60u m=1
+M4 i A vdd vdd pfet l=180n w=3.60u m=2
+M3 i enb Y vdd pfet l=180n w=3.60u m=2
+M5 j En Y gnd nfet l=180n w=1.80u m=2
+M6 j A gnd gnd nfet l=180n w=1.80u m=2
+.ends
+
+.subckt BUFX4 vdd gnd A Y
+M1 x A gnd gnd nfet l=180n w=1.35u m=1
+M2 x A vdd vdd pfet l=180n w=2.70u m=1
+M3 Y x gnd gnd nfet l=180n w=1.80u m=2
+M4 Y x vdd vdd pfet l=180n w=3.60u m=2
+.ends
+
+.subckt BUFX2 vdd gnd A Y
+M1 x A gnd gnd nfet l=180n w=0.90u m=1
+M2 x A vdd vdd pfet l=180n w=1.80u m=1
+M3 Y x gnd gnd nfet l=180n w=1.80u m=1
+M4 Y x vdd vdd pfet l=180n w=3.60u m=1
+.ends
+
+.subckt INVX1 vdd gnd A Y
+M1 Y A gnd gnd nfet l=180n w=0.90u m=1
+M2 Y A vdd vdd pfet l=180n w=1.80u m=1
+.ends
+
+.subckt INVX2 vdd gnd A Y
+M1 Y A gnd gnd nfet l=180n w=1.80u m=1
+M2 Y A vdd vdd pfet l=180n w=3.60u m=1
+.ends
+
+.subckt NOR2X1 vdd gnd A B Y
+M1 Y A gnd gnd nfet l=180n w=0.90u m=1
+M2 Y B gnd gnd nfet l=180n w=0.90u m=1
+M3 x1 A vdd vdd pfet l=180n w=3.60u m=1
+M4 Y B x1 vdd pfet l=180n w=3.60u m=1
+.ends
+
+.subckt NOR3X1 vdd gnd A B C Y
+M1 Y A gnd gnd nfet l=180n w=0.90u m=1
+M2 Y B gnd gnd nfet l=180n w=0.90u m=1
+M3 Y C gnd gnd nfet l=180n w=0.90u m=1
+M4 x1 A vdd vdd pfet l=180n w=2.70u m=2
+M5 x2 B x1 vdd pfet l=180n w=2.70u m=2
+M6 Y C x2 vdd pfet l=180n w=2.70u m=2
+.ends
+
+.subckt NAND2X1 vdd gnd A B Y
+M1 x1 A gnd gnd nfet l=180n w=1.80u m=1
+M2 Y B x1 gnd nfet l=180n w=1.80u m=1
+M3 Y A vdd vdd pfet l=180n w=1.80u m=1
+M4 Y B vdd vdd pfet l=180n w=1.80u m=1
+.ends
+
+.subckt NAND3X1 vdd gnd A B C Y
+M1 x1 A gnd gnd nfet l=180n w=2.70u m=1
+M2 x2 B x1 gnd nfet l=180n w=2.70u m=1
+M3 Y C x2 gnd nfet l=180n w=2.70u m=1
+M4 Y A vdd vdd pfet l=180n w=1.80u m=1
+M5 Y B vdd vdd pfet l=180n w=1.80u m=1
+M6 Y C vdd vdd pfet l=180n w=1.80u m=1
+.ends
+
+.subckt OR2X1 vdd gnd A B Y
+M1 x2 A gnd gnd nfet l=180n w=0.90u m=1
+M2 x2 B gnd gnd nfet l=180n w=0.90u m=1
+M3 x1 B vdd vdd pfet l=180n w=3.60u m=1
+M4 x2 A x1 vdd pfet l=180n w=3.60u m=1
+M5 Y x2 gnd gnd nfet l=180n w=0.90u m=1
+M6 Y x2 vdd vdd pfet l=180n w=1.80u m=1
+.ends
+
+.subckt LATCH vdd gnd CLK D Q
+M1 cb CLK gnd gnd nfet l=180n w=0.90u m=2
+M2 cb CLK vdd vdd pfet l=180n w=0.90u m=4
+
+M3 x2 D vdd vdd pfet l=180n w=0.90u m=2
+M4 qb cb x2 vdd pfet l=180n w=0.90u m=2
+M5 x4 D gnd gnd nfet l=180n w=0.90u m=1
+M6 qb CLK x4 gnd nfet l=180n w=0.90u m=1
+
+M7 x5 Q vdd vdd pfet l=180n w=0.90u m=1
+M8 qb CLK x5 vdd pfet l=180n w=0.90u m=1
+M9 x7 Q gnd gnd nfet l=180n w=0.90u m=1
+M10 qb cb x7 gnd nfet l=180n w=0.90u m=1
+
+M11 Q qb gnd gnd nfet l=180n w=0.90u m=2
+M12 Q qb vdd vdd pfet l=180n w=0.90u m=4
+.ends
diff --git a/lib/standard_cells_3V.cir b/lib/standard_cells_3V.cir
new file mode 100644
index 0000000..145cb85
--- /dev/null
+++ b/lib/standard_cells_3V.cir
@@ -0,0 +1,109 @@
+* standard_cells_3V.cir, netlists for verifying standard cells
+*
+* Conrad Ziesler and Tim Edwards, MultiGiG, Inc., 2005
+* Standard cells are from the IIT standard cell library.
+*
+* These cells have been modified for operation at 3.3V in a
+* nominally 1.8V process (generally, 0.18um feature size),
+* using thick oxide implant.
+
+.subckt BUFX4_3V vdd gnd A Y
+M1 x A gnd gnd nhv l=360n w=1.35u m=1
+M2 x A vdd vdd phv l=360n w=2.70u m=1
+M3 Y x gnd gnd nhv l=360n w=1.80u m=2
+M4 Y x vdd vdd phv l=360n w=3.60u m=2
+.ends
+
+.subckt BUFX2_3V vdd gnd A Y
+M1 x A gnd gnd nhv l=360n w=0.90u m=1
+M2 x A vdd vdd phv l=360n w=1.80u m=1
+M3 Y x gnd gnd nhv l=360n w=1.80u m=1
+M4 Y x vdd vdd phv l=360n w=3.60u m=1
+.ends
+
+.subckt INVX1_3V vdd gnd A Y
+M1 Y A gnd gnd nhv l=360n w=0.90u m=1
+M2 Y A vdd vdd phv l=360n w=1.80u m=1
+.ends
+
+.subckt NOR2X1_3V vdd gnd A B Y
+M1 Y A gnd gnd nhv l=360n w=0.90u m=1
+M2 Y B gnd gnd nhv l=360n w=0.90u m=1
+M3 x1 A vdd vdd phv l=360n w=3.60u m=1
+M4 Y B x1 vdd phv l=360n w=3.60u m=1
+.ends
+
+.subckt NOR4X1_3V vdd gnd A B C D Y
+M1 Y A gnd gnd nhv l=360n w=0.90u m=1
+M2 Y B gnd gnd nhv l=360n w=0.90u m=1
+M3 Y C gnd gnd nhv l=360n w=0.90u m=1
+M4 Y D gnd gnd nhv l=360n w=0.90u m=1
+M5 x1 A vdd vdd phv l=360n w=2.70u m=2
+M6 x2 B x1 vdd phv l=360n w=2.70u m=2
+M7 x3 C x2 vdd phv l=360n w=2.70u m=2
+M8 Y D x3 vdd phv l=360n w=2.70u m=2
+.ends
+
+.subckt NOR3X1_3V vdd gnd A B C Y
+M1 Y A gnd gnd nhv l=360n w=0.90u m=1
+M2 Y B gnd gnd nhv l=360n w=0.90u m=1
+M3 Y C gnd gnd nhv l=360n w=0.90u m=1
+M4 x1 A vdd vdd phv l=360n w=2.70u m=2
+M5 x2 B x1 vdd phv l=360n w=2.70u m=2
+M6 Y C x2 vdd phv l=360n w=2.70u m=2
+.ends
+
+.subckt NAND2X1_3V vdd gnd A B Y
+M1 x1 A gnd gnd nhv l=360n w=1.80u m=1
+M2 Y B x1 gnd nhv l=360n w=1.80u m=1
+M3 Y A vdd vdd phv l=360n w=1.80u m=1
+M4 Y B vdd vdd phv l=360n w=1.80u m=1
+.ends
+
+.subckt NAND3X1_3V vdd gnd A B C Y
+M1 x1 A gnd gnd nhv l=360n w=1.80u m=1
+M2 x2 B x1 gnd nhv l=360n w=1.80u m=1
+M3 Y C x2 gnd nhv l=360n w=1.80u m=1
+M4 Y A vdd vdd phv l=360n w=2.70u m=1
+M5 Y B vdd vdd phv l=360n w=2.70u m=1
+M6 Y C vdd vdd phv l=360n w=2.70u m=1
+.ends
+
+.subckt NAND4X1_3V vdd gnd A B C D Y
+M1 x1 A gnd gnd nhv l=360n w=1.80u m=1
+M2 x2 B x1 gnd nhv l=360n w=1.80u m=1
+M3 x3 C x2 gnd nhv l=360n w=1.80u m=1
+M4 Y D x3 gnd nhv l=360n w=1.80u m=1
+M5 Y A vdd vdd phv l=360n w=2.70u m=1
+M6 Y B vdd vdd phv l=360n w=2.70u m=1
+M7 Y C vdd vdd phv l=360n w=2.70u m=1
+M8 Y D vdd vdd phv l=360n w=2.70u m=1
+.ends
+
+.subckt OR2X1_3V vdd gnd A B Y
+M1 x2 A gnd gnd nhv l=360n w=0.90u m=1
+M2 x2 B gnd gnd nhv l=360n w=0.90u m=1
+M3 x1 B vdd vdd phv l=360n w=3.60u m=1
+M4 x2 A x1 vdd phv l=360n w=3.60u m=1
+M5 Y x2 gnd gnd nhv l=360n w=0.90u m=1
+M6 Y x2 vdd vdd phv l=360n w=1.80u m=1
+.ends
+
+.subckt LATCH_3V vdd gnd CLK D Q
+M1 cb CLK gnd gnd nhv l=360n w=0.90u m=2
+M2 cb CLK vdd vdd phv l=360n w=0.90u m=4
+
+M3 x2 D vdd vdd phv l=360n w=0.90u m=2
+M4 qb cb x2 vdd phv l=360n w=0.90u m=2
+M5 x4 D gnd gnd nhv l=360n w=0.90u m=1
+M6 qb CLK x4 gnd nhv l=360n w=0.90u m=1
+
+M7 x5 Q vdd vdd phv l=360n w=0.90u m=1
+M8 qb CLK x5 vdd phv l=360n w=0.90u m=1
+M9 x7 Q gnd gnd nhv l=360n w=0.90u m=1
+M10 qb cb x7 gnd nhv l=360n w=0.90u m=1
+
+M11 Q qb gnd gnd nhv l=360n w=0.90u m=2
+M12 Q qb vdd vdd phv l=360n w=0.90u m=4
+.ends
+
diff --git a/lib/startup.script b/lib/startup.script
new file mode 100644
index 0000000..59ea7d3
--- /dev/null
+++ b/lib/startup.script
@@ -0,0 +1,39 @@
+# XCircuit startup script
+# Does the work previously handled by "builtins.lps". Commands
+# "loadlibrary" and "loadfontencoding" should no longer be used.
+#
+# Written by Tim Edwards 12/19/00 (tim@bach.ece.jhu.edu)
+# The Johns Hopkins University
+
+font times_roman.xfe
+font times_romaniso.xfe
+font helvetica.xfe
+font helveticaiso.xfe
+font courier.xfe
+font courieriso.xfe
+font symbol.xfe
+
+# Alternate font encodings: Uncomment these if you want them
+# loaded by default
+#
+# font times_romaniso2.xfe
+# font courieriso2.xfe
+# font helveticaiso2.xfe
+# font times_romaniso5.xfe
+# font courieriso5.xfe
+# font helveticaiso5.xfe
+
+# First library page
+library generic.lps 1
+library analog.lps 1
+library avlsi.lps 1
+library digital.lps 1
+
+# Second library page
+library analoglib2.lps 2
+
+# Third library page
+library ic_templates.lps 3
+
+# Fourth library page
+library quadparts.lps 4
diff --git a/lib/tcl/boot_xcircuit.tcl b/lib/tcl/boot_xcircuit.tcl
new file mode 100644
index 0000000..f422a7d
--- /dev/null
+++ b/lib/tcl/boot_xcircuit.tcl
@@ -0,0 +1,42 @@
+## boot xcircuit within a starkit (replaces bin/xcircuit)
+
+package provide app-xcircuit 3.6.36
+
+# define the source code location
+set XCIRCUIT_SRC_DIR [file join $::starkit::topdir lib app-xcircuit]
+set env(XCIRCUIT_SRC_DIR) $XCIRCUIT_SRC_DIR
+
+# define the library location (outside the starkit)
+#set loclibdir [file join [file dirname $::starkit::topdir] xclib]
+set loclibdir [file join $env(HOME) xclib]
+#set XCIRCUIT_LIB_DIR [file join $loclibdir app-xcircuit]
+set XCIRCUIT_LIB_DIR $loclibdir
+set env(XCIRCUIT_LIB_DIR) $XCIRCUIT_LIB_DIR
+
+# create the library if necessary (usually just the first time)
+if {![file exists $loclibdir]} {
+ file mkdir $loclibdir
+ catch {unset libfiles}
+ # directories
+ lappend libfiles [file join $XCIRCUIT_SRC_DIR app-defaults]
+ lappend libfiles [file join $XCIRCUIT_SRC_DIR fonts]
+ lappend libfiles [file join $XCIRCUIT_SRC_DIR pixmaps]
+ # individual files
+ lappend libfiles [file join $XCIRCUIT_SRC_DIR xcircps2.pro]
+ foreach lf [glob -nocomplain -- [file join $XCIRCUIT_SRC_DIR *.lps]] {
+ lappend libfiles $lf
+ }
+ lappend libfiles [file join $XCIRCUIT_SRC_DIR xcstartup.tcl]
+ #
+ foreach lf $libfiles {
+ file copy $lf $loclibdir
+ }
+ unset libfiles
+}
+
+# start xcircuit thru tkcon w/o args
+source [file join $XCIRCUIT_SRC_DIR tkcon.tcl]
+tkcon main source [file join $XCIRCUIT_SRC_DIR console.tcl]
+tkcon slave slave package require Tk
+tkcon slave slave source [file join $XCIRCUIT_SRC_DIR xcircuit.tcl]
+tkcon slave slave source [file join $XCIRCUIT_SRC_DIR xcstartup.tcl]
diff --git a/lib/tcl/bparams.tcl b/lib/tcl/bparams.tcl
new file mode 100644
index 0000000..55c7198
--- /dev/null
+++ b/lib/tcl/bparams.tcl
@@ -0,0 +1,17 @@
+#--------------------------------------------------------------------------
+# bparams.tcl
+#
+# This Tcl script re-binds Button-3 to bring up the parameter edit
+# popup window when the right mouse button is clicked over a (non-selected)
+# object instance. Otherwise, Button-3 behaves as usual (e.g., deselects
+# selected objects).
+#--------------------------------------------------------------------------
+
+bind .xcircuit.mainframe.mainarea.drawing <ButtonPress-3> { \
+ if {[eventmode] == "normal" && [select get] == {} \
+ && [select here] != {}} {
+ xcircuit::prompteditparams {substring numeric expression}
+ } else {
+ standardaction %b down %s
+ }
+}
diff --git a/lib/tcl/console.tcl b/lib/tcl/console.tcl
new file mode 100644
index 0000000..6bae43c
--- /dev/null
+++ b/lib/tcl/console.tcl
@@ -0,0 +1,20 @@
+# Commands to run in the console prior to launching the
+# slave interpreter for XCircuit
+#
+# Since the TkCon window is not a necessity in XCircuit, we withdraw it
+# but set up commands which can be executed from the slave interpreter
+# that can be used to reinstate the console when necessary (such as
+# when the "%" key macro is typed).
+# (suggested by Joel Kuusk)
+#
+slave alias xcircuit::consoledown wm withdraw .
+slave alias xcircuit::consoleup wm deiconify .
+slave alias xcircuit::consoleontop raise .
+#
+# The setup is that tkcon is the master interpreter and the layout window
+# is the slave interpreter. However, the end-user has the impression that
+# tkcon is a subsidiary window of the layout. Thus, closing the console
+# window should pop down the console rather than forcing an immediate and
+# irrevocable exit from xcircuit.
+
+wm protocol . WM_DELETE_WINDOW {tkcon slave slave xcircuit::lowerconsole}
diff --git a/lib/tcl/edif.tcl b/lib/tcl/edif.tcl
new file mode 100644
index 0000000..c1dc5bc
--- /dev/null
+++ b/lib/tcl/edif.tcl
@@ -0,0 +1,931 @@
+#------------------------------------------------------------------------
+# EDIF file parser for XCircuit
+#------------------------------------------------------------------------
+# Written by Tim Edwards, MultiGiG, Inc., Scotts Valley, CA
+#------------------------------------------------------------------------
+# Revision history:
+# Revision 0: July 18, 2006 by Tim Edwards
+# Revision 1: July 24, 2006 by Jan Sundermeyer
+# Revision 2: July 30, 2006 by Jan Sundermeyer
+# Revision 3: July 31, 2006 by Jan Sundermeyer
+#------------------------------------------------------------------------
+
+set XCOps(module,edif) 1
+
+# "Standard" scaling: converts a typical factors-of-10 coordinate system
+# into XCircuit's factors-of-16 coordinate system (16/10 = 8/5)
+
+set Opts(scalen) 8
+set Opts(scaled) 5
+
+set symbolview {symbol symbolr spectre hspice spectreS}
+set subst_list {}
+
+#------------------------------------------------------------------------
+# EDIF rotations are the reverse of xcircuit rotations.
+#------------------------------------------------------------------------
+
+proc rotinvert {value} {
+ set newvalue [expr 360 - $value]
+ if {$newvalue == 360} {set newvalue 0}
+ return $newvalue
+}
+
+#------------------------------------------------------------------------
+# Scale a point by factor (scalen) / (scaled)
+# "point" is a point in EDIF format: {pt <x> <y>}
+#------------------------------------------------------------------------
+
+proc scalepoint {point} {
+ global Opts
+
+ set xin [lindex $point 1]
+ set yin [lindex $point 2]
+
+ set xout [expr $xin * $Opts(scalen) / $Opts(scaled)]
+ set yout [expr $yin * $Opts(scalen) / $Opts(scaled)]
+
+ return [list $xout $yout]
+}
+
+#------------------------------------------------------------------------
+# Convert arc 3-point form to center-radius-endpoint angles
+# Formula thanks to Yumnam Kirani Singh, found on geocities.com.
+# Saved me from having to work it out for myself.
+#------------------------------------------------------------------------
+
+proc convert_arc {point1 point2 point3} {
+ set x1 [lindex $point1 0]
+ set y1 [lindex $point1 1]
+ set x2 [lindex $point2 0]
+ set y2 [lindex $point2 1]
+ set x3 [lindex $point3 0]
+ set y3 [lindex $point3 1]
+
+ set m11 [expr $x2 * $x2 + $y2 * $y2 - ($x1 * $x1 + $y1 * $y1)]
+ set m21 [expr $y2 - $y1]
+ set m12 [expr $x3 * $x3 + $y3 * $y3 - ($x1 * $x1 + $y1 * $y1)]
+ set m22 [expr $y3 - $y1]
+
+ set n11 [expr $x2 - $x1]
+ set n21 $m11
+ set n12 [expr $x3 - $x1]
+ set n22 $m12
+
+ set d11 $n11
+ set d21 $m21
+ set d12 $n12
+ set d22 $m22
+
+ set absm [expr ($m11 * $m22) - ($m12 * $m21)]
+ set absn [expr ($n11 * $n22) - ($n12 * $n21)]
+ set absd [expr ($d11 * $d22) - ($d12 * $d21)]
+
+ set cx [expr $absm / (2.0 * $absd)]
+ set cy [expr $absn / (2.0 * $absd)]
+
+ set r [expr sqrt(($cx - $x2) * ($cx - $x2) + ($cy - $y2) * ($cy - $y2))]
+
+ set a1 [expr atan2($y1 - $cy, $x1 - $cx)]
+ set a2 [expr atan2($y2 - $cy, $x2 - $cx)]
+ set a3 [expr atan2($y3 - $cy, $x3 - $cx)]
+
+ # To be certain that the end angles are correct, make sure a2 is between
+ # a1 and a3.
+
+ if {($a1 < $a2) && ($a2 > $a3)} {
+ set a3 [expr $a3 + 3.1415927]
+ } elseif {($a1 > $a2) && ($a2 < $a3)} {
+ set a3 [expr $a3 - 3.1415927]
+ }
+
+ set cx [expr round($cx)]
+ set cy [expr round($cy)]
+ set r [expr round($r)]
+ set a1 [expr $a1 * 180 / 3.1415927]
+ set a3 [expr $a3 * 180 / 3.1415927]
+
+ return [list [list $cx $cy] $r $a1 $a3]
+}
+
+#------------------------------------------------------------------------
+# Quiet deselection
+#------------------------------------------------------------------------
+
+proc quiet_deselect {} {
+ set handle [select get]
+ if {$handle != {}} {deselect}
+}
+
+#------------------------------------------------------------------------
+# Parse a "shape" statement
+#------------------------------------------------------------------------
+
+proc parse_shape {elemlist} {
+ set handle {}
+ set shapedata [lindex $elemlist 0]
+ set shapetype [lindex $shapedata 0]
+
+ # Any keywords to handle other than "curve"?
+ switch $shapetype {
+ curve {
+ foreach phrase [lrange $shapedata 1 end] {
+ # Can a curve have any statement other than "arc"?
+ set curveType [lindex $phrase 0]
+ switch $curveType {
+ arc {
+ set pointlist {}
+ foreach point [lrange $phrase 1 end] {
+ lappend pointlist [scalepoint $point]
+ }
+ set xca [eval "convert_arc $pointlist"]
+ set handle [eval "arc make $xca"]
+ }
+ default {puts "Unknown curve type $curveType"}
+ }
+ }
+ }
+ default {puts "Unsupported shape type $shapetype"}
+ }
+ return $handle
+}
+
+#------------------------------------------------------------------------
+# decimal to octal code conversion
+#------------------------------------------------------------------------
+
+proc dec_to_oct {dval} {
+ set oval "\\"
+ set o3 [expr $dval / 64]
+ set r3 [expr $dval % 64]
+ set o2 [expr $r3 / 8]
+ set o1 [expr $r3 % 8]
+ set oval "\\$o3$o2$o1"
+}
+
+#------------------------------------------------------------------------
+# Parse a raw geometry statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_geometry {elemtype elemdata} {
+ global Opts
+
+ quiet_deselect
+ switch $elemtype {
+ openshape -
+ shape {
+ set handle [parse_shape $elemdata]
+ }
+
+ path -
+ polygon {
+ set polydata [lrange [lindex $elemdata 0] 1 end]
+ set pointlist {}
+ foreach point $polydata {
+ lappend pointlist [scalepoint $point]
+ }
+ set numpoints [llength $pointlist]
+ # puts "polygon make $numpoints $pointlist"
+ set handle [eval "polygon make $numpoints $pointlist"]
+ if {"$elemtype" == "polygon"} {
+ element $handle border closed
+ }
+ }
+ rectangle {
+ set pointlist {}
+ foreach point $elemdata {
+ lappend pointlist [scalepoint $point]
+ }
+ # puts "polygon make box $pointlist"
+ set handle [eval "polygon make box $pointlist"]
+ }
+ name -
+ stringDisplay {
+ # Parse various kinds of strings used by Cadence
+ set dstring [lindex $elemdata 0]
+ if {[lindex $dstring 0]== "array"} {
+ set dstring [subst_name [lindex $dstring 1]]
+ } else {
+ set dstring [subst_name $dstring]
+ }
+
+ # Do EDIF-format ASCII escape sequence substitution
+ while {[regexp -- {%([0-9]+)%} $dstring temp code] > 0} {
+ set oval [dec_to_oct $code]
+ regsub -- {%[0-9]+%} $dstring [subst "$oval"] dstring
+ }
+ set handle {}
+ if {[string first "cds" $dstring] == 0} {
+ switch -glob $dstring {
+ cdsName* {set handle [label make normal [object name] {0 0}]}
+ cdsParam* {set handle {}}
+ cdsTerm* {
+ if {[regexp {"(.+)"} $dstring temp pinname] > 0} {
+ set handle [label make pin $pinname {0 0}]
+ } else {
+ set handle [label make pin $dstring {0 0}]
+ }
+ }
+ default {set handle [label make normal $dstring {0 0}]}
+ }
+ set cds 1
+ } else {
+ set cds 0
+ }
+ foreach dparams [lrange $elemdata 1 end] {
+ if {$cds == 0} {
+ quiet_deselect
+ set handle [label make normal $dstring {0 0}]
+ }
+ if {$handle != {}} {
+ foreach dtext $dparams {
+ set dtk [lindex $dtext 0]
+ switch $dtk {
+ justify {
+ set jval [lindex $dtext 1]
+ switch $jval {
+ UPPERRIGHT {
+ label $handle justify top
+ label $handle justify right
+ }
+ CENTERRIGHT {
+ label $handle justify middle
+ label $handle justify right
+ }
+ LOWERRIGHT {
+ label $handle justify bottom
+ label $handle justify right
+ }
+ UPPERCENTER {
+ label $handle justify top
+ label $handle justify center
+ }
+ CENTERCENTER {
+ label $handle justify middle
+ label $handle justify center
+ }
+ LOWERCENTER {
+ label $handle justify bottom
+ label $handle justify center
+ }
+ UPPERLEFT {
+ label $handle justify top
+ label $handle justify left
+ }
+ CENTERLEFT {
+ label $handle justify middle
+ label $handle justify left
+ }
+ LOWERLEFT {
+ label $handle justify bottom
+ label $handle justify left
+ }
+ }
+ }
+ orientation {
+ set oval [lindex $dtext 1]
+ set odeg [string range $oval 1 end]
+ element $handle rotate [rotinvert $odeg]
+ }
+ origin {
+ set plist [lindex $dtext 1]
+ label $handle position [scalepoint $plist]
+ }
+ }
+ }
+ }
+ }
+ }
+ default {
+ puts "Unsupported geometry block keyword $elemtype"
+ set handle {}
+ }
+ }
+ return $handle
+}
+
+#------------------------------------------------------------------------
+# execute substitution of net names
+#------------------------------------------------------------------------
+
+proc subst_name {net} {
+
+ global subst_list
+
+ if {[llength $net] > 1} {
+ if {[lindex $net 0] == "rename"} {
+ lappend subst_list [lrange $net 1 2]
+ return [lindex $net 2]
+ } else {
+ return $net
+ }
+ } else {
+ set pos [lsearch $subst_list "$net *"]
+ if {$pos > -1} {
+ return [lindex [lindex $subst_list $pos] 1]
+ } else {
+ return $net
+ }
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse a "net" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_net {netdata} {
+
+ set netString [lindex $netdata 0]
+
+ if {[llength $netString] > 1} {
+ if {[lindex $netString 0] == "name"} {
+ parse_geometry [lindex $netString 0] [lrange $netString 1 end]
+ } elseif {[lindex $netString 0] == "rename"} {
+ set elemdata [lrange $netString 1 end]
+ if { [llength [lindex $elemdata 1]]>1 } {
+ parse_geometry [lindex [lindex $elemdata 1] 0] [lrange [lindex $elemdata 1] 1 end]
+ }
+ } elseif {[lindex $netString 0] == "array"} {
+ parse_net [list [lindex $netString 1]]
+ } else {
+ puts "Unknown net name $netString"
+ return
+ }
+ }
+
+ foreach phrase [lrange $netdata 1 end] {
+ set keyword [lindex $phrase 0]
+ switch $keyword {
+ joined {
+ # ignore net information (for now)
+ }
+ figure {
+ # Figure types defined in the technology block.
+ set figureType [lindex $phrase 1]
+ set geolist [lindex $phrase 2]
+ parse_geometry [lindex $geolist 0] [lrange $geolist 1 end]
+ }
+ default {puts "Unsupported net block keyword $keyword"}
+ }
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse an "instance" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_instance {instName instdata} {
+ quiet_deselect
+ set handle {}
+ if {[lindex $instName 0] == "array"} {
+ set instName [subst_name [lindex $instName 1]]
+ } else {
+ set instName [subst_name $instName]
+ }
+ foreach phrase $instdata {
+ set keyword [lindex $phrase 0]
+ switch $keyword {
+ viewRef {
+ # Next keyword should be "symbol" or "symbolr"?
+ set objtype [lindex $phrase 1]
+ set instinfo [lindex $phrase 2]
+ # 1st keyword should be "cellRef", 3rd "libraryRef". Ignore these.
+ set cellname [lindex $instinfo 1]
+ # Create the instance
+ if {[catch {set handle [instance make $cellname "0 0"]}]} {
+ puts "ERROR: Attempt to instance non-existant object $cellname"
+ } else {
+ puts "Created instance $instName of $cellname"
+ }
+ }
+ transform {
+ if {$handle == {}} {
+ puts "Error: Transform specified without reference instance"
+ } else {
+ foreach trans [lrange $phrase 1 end] {
+ set trk [lindex $trans 0]
+ switch $trk {
+ orientation {
+ set ogood 0
+ set oval [lindex $trans 1]
+
+ if {[string first "MX" $oval] >= 0} {
+ element $handle flip vertical
+ set ogood 1
+ } elseif {[string first "MY" $oval] >= 0} {
+ element $handle flip horizontal
+ set ogood 1
+ }
+ set rpos [string first "R" $oval]
+ if {$rpos >= 0} {
+ incr rpos
+ element $handle rotate [rotinvert [string range \
+ $oval $rpos end]]
+ set ogood 1
+ }
+ if {$ogood == 0} {
+ puts "Unsupported orientation $oval in transform"
+ }
+ }
+ origin {
+ set plist [lindex $trans 1]
+ instance $handle center [scalepoint $plist]
+ }
+ }
+ }
+ }
+ }
+ property {
+ if {$handle != {}} {
+ push $handle
+ parse_property [lindex $phrase 1] [lrange $phrase 2 end]
+ pop
+ }
+ }
+
+ default {puts "Unsupported instance block keyword $keyword"}
+ }
+ }
+
+ # Set standard parameters idx and class from the instance name
+
+ if {$handle != {}} {
+ push $handle
+ if {[catch {parameter set class [string range $instName 0 0]}]} {
+ if {[catch {parameter set instName $instName}]} {
+ parameter make substring instName ?
+ parameter set instName $instName
+ }
+ } else {
+ parameter set idx [string range $instName 1 end]
+ }
+ pop
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse a "portImplementation" statement
+#------------------------------------------------------------------------
+
+proc parse_port {labellist portdata} {
+
+ set portString [lindex $portdata 0]
+ set plabel {}
+
+ if {[llength $portString] > 1} {
+ if {[lindex $portString 0] == "name"} {
+ set plabel [parse_geometry [lindex $portString 0] [lrange $portString 1 end]]
+ set portName [subst_name [lindex $portString 1]]
+ } else {
+ puts "Unknown portImplementation pin $portString"
+ return
+ }
+ } else {
+ set portName [subst_name $portString]
+ }
+
+ if {$labellist != {}} {
+ foreach llabel $labellist {
+ if {"$portName" == [label $llabel text]} {
+ set plabel $llabel
+ break
+ }
+ }
+ } else {
+ if {$plabel == {}} {
+ quiet_deselect
+ set plabel [label make normal $portName {0 0}]
+ }
+ }
+
+
+ if {$plabel == {}} {
+ puts "Can't determine port name in $portdata"
+ return
+ }
+
+ # If we were not given a label list, then this is a pin on the schematic
+ # and should be converted into a pin.
+
+ if {[label $plabel type] == "normal"} {
+ label $plabel type local
+ }
+
+ foreach portProp [lrange $portdata 1 end] {
+ set portkey [lindex $portProp 0]
+ switch $portkey {
+ figure {
+ set figureType [lindex $portProp 1]
+ set geolist [lindex $portProp 2]
+ parse_geometry [lindex $geolist 0] [lrange $geolist 1 end]
+ }
+ connectLocation {
+ # Expect a (figure pin (dot (pt x y))))
+ # Use the point position to reposition the label.
+ set cpoint [scalepoint [lindex [lindex [lindex $portProp 1] 2] 1]]
+ label $plabel position $cpoint
+ }
+ instance {
+ parse_instance [lindex $portProp 1] [lrange $portProp 2 end]
+ }
+ default {puts "Unsupported portImplementation keyword $portkey"}
+ }
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse a "page" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_page {cellname portlist pagedata} {
+
+ # Go to the next empty page
+ set cpage 1
+ page $cpage -force
+ while {[object parts] != {}} {incr cpage ; page $cpage -force}
+ page label $cellname
+
+ foreach phrase $pagedata {
+ set keyword [lindex $phrase 0]
+ switch $keyword {
+ instance {
+ set instName [lindex $phrase 1]
+ parse_instance $instName [lrange $phrase 2 end]
+ }
+ net {
+ parse_net [lrange $phrase 1 end]
+ }
+ portImplementation {
+ parse_port {} [lrange $phrase 1 end]
+ }
+ commentGraphics {
+ set comment [lindex $phrase 1]
+ set ctype [lindex $comment 0] ;# from the technology block...
+ set geolist [lindex $comment 1]
+ parse_geometry [lindex $geolist 0] [lrange $geolist 1 end]
+ }
+ default {puts "Unsupported page block keyword $keyword"}
+ }
+ }
+
+ if {$portlist != {}} {
+ quiet_deselect
+ set obbox [object bbox]
+ set x [expr [lindex $obbox 0] + 128]
+ set y [expr [lindex $obbox 1] - 64]
+ set itext [list {Text "spice1:.subckt %n"}]
+ set pstring ""
+ foreach pname $portlist {
+ if {[string length $pstring] > 60} {
+ lappend itext [subst {Text "$pstring"}]
+ lappend itext {Return}
+ set pstring "+"
+ incr y -32
+ }
+ set pstring [join [list $pstring "%p$pname"]] ;# preserves whitespace
+ }
+ lappend itext [subst {Text "$pstring"}]
+ label make info "$itext" "$x $y"
+
+ incr y -32
+ label make info "spice-1:.ends" "$x $y"
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse a "contents" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_contents {celltype cellname portlist contentdata} {
+
+ global symbolview
+
+ set labellist {}
+ foreach phrase $contentdata {
+ set keyword [lindex $phrase 0]
+ switch $keyword {
+ boundingBox {
+ set bbox [lindex $phrase 1]
+ set handle [parse_geometry [lindex $bbox 0] [lrange $bbox 1 end]]
+ element $handle border bbox true
+ }
+ commentGraphics {
+ set comment [lindex $phrase 1]
+ set ctype [lindex $comment 0] ;# from the technology block...
+ set geolist [lindex $comment 1]
+ set plabel [parse_geometry [lindex $geolist 0] [lrange $geolist 1 end]]
+ if {$plabel != {}} {lappend labellist $plabel}
+ }
+ figure {
+ # Figure type is defined in the technology section, and defines
+ # color, linewidth, etc.
+ set figureType [lindex $phrase 1]
+ set geolist [lindex $phrase 2]
+ parse_geometry [lindex $geolist 0] [lrange $geolist 1 end]
+ }
+ portImplementation {
+ parse_port $labellist [lrange $phrase 1 end]
+ }
+ page {
+ # Note: Handle multiple pages here!
+ parse_page $cellname $portlist [lrange $phrase 1 end]
+ }
+ default {puts "Unsupported content/symbol block keyword $keyword"}
+ }
+ }
+
+ # search for all symbol views
+ # following list contains these viewnames
+
+ if {[lsearch $symbolview $celltype] > -1} {
+ # Create standard parameters
+ parameter make substring class "X"
+ parameter make substring idx "?"
+
+ if {$portlist != {}} {
+ quiet_deselect
+ set obbox [object bbox]
+ set x [expr [lindex $obbox 0] + 128]
+ set y [expr [lindex $obbox 1] - 64]
+ set itext [list {Text "spice:"} {Parameter class} {Parameter idx}]
+ set pstring ""
+ foreach pname $portlist {
+ if {[string length $pstring] > 60} {
+ lappend itext [subst {Text "$pstring"}]
+ lappend itext {Return}
+ set pstring "+"
+ incr y -32
+ }
+ set pstring [join [list $pstring "%p$pname"]] ;# preserves whitespace
+ }
+ set pstring [join [list $pstring "%n"]] ;# preserves whitespace
+ lappend itext [subst {Text "$pstring"}]
+
+ label make info "$itext" "$x $y"
+ }
+ }
+
+}
+
+#------------------------------------------------------------------------
+# Parse a "property" statement in the EDIF data.
+# (To do: generate an xcircuit parameter for the object)
+#------------------------------------------------------------------------
+
+proc parse_property {key value} {
+ set keylen [llength $key]
+ set property [lindex $value 0]
+ set proptype [lindex $property 0]
+ set pvalue [lindex $property 1]
+
+ # Any other proptypes to handle?
+ switch $proptype {
+ string { set paramtype substring }
+ integer { set paramtype numeric }
+ boolean {
+ set paramtype numeric
+ switch $pvalue {
+ true -
+ True -
+ TRUE -
+ t -
+ T { set pvalue 1}
+ false -
+ False -
+ FALSE -
+ f -
+ F { set pvalue 0}
+ }
+ }
+ default { puts "Unknown property type $proptype" ; return }
+ }
+
+ # Attempt to set the parameter value. If the parameter doesn't
+ # exist, then create it.
+
+ if [catch {parameter set $key $pvalue}] {
+ parameter make $paramtype $key $pvalue
+ }
+}
+
+#------------------------------------------------------------------------
+# Parse an "interface" block in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_interface {cellname ifacedata} {
+ set portlist {}
+ foreach phrase $ifacedata {
+ set keyword [lindex $phrase 0]
+
+ # Possible other keywords to handle:
+ # port (ignoring ports for now, just dealing with portImplementation)
+ # property (is a property of what??) --- should translate instNamePrefix
+ # to parameter "class".
+
+ switch $keyword {
+ port {
+ if {[lindex [lindex $phrase 1] 0] == "array"} {
+ set zw [subst_name [lindex [lindex $phrase 1] 1]]
+ } else {
+ set zw [subst_name [lindex $phrase 1]]
+ }
+ lappend portlist $zw
+ }
+ symbol {parse_contents symbol $cellname $portlist [lrange $phrase 1 end]}
+ default {puts "Unsupported interface block keyword $keyword"}
+ }
+ }
+ return $portlist
+}
+
+#------------------------------------------------------------------------
+# Parse a "view schematic" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_schematic {cellname viewdata} {
+
+ set portlist {}
+ foreach phrase $viewdata {
+ set keyword [lindex $phrase 0]
+ # Possible other keywords to handle:
+ # viewType, interface
+ switch $keyword {
+ interface {set portlist [parse_interface $cellname [lrange $phrase 1 end]]}
+ contents {parse_contents schematic $cellname $portlist [lrange $phrase 1 end]}
+ property {parse_property [lindex $phrase 1] [lrange $phrase 2 end]}
+ default {puts "Unsupported schematic view block keyword $keyword"}
+ }
+ }
+
+}
+
+#------------------------------------------------------------------------
+# Parse a "view symbol" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_symbol {libname cellname viewdata} {
+
+ # If an object of this name exists, rename it first.
+ catch {object [object handle $cellname] name "_$cellname"}
+ set handle [object make $cellname $libname -force]
+ if {$handle == ""} {
+ puts "Error: Couldn't create new object!"
+ return
+ }
+ set cpage [page]
+ push $handle
+ symbol type fundamental
+ set portlist {}
+
+ foreach phrase $viewdata {
+ set keyword [lindex $phrase 0]
+ # Possible other keywords to handle:
+ # viewType, interface
+ switch $keyword {
+ interface {set portlist [parse_interface $cellname [lrange $phrase 1 end]]}
+ contents {parse_contents fundamental $cellname $portlist [lrange $phrase 1 end]}
+ property {parse_property [lindex $phrase 1] [lrange $phrase 2 end]}
+ default {puts "Unsupported symbol view block keyword $keyword"}
+ }
+ }
+
+ pop
+ if [catch {delete $handle}] {
+ page $cpage
+ if [catch {delete $handle}] {
+ puts "Error: Element handle $handle does not exist?"
+ puts "Page objects: [object parts]"
+ }
+ }
+
+ # Find the instance in the library and force a recomputation of its
+ # bounding box.
+
+ library $libname goto
+ foreach inst [library $libname handle] {
+ if {[instance $inst object] == $cellname} {
+ instance $inst bbox recompute
+ break
+ }
+ }
+ page $cpage
+}
+
+#------------------------------------------------------------------------
+# Parse a "cell" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_cell {libname cellname celldata} {
+
+ global symbolview
+
+ foreach phrase $celldata {
+ set keyword [lindex $phrase 0]
+ # Possible other keywords to handle:
+ # cellType
+ switch $keyword {
+ view {
+ set viewType [lindex $phrase 1]
+ if {[lsearch $symbolview $viewType] > -1} {
+ parse_symbol $libname $cellname [lrange $phrase 2 end]
+ } else {
+ switch $viewType {
+ schematic {parse_schematic $cellname [lrange $phrase 2 end]}
+ default {puts "Unsupported view type $viewType"}
+ }
+ }
+ }
+ default {puts "Unsupported cell block keyword $keyword"}
+ }
+ }
+}
+
+
+#------------------------------------------------------------------------
+# Parse a "library" statement in the EDIF data.
+#------------------------------------------------------------------------
+
+proc parse_library {libname libdata} {
+ library make $libname
+ foreach phrase $libdata {
+ set keyword [lindex $phrase 0]
+ # Possible other keywords to handle:
+ # basic, edifLevel, technology
+ switch $keyword {
+ cell {
+ parse_cell $libname [lindex $phrase 1] [lrange $phrase 2 end]
+ }
+ default {puts "Unsupported library block keyword $keyword"}
+ }
+ }
+
+ # Regenerate the library
+ library $libname compose
+}
+
+#------------------------------------------------------------------------
+# Main file reader routine. Read the file into a single string, and
+# replace parentheses so we turn the LISP phrasing into a nested TCL
+# list.
+#------------------------------------------------------------------------
+
+proc read_edif {filename} {
+
+ if [catch {open $filename r} fileIn] {
+ puts stderr "Cannot find file $filename"
+ return;
+ }
+
+ # Remove some tag callbacks that cause problems. . .
+
+ set paramtag [tag parameter]
+ tag parameter {}
+
+ # Convert the file into a nested list by converting () to {}.
+
+ set everything [read $fileIn]
+ set masterlist [lindex [string map {( \{ ) \} \n " "} $everything] 0]
+ unset everything
+ close $fileIn
+
+ # Now parse the file. . .
+
+ set cpage [page]
+ config suspend true
+
+ foreach phrase $masterlist {
+ set keyword [lindex $phrase 0]
+ # Possible other keywords to handle:
+ # edif, edifVersion, edifLevel, keywordMap, status
+ switch $keyword {
+ library {parse_library [lindex $phrase 1] [lrange $phrase 2 end]}
+ default {puts "Unsupported primary keyword $keyword"}
+ }
+ }
+
+ tag parameter $paramtag
+
+ # Return to (and redraw) original page
+ page $cpage
+ zoom view
+ config suspend false
+
+}
+
+#------------------------------------------------------------------------
+# Procedure that creates the dialog to find an EDIF file to parse and
+# calls procedure read_edif.
+#---------------------------------------------------------------------------
+
+proc xcircuit::promptreadedif {} {
+ global XCOps
+ .filelist.bbar.okay configure -command \
+ {read_edif [.filelist.textent.txt get] ; \
+ wm withdraw .filelist}
+ .filelist.listwin.win configure -data "edf edif"
+ .filelist.textent.title.field configure -text "Select EDIF 2.0.0 file to parse:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+ xcircuit::removelists .filelist
+}
+
diff --git a/lib/tcl/files.tcl b/lib/tcl/files.tcl
new file mode 100644
index 0000000..6a8f075
--- /dev/null
+++ b/lib/tcl/files.tcl
@@ -0,0 +1,203 @@
+#---------------------------------------------------------------------------
+# files.tcl ---
+#
+# xcircuit Tcl script for handling multiple-file writes
+#
+# Tim Edwards 12/5/05 for MultiGiG
+#---------------------------------------------------------------------------
+
+set XCOps(module,files) 1
+
+#---------------------------------------------------------------------------
+# Forced write all
+#---------------------------------------------------------------------------
+
+proc xcircuit::forcewriteall {} {
+ set pages [page links all]
+ for {set i 1} {$i <= $pages} {incr i} {
+ page $i changes 1
+ set techlist [technology used $i]
+ foreach tech $techlist {
+ if {[technology writable $tech]} {technology changed $tech 1}
+ }
+ }
+ destroy .writeall
+ xcircuit::promptwriteall
+}
+
+#---------------------------------------------------------------------------
+# Write all pages. Determine which pages are enabled/disabled in the
+# ".writeall" window, and save each one.
+#---------------------------------------------------------------------------
+
+proc xcircuit::writeall {} {
+ global XCOps
+
+ if {![catch {raise .writeall}]} {
+ set rows [lindex [grid size .writeall.list] 1]
+ incr rows -1
+ for {set i 1} {$i <= $rows} {incr i} {
+ if {$XCOps(cbox${i}) > 0} {
+ set pagelist [pack slaves .writeall.list.pframe${i}]
+ set firstpage [lindex $pagelist 0]
+ set pageno [${firstpage} cget -text]
+ if {$pageno == "-" || $pageno == "X"} {
+ set tname [.writeall.list.f${i} cget -text]
+ set fname [technology filename $tname]
+ if {$fname == "(no associated file)"} {
+ # Fix me: this works only on one technology at a time!
+ xcircuit::promptsavetech
+ } else {
+ technology save $tname
+ }
+ } else {
+ page ${pageno} save
+ }
+ }
+ unset XCOps(cbox${i})
+ }
+ destroy .writeall
+ }
+}
+
+#---------------------------------------------------------------------------
+# Prompt for writing all pages
+#---------------------------------------------------------------------------
+
+proc xcircuit::promptwriteall {} {
+ global XCOps
+
+ # Get list of unique filenames.
+
+ set pages [page links all]
+ set filelist {}
+ for {set i 1} {$i <= $pages} {incr i} {
+ set changes [page $i changes]
+ if {$changes > 0} {
+ if {[page $i filename] == {}} {
+ page $i filename [page $i label]
+ }
+ lappend filelist [page $i filename]
+ }
+ }
+ set filelist [lsort -unique -dictionary $filelist]
+
+ set techlist {}
+ set badtechslist {}
+ foreach tech [technology list] {
+ if {[technology changed $tech] > 0} {
+ if {[technology writable $tech] > 0} {
+ lappend techlist $tech
+ } else {
+ lappend badtechslist $tech
+ }
+ }
+ }
+
+ set filestowrite [expr [llength $filelist] + [llength $techlist]]
+
+ # Set up the "writeall" window
+
+ catch {destroy .writeall}
+ toplevel .writeall -bg beige
+ frame .writeall.tbar -bg beige
+ frame .writeall.list -bg beige
+ frame .writeall.bbar -bg beige
+
+ pack .writeall.tbar -side top -padx 5 -pady 5 -fill x
+ pack .writeall.list -side top -padx 5 -pady 5 -fill x
+ pack .writeall.bbar -side top -padx 5 -pady 5 -fill x
+
+ if {$filestowrite == 0} {
+ label .writeall.tbar.title -text \
+ "(No modified pages or technologies to write)" -bg \
+ beige -fg gray40
+ pack .writeall.tbar.title -side left
+ } else {
+ label .writeall.tbar.title -text "Write All Modified Pages and Technologies:" \
+ -bg beige -fg blue
+ pack .writeall.tbar.title -side left
+
+ label .writeall.list.ftitle -text "Filename" -bg beige -fg brown
+ label .writeall.list.ptitle -text "Pages" -bg beige -fg brown
+ label .writeall.list.wtitle -text "Write?" -bg beige -fg brown
+ grid .writeall.list.ftitle -row 0 -column 0 -sticky news
+ grid .writeall.list.ptitle -row 0 -column 1 -sticky news
+ grid .writeall.list.wtitle -row 0 -column 2 -sticky news
+ }
+
+ set k 0
+ foreach j $filelist {
+ incr k
+ label .writeall.list.f${k} -text "$j" -anchor w -bg beige
+ frame .writeall.list.pframe${k} -bg beige
+ set XCOps(cbox${k}) 1
+ checkbutton .writeall.list.cbox${k} -bg beige -variable XCOps(cbox${k})
+
+ set l 0
+ for {set i 1} {$i <= $pages} {incr i} {
+ if {[page $i filename] == $j} {
+ set changes [page $i changes]
+ if {$changes > 0} {
+ incr l
+ button .writeall.list.pframe${k}.b${l} -text "$i" -bg \
+ white -command "page goto $i ; \
+ promptsavepage"
+ pack .writeall.list.pframe${k}.b${l} -side left -padx 5
+ }
+ }
+ }
+ grid .writeall.list.f${k} -row $k -column 0 -sticky news
+ grid .writeall.list.pframe${k} -row $k -column 1 -sticky news
+ grid .writeall.list.cbox${k} -row $k -column 2 -sticky news
+ }
+
+ foreach j $techlist {
+ incr k
+ label .writeall.list.f${k} -text "$j" -anchor w -bg beige
+ frame .writeall.list.pframe${k} -bg beige
+ set XCOps(cbox${k}) 1
+ checkbutton .writeall.list.cbox${k} -bg beige -variable XCOps(cbox${k})
+
+ button .writeall.list.pframe${k}.b1 -text "-" -bg white \
+ -command "set XCOps(technology) $j ; \
+ xcircuit::promptsavetech"
+ pack .writeall.list.pframe${k}.b1 -side left -padx 5
+ grid .writeall.list.f${k} -row $k -column 0 -sticky news
+ grid .writeall.list.pframe${k} -row $k -column 1 -sticky news
+ grid .writeall.list.cbox${k} -row $k -column 2 -sticky news
+ }
+
+ foreach j $badtechslist {
+ incr k
+ label .writeall.list.f${k} -text "$j" -anchor w -bg beige -fg gray60
+ frame .writeall.list.pframe${k} -bg beige
+ set XCOps(cbox${k}) 0
+ checkbutton .writeall.list.cbox${k} -bg beige -variable XCOps(cbox${k})
+
+ button .writeall.list.pframe${k}.b1 -text "X" -bg white -fg gray60 \
+ -command "set XCOps(technology) $j ; \
+ xcircuit::promptsavetech"
+ pack .writeall.list.pframe${k}.b1 -side left -padx 5
+ grid .writeall.list.f${k} -row $k -column 0 -sticky news
+ grid .writeall.list.pframe${k} -row $k -column 1 -sticky news
+ grid .writeall.list.cbox${k} -row $k -column 2 -sticky news
+ }
+
+ if {$filestowrite > 0} {
+ button .writeall.bbar.okay -text Write -bg beige -command \
+ {xcircuit::writeall}
+ pack .writeall.bbar.okay -side left -ipadx 10 -padx 5
+ }
+
+ if {$filestowrite < $pages} {
+ button .writeall.bbar.force -text Force -bg beige -command \
+ {xcircuit::forcewriteall}
+ pack .writeall.bbar.force -side left -ipadx 10 -padx 5
+ }
+
+ button .writeall.bbar.cancel -text Cancel -bg beige -command \
+ {destroy .writeall}
+ pack .writeall.bbar.cancel -side right -ipadx 10 -padx 5
+}
+
diff --git a/lib/tcl/library.tcl b/lib/tcl/library.tcl
new file mode 100644
index 0000000..e939f30
--- /dev/null
+++ b/lib/tcl/library.tcl
@@ -0,0 +1,297 @@
+#----------------------------------------
+# Library management for XCircuit
+#----------------------------------------
+
+set XCOps(module,library) 1
+
+#----------------------------------------
+
+proc xcircuit::raisemanager {} {
+ makelibmanager
+ set midx [.xcircuit.menubar.filebutton.filemenu index *Manager*]
+ .xcircuit.menubar.filebutton.filemenu entryconfigure \
+ $midx -label "Hide Library Manager" -command {xcircuit::lowermanager}
+}
+
+#----------------------------------------
+
+proc xcircuit::lowermanager {} {
+ destroy .libmgr
+ set midx [.xcircuit.menubar.filebutton.filemenu index *Manager*]
+ .xcircuit.menubar.filebutton.filemenu entryconfigure \
+ $midx -label "Library Manager" -command {xcircuit::raisemanager}
+}
+
+#----------------------------------------
+
+proc xcircuit::promptadddirectory {} {
+ .filelist.bbar.okay configure -command \
+ {.libmgr.search.list insert 0 [.filelist.textent.txt get];\
+ updatelibmanager; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "lps"
+ .filelist.textent.title.field configure -text "Select directory to add to search:"
+ .filelist.textent.txt delete 0 end
+ wm deiconify .filelist
+ focus .filelist.textent.txt
+}
+
+#----------------------------------------
+
+proc xcircuit::promptnewlibrary {} {
+ .dialog.bbar.okay configure -command \
+ {library make [.dialog.textent.txt get]; updatelibmanager; \
+ wm withdraw .dialog}
+ .dialog.textent.title.field configure -text "Enter name for new library page:"
+ .dialog.textent.txt delete 0 end
+ wm deiconify .dialog
+ focus .dialog.textent.txt
+}
+
+#----------------------------------------
+
+proc xcircuit::prompttechtarget {} {
+ .dialog.bbar.okay configure -command \
+ {foreach i [.libmgr.object.list curselection] \
+ {technology objects [.dialog.textent.txt get] \
+ [.libmgr.object.list get $i]}; \
+ updatelibmanager; wm withdraw .dialog}
+ .dialog.textent.title.field configure -text "Enter name of target technology:"
+ .dialog.textent.txt delete 0 end
+ wm deiconify .dialog
+ focus .dialog.textent.txt
+}
+
+#----------------------------------------
+
+proc makelibmanager {} {
+ global XCOps
+ global XCIRCUIT_LIB_DIR
+
+ toplevel .libmgr
+
+ wm protocol .libmgr WM_DELETE_WINDOW {xcircuit::lowermanager}
+
+ label .libmgr.title1 -text "Source Technology File" -foreground "blue"
+ label .libmgr.title2 -text "Target Library Page" -foreground "blue"
+ label .libmgr.title3 -text "Search Directories" -foreground "blue"
+ frame .libmgr.tblock
+
+ label .libmgr.tblock.title -text "Objects" -foreground "blue"
+
+ menubutton .libmgr.srclib -text "" -menu .libmgr.srclib.menu -relief groove
+ menubutton .libmgr.tgtlib -text "" -menu .libmgr.tgtlib.menu -relief groove
+
+ frame .libmgr.object
+ frame .libmgr.search
+
+ listbox .libmgr.object.list -relief groove -background white \
+ -yscrollcommand ".libmgr.object.scroll set" -width 30 \
+ -selectmode extended
+ listbox .libmgr.search.list -relief groove -background white \
+ -yscrollcommand ".libmgr.object.scroll set" -width 30
+
+ scrollbar .libmgr.object.scroll -orient vertical \
+ -command ".libmgr.object.list yview"
+ scrollbar .libmgr.search.scroll -orient vertical \
+ -command ".libmgr.search.list yview"
+
+ pack .libmgr.object.list -side left -fill both -expand true
+ pack .libmgr.object.scroll -side right -fill y
+
+ pack .libmgr.search.list -side left -fill both -expand true
+ pack .libmgr.search.scroll -side right -fill y
+
+ frame .libmgr.buttons
+
+ button .libmgr.buttons.add -text "Add Directory" \
+ -command {xcircuit::promptadddirectory}
+ button .libmgr.buttons.new -text "Add New Library Page" \
+ -command {xcircuit::promptnewlibrary}
+ button .libmgr.buttons.done -text "Load Selected" \
+ -command {foreach i [.libmgr.object.list curselection] \
+ {library $XCOps(tgtlib) import $XCOps(srclib) \
+ [.libmgr.object.list get $i]}; updateobjects $XCOps(srclib); \
+ refresh}
+ button .libmgr.buttons.all -text "Load All" \
+ -command {library $XCOps(tgtlib) load $XCOps(srclib); \
+ updateobjects $XCOps(srclib); refresh}
+ button .libmgr.buttons.move -text "Move Selected" \
+ -command {xcircuit::prompttechtarget}
+
+ checkbutton .libmgr.tblock.check -text "Show Loaded" \
+ -variable XCOps(showloaded) -onvalue 1 -offvalue 0 \
+ -command {updateobjects $XCOps(srclib)}
+
+ set XCOps(showloaded) 0
+
+ pack .libmgr.buttons.add -side left
+ pack .libmgr.buttons.new -side left
+ pack .libmgr.buttons.done -side left
+ pack .libmgr.buttons.all -side left
+ # pack .libmgr.buttons.move -side left
+
+ grid .libmgr.title1 -row 0 -column 0 -sticky news
+ grid .libmgr.title2 -row 0 -column 1 -sticky news
+ grid .libmgr.title3 -row 2 -column 0 -sticky news
+ grid .libmgr.tblock -row 2 -column 1 -sticky news
+
+ pack .libmgr.tblock.title -side left
+ pack .libmgr.tblock.check -side left
+
+ grid .libmgr.srclib -row 1 -column 0 -sticky news -padx 4
+ grid .libmgr.tgtlib -row 1 -column 1 -sticky news -padx 4
+ grid .libmgr.object -row 3 -column 1 -sticky news
+ grid .libmgr.search -row 3 -column 0 -sticky news
+ grid .libmgr.buttons -row 4 -column 0 -columnspan 2 -sticky news
+
+ grid columnconfigure .libmgr 0 -weight 1
+ grid columnconfigure .libmgr 1 -weight 1
+ grid rowconfigure .libmgr 3 -weight 1
+
+ menu .libmgr.srclib.menu -tearoff 0
+ menu .libmgr.tgtlib.menu -tearoff 0
+
+ # Initial set of library directories to search
+ set searchpath [config search lib]
+ if {$searchpath == {}} {
+ .libmgr.search.list insert end $XCIRCUIT_LIB_DIR
+ .libmgr.search.list insert end "."
+ } else {
+ set searchlist [string map {: " "} $searchpath]
+ foreach i $searchlist {
+ .libmgr.search.list insert end $i
+ }
+ }
+
+ # Do an update
+ updatelibmanager
+}
+
+#----------------------------------------
+
+proc updateobjects {techfile} {
+ global XCOps
+
+ # Erase the current entries
+ .libmgr.object.list delete 0 end
+ catch unset XObjs(objects)
+
+ # Find all the objects defined in library "techfile"
+ set objlist {}
+ set fileId [open $techfile]
+ foreach line [split [read $fileId] \n] {
+ switch -glob -- $line {
+ "/* \{" {
+ lappend objlist [string range [lindex [split $line] 0] 1 end]
+ }
+ }
+ }
+ close $fileId
+
+ set objlist [lsort -dictionary $objlist]
+ foreach objname $objlist {
+ if {[catch {object handle $objname}]} {
+ .libmgr.object.list insert end $objname
+ } elseif {$XCOps(showloaded) == 1} {
+ .libmgr.object.list insert end $objname
+ .libmgr.object.list itemconfigure end -fg forestgreen
+ }
+ }
+}
+
+#----------------------------------------------
+# Filename sorting function---sort by root name
+#----------------------------------------------
+
+proc FileCompare {a b} {
+ set aname [file rootname [file tail $a]]
+ set bname [file rootname [file tail $b]]
+ set res [string compare $aname $bname]
+ if {$res != 0} {
+ return $res
+ } else {
+ # If the root matches, then order by order of search directory
+ set dlist [.libmgr.search.list get 0 end]
+ set aidx [lsearch $dlist [file dirname $a]]
+ set bidx [lsearch $dlist [file dirname $b]]
+ if {$aidx > $bidx} {
+ return 1
+ } elseif {$aidx < $bidx} {
+ return -1
+ } else {
+ return 0
+ }
+ }
+}
+
+#----------------------------------------
+
+proc updatelibmanager {} {
+ global XCOps
+
+ # Get the list of directories in which to search for libraries
+ set dirlist [.libmgr.search.list get 0 end]
+
+ # Erase the current entries
+ .libmgr.tgtlib.menu delete 0 end
+ .libmgr.srclib.menu delete 0 end
+
+ # Create the list of source libraries
+ set srclist {}
+ foreach i $dirlist {
+ if {[file isdirectory $i]} {
+ set srclist [concat $srclist [glob -nocomplain ${i}/*.lps]]
+ }
+ }
+ set srclist [lsort -command FileCompare $srclist]
+
+ foreach j $srclist {
+ set libname [file rootname [file tail $j]]
+ if {[.libmgr.srclib.menu entrycget end -label] != $libname} {
+ .libmgr.srclib.menu add radio -label $libname -variable XCOps(srclib) \
+ -value $j -command ".libmgr.srclib configure \
+ -text $libname; updateobjects $j"
+ }
+ }
+
+ # Reset "Source Technology" only if not set before, or if the name doesn't match
+ # the menu entry.
+ set cres [catch {set entry [.libmgr.srclib.menu index [file rootname \
+ [file tail $XCOps(srclib)]]]}]
+ if {$cres == 0} {
+ if {[.libmgr.srclib cget -text] == [.libmgr.srclib.menu entrycget $entry -label]} {
+ set cres 1
+ }
+ }
+ if {$cres == 1} {
+ set XCOps(srclib) [.libmgr.srclib.menu entrycget 0 -value]
+ .libmgr.srclib configure -text [.libmgr.srclib.menu entrycget 0 -label]
+ }
+
+ # Find the number of technologies in XCircuit
+ set numlibs [library "User Library"]
+
+ # Create the list of target libraries
+ for {set i 1} {$i <= $numlibs} {incr i} {
+ .libmgr.tgtlib.menu add radio -label [library $i] -variable XCOps(tgtlib) \
+ -value $i -command ".libmgr.tgtlib configure -text {[library $i]}"
+ }
+
+ # Reset "Target Library" only if not set before, or if the name doesn't match
+ # the menu entry.
+ set cres [catch {set entry [.libmgr.srclib.menu index $XCOps(tgtlib)]}]
+ if {$cres == 0} {
+ if {[.libmgr.tgtlib cget -text] == [.libmgr.tgtlib.menu entrycget $entry -label]} {
+ set cres 1
+ }
+ }
+ if {$cres == 1} {
+ set XCOps(tgtlib) $numlibs
+ .libmgr.tgtlib configure -text [library $numlibs]
+ }
+
+ # Create the object list for the first source library entry
+ updateobjects $XCOps(srclib)
+}
+
+#----------------------------------------
diff --git a/lib/tcl/matgen.tcl b/lib/tcl/matgen.tcl
new file mode 100644
index 0000000..2adf583
--- /dev/null
+++ b/lib/tcl/matgen.tcl
@@ -0,0 +1,513 @@
+#----------------------------------------------------------------------
+# matgen.tcl v0.7 --- An xcircuit Tcl extension for importing matlab
+# postscript files
+# Copyright (c) 2008 Wim Vereecken
+# Wim.Vereecken@gmail.com
+# Wim.Vereecken@esat.kuleuven.be
+#
+# 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.
+#----------------------------------------------------------------------
+
+# "lset" forward compatibility routine from wiki.tcl.tk---"lset" is
+# used in these routines, and was new with Tcl version 8.4.
+
+if {[package vcompare [package provide Tcl] 8.4] < 0} {
+ proc tcl::K {a b} {return $a}
+ proc lset {listName index val} {
+ upvar $listName list
+ set list [lreplace [tcl::K $list [set list {}]] $index $index $val]
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptimportmatlab {} {
+ .filelist.bbar.okay configure -command \
+ {matgen [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "ps"
+ .filelist.textent.title.field configure -text "Select file to import:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+
+proc matgen {argv} {
+global XCOps XCWinOps
+# PART 1: Command line parser_______________________________
+# load-axes property is set
+set axes 1
+# set default scale factor
+set scalefactor 0.2
+# set default line width
+set linewidth 1.00
+# set default line width
+set bold 0
+# set default file name
+set filenames {}
+# set default text size
+set matlab_textsize 100
+# parse all command line args
+puts "Checking options..."
+foreach arg $argv {
+ # if -noaxes key is found, disable axes
+ if [string compare $arg "-noaxes"]==0 then {
+ set axes 0
+ puts " *** Axes are disabled"
+ }
+ if [regexp {\-scale=(\d+\.*\d*)} $arg matchresult sub1] then {
+ set scalefactor [expr $sub1*0.20]
+ puts " *** Scalefactor set to $scalefactor"
+ }
+ if [regexp {\-lw=(\d+\.*\d*)} $arg matchresult sub1] then {
+ set linewidth $sub1
+ puts " *** Linewidth set to $linewidth"
+ }
+ if [regexp {\-bold} $arg matchresult] then {
+ set bold 1
+ puts " *** Bold fonts are enabled"
+ }
+ if [regexp {(.*\.e?ps)} $arg matchresult sub1] then {
+ lappend filenames $sub1
+ set file [lindex $filenames [expr [llength $filenames]-1]]
+ }
+}
+
+if {[llength $argv] < 1} then {
+ puts " *** no arguments found...\n"
+ puts "matgen.tcl 0.7"
+ puts "Written by Wim Vereecken\n"
+ puts "Usage:"
+ puts " matgen \"\[options\] file.eps \[file2.eps\] ...\"\n"
+ puts "Options:"
+ puts " -noaxes: strip axes data"
+ puts " -scale=x: rescale by factor x"
+ puts " -lw=x: scale linewidth by factor x"
+ puts " -bold: use bold text labels\n"
+ puts "Example:"
+ puts " matgen \"-scale=0.7 -lw=3 file.eps\"\n"
+ return 0
+}
+
+# PART 2: Parse and process the source matlab eps file_______
+# The extension of the source files that will be examined
+puts "Checking for valid matlab postscript (eps) files..."
+## Search in the current directory for files with an .eps
+## extension. If the file is recognized as a matlab .eps
+## file, add the source file to @foundsources.
+
+set validfiles {};
+foreach file $filenames {
+ if [regexp {e?ps} $file matchresult] then {
+ # try to open $file
+ if [catch {open $file r} result] {
+ puts "Warning: $result"
+ return -1
+ } else {
+ set fp $result
+ set data [read $fp]
+ close $fp
+ }
+ # split data in seperate lines
+ set data [split $data "\n"]
+ # read every line and search for "Creator: MATLAB"
+ foreach line $data {
+ # check if the source is a matlab eps
+ if [regexp {Creator: MATLAB} $line matchresult] then {
+ lappend validfiles $file
+ puts " *** $file is a valid Matlab plot";
+ # break searching here
+ break
+ }
+ }
+ }
+}
+
+# exit with message when no source files are found
+if [llength $validfiles]<1 {
+ puts " *** No valid matlab .eps files found. Bye!";
+ return -1
+}
+
+# PART 3____________________________________________________
+foreach file $validfiles {
+ puts "Processing $file...";
+ # open each matlab eps file
+ if [catch {open $file r} result] {
+ puts "Warning: $result"
+ return -1
+ } else {
+ set fp $result
+ set data [read $fp]
+ close $fp
+ }
+ # the stack emulator
+ set source_stack ""
+ # the xcircuit output vector
+ set xcircuit_output ""
+ # the xcircuit lib definitions
+ set xcircuit_libdefs ""
+ # the color definitions library
+ set colordefs ""
+
+ # split data in seperate lines
+ set data [split $data "\n"]
+ set object_list {}
+ foreach line $data {
+ append source_stack "\x0a$line"
+ # Skip first part of matlab $source_stack if noaxes is set
+ if [regexp {\/c8} $line matchresult] then {
+ if {$axes == 0} then {
+ # clear output
+ set xcircuit_output ""
+ } else {
+ # select all items in page, make object, and deselect
+ if {[llength $object_list] > 0} then {
+ select $object_list
+ set axes_object [object make "axes"]
+ deselect $axes_object
+ }
+ }
+ }
+ # Extract polylines from the matlab $source_stack
+ if [regexp {(\d+)\s*MP\sstroke} $line matchresult sub1] {
+ # extract the number of vertices of the polyline
+ set num_vertices $sub1
+ # the number of arguments to read is thus 2*num_vertices
+ set num_args [expr $num_vertices*2]
+ # extract the vertices list of the polyline
+ set re "\\x0a+\\s*((?:\-?\\d+\\x20*\\x0a*)+?)\\s+$num_vertices\\s+MP\\sstroke"
+ if [regexp $re $source_stack matchresult sub1] then {
+ # replace 1+ spaces by the ":" separator
+ regsub -all {\s+} $sub1 ":" sub1
+ # split $sub1 based on the ":" separator
+ set polyline_vertices [split $sub1 ":"]
+ # the polyline_vertices list contains all vertices
+ # --> {<undefined data> x1 y1 x2 y2 ... xn yn}
+ } else {
+ puts "Error in polyline regular expression. Exiting..."
+ return -1
+ }
+ # convert the arguments to the xcircuit coordinate format.
+ # The matlab polyline coordinates are relative to each other,
+ # starting for the last value of the postscript stack.
+ # XCircuit needs absolute coordinates for the polyline vertices.
+ # Some recalculation is thus needed to obtain absolute coordinates.
+ for {set i [expr $num_args-4]} {$i>=0} {incr i -2} {
+ # calculate x-coordinates
+ set prev_point_x [lindex $polyline_vertices $i]
+ set current_point_x [lindex $polyline_vertices [expr $i+2]]
+ lset polyline_vertices $i [expr $prev_point_x+$current_point_x]
+ # calculate y-coordinates
+ set prev_point_y [lindex $polyline_vertices [expr $i+1]]
+ set current_point_y [lindex $polyline_vertices [expr $i+3]]
+ lset polyline_vertices [expr $i+1] [expr $prev_point_y+$current_point_y]
+ }
+ # Rescaling feature. Should be re-implemented in a decent way
+ for {set i 0} {$i<$num_args} {incr i 1} {
+ lset polyline_vertices $i [expr int([lindex $polyline_vertices $i]*$scalefactor)]
+ }
+ # Flip the y-axis coordinates. XCircuit's coordinate system seems to use
+ # the left hand rule.
+ for {set i 1} {$i<$num_args} {incr i 2} {
+ lset polyline_vertices $i [expr [lindex $polyline_vertices $i]*-1]
+ }
+ # create the tcl command and draw the polygon
+ set prev_point_x 0
+ set prev_point_y 0
+ set num_vertices 0
+ set tcl_command ""
+ eval "fill 0"
+ for {set i 0} {$i<$num_args} {incr i 2} {
+ # the number of vertices xcircuit can handle is limited to 250
+ if {$num_vertices == 200} then {
+ eval "lappend object_list \[polygon make 200 $tcl_command\]"
+ set prev_point_x 0
+ set prev_point_y 0
+ set num_vertices 0
+ set tcl_command ""
+ # resume last point in next polyline
+ incr i -2
+ }
+ # extract the current x- and y-coordinates
+ set current_point_x [lindex $polyline_vertices $i]
+ set current_point_y [lindex $polyline_vertices [expr $i+1]]
+ # drop the current vertex if distance from previous point is too small
+ if { abs([expr $current_point_x - $prev_point_x]) < 1
+ && abs([expr $current_point_y - $prev_point_y]) < 1} then {
+ # drop the current vertex
+ continue
+ # add the current vertex to the tcl_command string
+ } else {
+ # increase the number of vertices in the tcl_command
+ incr num_vertices 1
+ # append the current vertex to the tcl_command string
+ # format: "polygon make N {x1 y1} {x2 y2} ... {xn yn}"
+ append tcl_command "\{$current_point_x $current_point_y\} "
+ # save the current vertex for future reference
+ set prev_point_x $current_point_x
+ set prev_point_y $current_point_y
+ }
+ }
+ # Evaluate the tcl_command
+ eval "lappend object_list \[polygon make $num_vertices $tcl_command\]"
+ # flush stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract filled polylines from the matlab $source_stack
+ if [regexp {(\d+)\s+MP} $line matchresult sub1] {
+ set num_vertices $sub1
+ set num_args [expr $num_vertices*2]
+ # extract the vertices list of the polyline
+ set re "\\x0a+\\s*((?:\-?\\d+\\x20*\\x0a*)+)\\s+$num_vertices\\s+MP"
+ if [regexp $re $source_stack matchresult sub1] then {
+ # replace 1+ spaces by the ":" separator
+ regsub -all {\s+} $sub1 ":" sub1
+ # split $sub1 based on the ":" separator
+ set polyline_vertices [split $sub1 ":"]
+ # the polyline_vertices list contains all vertices
+ # --> {<undefined data> x1 y1 x2 y2 ... xn yn}
+ } else {
+ puts "Error in filled polyline regular expression. Exiting..."
+ return -1
+ }
+ # convert the arguments to the xcircuit coordinate format.
+ # The matlab polyline coordinates are relative to each other,
+ # starting for the last value of the postscript stack.
+ # XCircuit needs absolute coordinates for the polyline vertices.
+ # Some recalculation is thus needed to obtain absolute coordinates.
+ for {set i [expr $num_args-4]} {$i>=0} {incr i -2} {
+ # calculate x-coordinates
+ set prev_point_x [lindex $polyline_vertices $i]
+ set current_point_x [lindex $polyline_vertices [expr $i+2]]
+ lset polyline_vertices $i [expr $prev_point_x+$current_point_x]
+ # calculate y-coordinates
+ set prev_point_y [lindex $polyline_vertices [expr $i+1]]
+ set current_point_y [lindex $polyline_vertices [expr $i+3]]
+ lset polyline_vertices [expr $i+1] [expr $prev_point_y+$current_point_y]
+ }
+ # Rescaling feature. Should be re-implemented in a decent way
+ for {set i 0} {$i<$num_args} {incr i 1} {
+ lset polyline_vertices $i [expr int([lindex $polyline_vertices $i]*$scalefactor)]
+ }
+ # Flip the y-axis coordinates. XCircuit's coordinate system seems to use
+ # the left hand rule.
+ for {set i 1} {$i<$num_args} {incr i 2} {
+ lset polyline_vertices $i [expr [lindex $polyline_vertices $i]*-1]
+ }
+ # create the tcl command and draw the polygon
+ set prev_point_x 0
+ set prev_point_y 0
+ set num_vertices 0
+ set tcl_command ""
+ for {set i 0} {$i<$num_args} {incr i 2} {
+ # the number of vertices xcircuit can handle is limited to 250
+ if {$num_vertices > 200} then break
+ # extract the current x- and y-coordinates
+ set current_point_x [lindex $polyline_vertices $i]
+ set current_point_y [lindex $polyline_vertices [expr $i+1]]
+ # drop the current vertex if distance from previous point is too small
+ if { abs([expr $current_point_x - $prev_point_x]) < 2
+ && abs([expr $current_point_y - $prev_point_y]) < 2} then {
+ # drop the current vertex
+ continue
+ # add the current vertex to the tcl_command string
+ } else {
+ # increase the number of vertices in the tcl_command
+ incr num_vertices 1
+ # append the current vertex to the tcl_command string
+ # format: "polygon make N {x1 y1} {x2 y2} ... {xn yn}"
+ append tcl_command "\{$current_point_x $current_point_y\} "
+ # save the current vertex for future reference
+ set prev_point_x $current_point_x
+ set prev_point_y $current_point_y
+ }
+ }
+ # Evaluate the tcl_command. Only write if we have a valid color,
+ # different from white (white color index is 1 in xcircuit)
+ if {[color get] != 1} then {
+ eval "fill 100"
+ eval "lappend object_list \[polygon make $num_vertices $tcl_command\]"
+ eval "fill 0"
+ }
+ # flush stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract lines from the matlab $source_stack
+ set re "(\\d+)\\s+(\\d+)\\s+mt\\s+(\\d+)\\s+(\\d+)\\sL"
+ if [regexp $re $line matchresult sub1 sub2 sub3 sub4] then {
+ set x1 [expr int($sub1*$scalefactor)]
+ set y1 [expr int(-$sub2*$scalefactor)]
+ set x2 [expr int($sub3*$scalefactor)]
+ set y2 [expr int(-$sub4*$scalefactor)]
+ # Create the tcl command and draw the line
+ eval "lappend object_list \[polygon make 2 {$x1 $y1} {$x2 $y2}\]"
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract points from the matlab $source_stack
+ set re "(\\d+)\\s+(\\d+)\\s+PD"
+ if [regexp $re $line matchresult sub1 sub2] then {
+ set x1 [expr int($sub1*$scalefactor)]
+ set y1 [expr -int($sub2*$scalefactor)]
+ set dotsize [expr int(15*$scalefactor)]
+ # concatenate all lines in one vector
+ eval "fill 100"
+ eval "lappend object list \[arc make \{$x1 $y1\} $dotsize\]"
+ eval "fill 0"
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract axes labels from the matlab $source_stack
+ set re "(\\d+)\\s+(\\d+)\\s+mt\\s*\\n\\((.*)\\)"
+ if [regexp $re $source_stack matchresult sub1 sub2 sub3] then {
+ set x1 [expr int($sub1*$scalefactor)]
+ set y1 [expr -int($sub2*$scalefactor)]
+ set labeltext $sub3
+ # some experimental rescaling. Should be reimplemented in the future
+ set textsize [expr $matlab_textsize*4*$scalefactor/168]
+ # concatenate all text in one vector
+ # also remove empty labels (causes segfault in xcircuit-3.4.26)
+ if {$bold == 1 && [regexp {[^\s]+} $labeltext]} then {
+ eval "label style bold"
+ eval "label scale $textsize"
+ eval "lappend object_lsit \[label make normal \"$labeltext\" \{$x1 $y1\}\]"
+ } elseif [regexp {[^\s]+} $labeltext] {
+ eval "label scale $textsize"
+ eval "lappend object_list \[label make normal \"$labeltext\" \{$x1 $y1\}\]"
+ }
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract color definitions from the matlab $source_stack
+ set re "(\\/c\\d+\\s+\\{\\s\\d+\\.\\d+\\s+\\d+\\.\\d+\\s+\\d+\\.\\d+\\s+sr\\}\\sbdef)"
+ if [regexp $re $source_stack matchresult sub1] then {
+ # add color definition to library
+ append colordefs $sub1
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract the text size from the matlab $source_stack
+ set re "(\\d+) FMSR"
+ if [regexp $re $line matchresult sub1] then {
+ set matlab_textsize $sub1
+ append colordefs $sub1
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Retrieve the color specified on the matlab $source_stack
+ set re "(c\\d+)"
+ if [regexp $re $line matchresult sub1] then {
+ # extract color from the library
+ set re "\\/$sub1\\s+\\{\\s(\\d+\\.\\d+)\\s+(\\d+\\.\\d+)\\s+(\\d+\\.\\d+)\\s+sr\\}\\sbdef"
+ if [regexp $re $colordefs matchresult sub1 sub2 sub3] then {
+ set red [expr int($sub1*255)]
+ set green [expr int($sub2*255)]
+ set blue [expr int($sub3*255)]
+ set rgb [dec2rgb $red $green $blue]
+ # add color to xcircuit output
+ set color_index [eval "color add $rgb"]
+ eval "color set $color_index"
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ }
+ # Extract grayscale colors from the matlab $source_stack
+ set re "(\[0-9\]*\\.\[0-9\]+|\[0-9\]+)\\ssg"
+ if [regexp $re $line matchresult sub1] then {
+ set greylevel [expr int($sub1*255)]
+ set rgb [dec2rgb $greylevel $greylevel $greylevel]
+ # add color to xcircuit output
+ set color_index [eval "color add $rgb"]
+ eval "color set $color_index"
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ # Extract solid/dotted linestyle ftom the matlab $source_stack
+ set re "((?:SO)|(?:DO)|(?:DA)|(?:DD))"
+ if [regexp $re $line matchresult sub1] then {
+ if {$sub1 == "DO"} then {
+ eval "border dotted"
+ } elseif {$sub1 == "SO"} then {
+ eval "border solid"
+ } elseif {$sub1 == "DA"} then {
+ eval "border dashed"
+ } elseif {$sub1 == "DD"} then {
+ eval "border solid"
+ }
+ # clear the source stack
+ set source_stack ""
+ set line ""
+ }
+ }
+ puts " *** $file import OK";
+# >> end of foreach file
+}
+# >> end of proc matgen
+}
+
+# PART 4____________________________________________________
+# Extract from util-color.tcl
+# Copyright (c) 1998 Jeffrey Hobbs
+#
+# dec2rgb --
+#
+# See the file "license.terms" for information on usage and
+# redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+#
+# Takes a color name or dec triplet and returns a #RRGGBB color.
+# If any of the incoming values are greater than 255,
+# then 16 bit value are assumed, and #RRRRGGGGBBBB is
+# returned, unless $clip is set.
+#
+# Arguments:
+# r red dec value, or list of {r g b} dec value or color name
+# g green dec value, or the clip value, if $r is a list
+# b blue dec value
+# clip Whether to force clipping to 2 char hex
+# Results:
+# Returns a #RRGGBB or #RRRRGGGGBBBB color
+#
+proc dec2rgb {r {g 0} {b UNSET} {clip 0}} {
+ if {![string compare $b "UNSET"]} {
+ set clip $g
+ if {[regexp {^-?(0-9)+$} $r]} {
+ foreach {r g b} $r {break}
+ } else {
+ foreach {r g b} [winfo rgb . $r] {break}
+ }
+ }
+ set max 255
+ set len 2
+ if {($r > 255) || ($g > 255) || ($b > 255)} {
+ if {$clip} {
+ set r [expr {$r>>8}]; set g [expr {$g>>8}]; set b [expr {$b>>8}]
+ } else {
+ set max 65535
+ set len 4
+ }
+ }
+ return [format "#%.${len}x%.${len}x%.${len}x" \
+ [expr {($r>$max)?$max:(($r<0)?0:$r)}] \
+ [expr {($g>$max)?$max:(($g<0)?0:$g)}] \
+ [expr {($b>$max)?$max:(($b<0)?0:$b)}]]
+}
+
diff --git a/lib/tcl/mousehint.tcl b/lib/tcl/mousehint.tcl
new file mode 100644
index 0000000..9d1e8d4
--- /dev/null
+++ b/lib/tcl/mousehint.tcl
@@ -0,0 +1,104 @@
+#------------------------------------------------------------------------
+# Mouse button hints---written by James Vernon March 2006
+#------------------------------------------------------------------------
+
+#------------------------------------------------------------------------
+# Write 3 strings corresponding to the 3 mouse button functions
+# Use the "bindkey -compat" to get the current button bindings
+#------------------------------------------------------------------------
+
+proc xcircuit::automousehint {window} {
+
+ set frame [winfo top $window]
+ set btext [bindkey $window -compat Button1]
+ ${frame}.infobar.mousehints.left configure -text $btext
+ set btext [bindkey $window -compat Button2]
+ ${frame}.infobar.mousehints.middle configure -text $btext
+ set btext [bindkey $window -compat Button3]
+ ${frame}.infobar.mousehints.right configure -text $btext
+}
+
+#------------------------------------------------------------------------
+# Creates a canvas showing the 3 buttons of a 3 button mouse
+# and adds labels that can contain strings telling the user what
+# the current function of those buttons is
+#------------------------------------------------------------------------
+
+proc xcircuit::mousehint_create {name} {
+
+ frame ${name}.infobar.mousehints -background beige
+
+ label ${name}.infobar.mousehints.title -background beige -foreground brown4 \
+ -anchor e -text "Button bindings: "
+ button ${name}.infobar.mousehints.left -background beige -relief groove
+ button ${name}.infobar.mousehints.middle -background beige -relief groove
+ button ${name}.infobar.mousehints.right -background beige -relief groove
+
+ grid ${name}.infobar.mousehints.title -row 0 -column 0 -sticky news
+ grid ${name}.infobar.mousehints.left -row 0 -column 1 -sticky news
+ grid ${name}.infobar.mousehints.middle -row 0 -column 2 -sticky news
+ grid ${name}.infobar.mousehints.right -row 0 -column 3 -sticky news
+
+ grid columnconfigure ${name}.infobar.mousehints 0 -weight 0
+ grid columnconfigure ${name}.infobar.mousehints 1 -weight 0
+ grid columnconfigure ${name}.infobar.mousehints 2 -weight 0
+ grid columnconfigure ${name}.infobar.mousehints 3 -weight 0
+
+ mousehint_bindings ${name} ${name}.infobar.mousehints
+
+ xcircuit::mousehint_show ${name}
+}
+
+#------------------------------------------------------------------------
+# Displays the mouse_canvas that shows a picture of the 3
+# buttons on a mouse in the top right corner of the top level window
+# and moves the menubar.message widget under the menu buttons
+#------------------------------------------------------------------------
+
+proc xcircuit::mousehint_show { name } {
+
+ pack forget ${name}.infobar.message2
+ pack ${name}.infobar.mousehints -padx 2 -side left -ipadx 6 -fill y
+ pack ${name}.infobar.message2 -side left -padx 2 -ipadx 6 -expand true -fill both
+
+ bind ${name}.infobar.mode <ButtonPress-1> "::xcircuit::mousehint_hide ${name}"
+}
+
+#------------------------------------------------------------------------
+# Hides the mouse_canvas that shows a picture of the 3
+# buttons on a mouse and moves the menubar.message label
+# back in its place.
+#------------------------------------------------------------------------
+
+proc xcircuit::mousehint_hide { name } {
+
+ pack forget ${name}.infobar.mousehints
+ bind ${name}.infobar.mode <ButtonPress-1> "::xcircuit::mousehint_show ${name}"
+}
+
+#------------------------------------------------------------------------
+# Highlights buttons on the mouse_canvas when the user
+# presses the corresponding mouse buttons
+# Seems unnescesary, but without it who would guess that those
+# rectangles are supposed to look like mouse buttons?
+#------------------------------------------------------------------------
+
+proc xcircuit::mousehint_bindings { name mouse_frame } {
+
+ bind all <Button-1> "${mouse_frame}.left configure -state active ; \
+ xcircuit::automousehint ${name}.mainframe.mainarea.drawing"
+ bind all <Button-2> "${mouse_frame}.middle configure -state active ; \
+ xcircuit::automousehint ${name}.mainframe.mainarea.drawing"
+ bind all <Button-3> "${mouse_frame}.right configure -state active ; \
+ xcircuit::automousehint ${name}.mainframe.mainarea.drawing"
+
+ bind all <ButtonRelease-1> "${mouse_frame}.left configure -state normal"
+ bind all <ButtonRelease-2> "${mouse_frame}.middle configure -state normal"
+ bind all <ButtonRelease-3> "${mouse_frame}.right configure -state normal"
+
+ bind all <KeyPress> "xcircuit::automousehint ${name}.mainframe.mainarea.drawing"
+
+ bind ${mouse_frame}.title <ButtonPress-1> "::xcircuit::mousehint_hide ${name}"
+}
+
+#------------------------------------------------------------------------
diff --git a/lib/tcl/ngspice.tcl b/lib/tcl/ngspice.tcl
new file mode 100644
index 0000000..af81ed1
--- /dev/null
+++ b/lib/tcl/ngspice.tcl
@@ -0,0 +1,27 @@
+# ngspice.tcl
+#
+# This script creates the active loop for the background ngspice
+# simulator, and creates buttons for various simulator controls.
+#
+# Labels wishing to access spice variables can use, e.g.:
+# spice send "print TIME\[$STEP\]"
+
+proc ngsim {} {
+ if {![catch {spice break}]} {
+ refresh;
+ spice resume
+ after 500 ngsim ;# update at 1/2 second intervals
+ }
+}
+
+proc startspice {} {
+ spice start
+ spice run
+ after 500 ngsim
+}
+
+proc stopspice {} {
+ after cancel ngsim
+ spice break;
+ refresh;
+}
diff --git a/lib/tcl/panzoom.tcl b/lib/tcl/panzoom.tcl
new file mode 100644
index 0000000..c672ea9
--- /dev/null
+++ b/lib/tcl/panzoom.tcl
@@ -0,0 +1,6 @@
+# panzoom.tcl --- rebinds keys Z and z for a zoom style in which
+# the page is centered on the cursor position
+# (provded by Ed Casas, 9/4/03)
+
+xcircuit::keybind Z { pan here ; zoom in }
+xcircuit::keybind z { pan here ; zoom out }
diff --git a/lib/tcl/pcbout.tcl b/lib/tcl/pcbout.tcl
new file mode 100644
index 0000000..c9c5ebe
--- /dev/null
+++ b/lib/tcl/pcbout.tcl
@@ -0,0 +1,326 @@
+#-----------------------------------------------------------------------
+# Set of Tcl procedures to convert an xcircuit schematic to an initial
+# (unrouted) PCB layout.
+#
+# Written by Tim Edwards for MultiGiG Inc., February 27, 2004.
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Procedure to convert xcircuit strings to plain ASCII text.
+#-----------------------------------------------------------------------
+
+proc string_to_text {xcstr} {
+ set rst ""
+ foreach sst $xcstr {
+ switch -glob $sst {
+ Text* {
+ set atxt [lindex $sst 1]
+ append rst $atxt
+ }
+ }
+ }
+ return $rst
+}
+
+#-----------------------------------------------------------------------
+# Procedure to map XCircuit names to PBC names. This is just a hack.
+# Ideally, we would want an XCircuit library whose names map directly
+# into the PCB library, so no translation is needed. There would be
+# parameters for the description line, package line, and name line to
+# be passed to the program.
+#-----------------------------------------------------------------------
+# Currently, understands 7400 series devices from the "diplib" and
+# "newdiplib" libraries. ("DIP7400" or "dil_7400" maps to "7400_dil",
+# and so forth).
+#-----------------------------------------------------------------------
+# Understanding of axial and SMD resistors and capacitors added
+# 1/4/05. This is somewhat hacked-up. PCB has it backwards: The
+# package type should be, e.g., "SMD_SIMPLE_603", not "SMD_SIMPLE",
+# while the name should be "smd_resistor", not "smd_resistor_603".
+#-----------------------------------------------------------------------
+
+proc xcirc_to_pcbname {xcname {pkgparam ""}} {
+ switch -glob $xcname {
+ dil_* {
+ set lstyp [string range $xcname 4 end]
+ set rst "${lstyp}_dil"
+ }
+ DIP* {
+ set lstyp [string range $xcname 3 end]
+ set rst "${lstyp}_dil"
+ }
+ res* -
+ Res* {
+ switch -glob $pkgparam {
+ SMD* {
+ set lpos [string last "_" $pkgparam]
+ set pkgsize [string range $pkgparam $lpos end]
+ set rst "smd_resistor$pkgsize"
+ }
+ AXIAL* {
+ set lpos [string last "_" $pkgparam]
+ set pkgsize [string range $pkgparam $lpos end]
+ set rst "generic_resistor_axial$pkgsize"
+ }
+ default {
+ set rst "generic_resistor_axial_400"
+ }
+ }
+ }
+ cap* -
+ Cap* {
+ switch -glob $pkgparam {
+ SMD* {
+ set lpos [string last "_" $pkgparam]
+ set pkgsize [string range $pkgparam $lpos end]
+ set rst "smd_capacitor$pkgsize"
+ }
+ AXIAL* {
+ set lpos [string last "_" $pkgparam]
+ set pkgsize [string range $pkgparam $lpos end]
+ set rst "generic_capacitor_axial$pkgsize"
+ }
+ default {
+ set rst "generic_capacitor_axial_400"
+ }
+ }
+ }
+ default {set rst $xcname}
+ }
+ return $rst
+}
+
+#-----------------------------------------------------------------------
+# Procedure to map XCircuit names to PCB package names.
+#-----------------------------------------------------------------------
+# Currently, understands DIP packages (7400 series)
+#-----------------------------------------------------------------------
+
+proc xcirc_to_pkgname {pkgparam numpins} {
+ switch -glob $pkgparam {
+ DIP {set rst "DIP$numpins"}
+ SMD* {set rst SMD_SIMPLE}
+ AXIAL* {set rst AXIAL_LAY}
+ default {set rst $pkgparam}
+ }
+ return $rst
+}
+
+#-----------------------------------------------------------------------
+# Add an element to the (open) pcb file
+#-----------------------------------------------------------------------
+
+proc add_pcb_element {fileId element numpins devname pkgparam} {
+ global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
+ set pcbelem [xcirc_to_pcbname $element $pkgparam]
+ set pkgname [xcirc_to_pkgname $pkgparam $numpins]
+ set elist [exec ${PCBLIBDIR}/${GEN_ELEM_SCRIPT} ${PCBLIBDIR} ${SUBDIR} \
+ $pcbelem $element $pkgname]
+ eval [subst {regsub {""} \$elist {"$devname"} efinal}]
+ puts stdout "IN: QueryLibrary.sh pcblib $pcbelem $element $pkgname"
+ puts stdout "OUT: $efinal"
+ puts $fileId $efinal
+}
+
+#-----------------------------------------------------------------------
+# Generate elements from the xcircuit schematic
+#
+# This assumes a pcb-like schematic, with a flat schematic. Needs to be
+# expanded to handle hierarchical schematics. This will work with
+# multipage schematics.
+#
+# For now, this only supports 7400 series devices, so we can assume that
+# the string is "U". However, different packages of the devices can be
+# specified, and any device name can be processed as long as it has a
+# valid package type (DIL, SO, US, etc.).
+#
+# Extended 1/4/05 to handle resistors and capacitors.
+#-----------------------------------------------------------------------
+
+proc gen_pcb_elements {fileId} {
+ set numpins 0
+ set pkgname "unknown"
+
+ set nl [netlist make]
+ set ckt [lindex $nl 3]
+
+ foreach subckt $ckt {
+ set ename "default"
+ # MUST parse in order: name, device, (everything else)
+ foreach {key value} $subckt {
+ switch -- $key {
+ name {
+ set ename $value
+ break;
+ }
+ }
+ }
+ foreach {key value} $subckt {
+ switch -- $key {
+ devices {
+ foreach dev $value {
+ foreach tpart $dev {
+ set ascl [string_to_text $tpart]
+ set cpos [string first "pcb:" $ascl]
+ if {$cpos >= 0} {
+ set defpfix($ename) [string range $ascl 4 end]
+ break
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach {key value} $subckt {
+ switch -- $key {
+ name {set ename $value}
+ ports {set defpins($ename) [expr {[llength $value] / 2}]}
+ parameters {
+ foreach {pkey pval} $value {
+ switch -- $pkey {
+ idx -
+ v1 {
+ set devnum [string_to_text $pval]
+ set defnum($ename) "${devnum}"
+ }
+ pkg {
+ set defpkg($ename) [string_to_text $pval]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ set top [lindex $ckt [expr {[llength $ckt] - 1}]]
+ foreach {key calllist} $top {
+ if {$key == "calls"} {break}
+ }
+ set devnum 0
+ foreach call $calllist {
+ set numpins 0
+ incr devnum
+ set devpfix "U"
+ set devname "U?"
+ set pkgname "unknown"
+ set ename "default"
+ foreach {key value} $call {
+ switch -- $key {
+ name {
+ set ename $value
+ catch {set numpins $defpins($ename)}
+ catch {set devpfix $defpfix($ename)}
+ catch {set pkgname $defpkg($ename)}
+ catch {set locdevnum $defnum($ename); \
+ set devname ${devpfix}${locdevnum}}
+ }
+ ports {set numpins [expr {[llength $value] / 2}]}
+ parameters {
+ foreach {pkey pval} $value {
+ switch -- $pkey {
+ idx -
+ v1 {
+ set locdevnum [string_to_text $pval]
+ set devname "${devpfix}${locdevnum}"
+ }
+ pkg {
+ set pkgname [string_to_text $pval]
+ }
+ }
+ }
+ }
+ }
+ }
+ if {[string range $devname end end] == "?"} {set devname "${devpfix}${devnum}"}
+ add_pcb_element $fileId $ename $numpins $devname $pkgname
+ }
+}
+
+#-----------------------------------------------------------------------
+# Tcl procedure to write an xcircuit layout to an initial PCB layout.
+#-----------------------------------------------------------------------
+
+proc xcirc_to_pcb {filename} {
+ global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
+
+ # Open the pcb file and generate a valid header
+ set fileId [open $filename w 0600]
+ puts $fileId "PCB(\"\" 6000 5000)"
+ puts $fileId ""
+ puts $fileId "Grid(10 0 0 0)"
+ puts $fileId "Cursor(160 690 3)"
+ puts $fileId "Flags(0x00000000000006d0)"
+ puts $fileId "Groups(\"1,s:2,c:3:4:5:6:7:8\")"
+ puts $fileId "Styles(\"Signal,10,55,28,10:Power,25,60,35,10:Fat,40,60,35,10:Skinny,8,36,20,7\")"
+ puts $fileId ""
+
+ # Generate elements
+ gen_pcb_elements $fileId
+
+ # Generate a valid trailer and close the pcb file
+
+ puts $fileId ""
+ puts $fileId "Layer(1 \"solder\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(2 \"component\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(3 \"GND\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(4 \"power\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(5 \"signal1\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(6 \"signal2\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(7 \"unused\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(8 \"unused\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(9 \"silk\")"
+ puts $fileId "("
+ puts $fileId ")"
+ puts $fileId "Layer(10 \"silk\")"
+ puts $fileId "("
+ puts $fileId ")"
+ close $fileId
+}
+
+#-----------------------------------------------------------------------
+# Create a dialog for querying the name of the output layout file
+#-----------------------------------------------------------------------
+
+proc xcircuit::promptpcblayout {} {
+ .dialog.bbar.okay configure -command \
+ {xcirc_to_pcb [.dialog.textent.txt get]; wm withdraw .dialog}
+ .dialog.textent.title.field configure -text "Enter name for PCB layout:"
+ .dialog.textent.txt delete 0 end
+ set lname [xcircuit::page label]
+ append lname ".pcb"
+ .dialog.textent.txt insert 0 $lname
+ wm deiconify .dialog
+ focus .dialog.textent.txt
+}
+
+# These may be reset at any time. . .
+
+set PCBLIBDIR "/usr/local/share/pcb/"
+set SUBDIR "pcblib"
+set GEN_ELEM_SCRIPT "QueryLibrary.sh"
+
+#-----------------------------------------------------------------------
+# Add the PCB layout command to the XCircuit "Netlist" menu.
+#-----------------------------------------------------------------------
+
+set m .xcircuit.menubar.netlistbutton.netlistmenu
+$m add command -label "Create PCB Layout" -command {xcircuit::promptpcblayout}
+
+#-----------------------------------------------------------------------
diff --git a/lib/tcl/pkgIndex.tcl b/lib/tcl/pkgIndex.tcl
new file mode 100644
index 0000000..a727350
--- /dev/null
+++ b/lib/tcl/pkgIndex.tcl
@@ -0,0 +1,3 @@
+
+ package ifneeded app-xcircuit 3.6.39 \
+ [list source [file join $dir boot_xcircuit.tcl]]
diff --git a/lib/tcl/resource.tcl b/lib/tcl/resource.tcl
new file mode 100644
index 0000000..4700e97
--- /dev/null
+++ b/lib/tcl/resource.tcl
@@ -0,0 +1,78 @@
+#--------------------------------
+# XCircuit Resource setup for TCL
+#--------------------------------
+
+option add *xcircuit.width 1200
+option add *xcircuit.height 930
+option add *xcircuit*activeBackground #a07650
+option add *xcircuit*foreground #a07650
+option add *xcircuit*activeForeground beige
+option add *xcircuit*font -*-times-medium-r-normal--12-*
+
+option add *xcircuit1.width 900
+option add *xcircuit1.height 700
+option add *xcircuit1*activeBackground #a07650
+option add *xcircuit1*foreground #a07650
+option add *xcircuit1*activeForeground beige
+option add *xcircuit1*font -*-times-medium-r-normal--12-*
+
+option add *xcircuit2.width 700
+option add *xcircuit2.height 500
+option add *xcircuit2*activeBackground #a07650
+option add *xcircuit2*foreground #a07650
+option add *xcircuit2*activeForeground beige
+option add *xcircuit2*font -*-times-medium-r-normal--12-*
+
+option add *menubar.filebutton*background beige
+option add *menubar.editbutton*background beige
+option add *menubar.textbutton*background beige
+option add *menubar.optionsbutton*background beige
+option add *menubar.windowbutton*background beige
+option add *menubar.netlistbutton*background beige
+option add *menubar*font -*-times-bold-r-normal--12-*
+
+option add *librarymenu*activeBackground #805630
+option add *librarymenu*foreground #805630
+option add *librarymenu*activeForeground beige
+option add *librarymenu*font -*-times-medium-r-normal--12-*
+option add *librarymenu*background beige
+
+option add *pagemenu*activeBackground #805630
+option add *pagemenu*foreground #805630
+option add *pagemenu*activeForeground beige
+option add *pagemenu*font -*-times-medium-r-normal--12-*
+option add *pagemenu*background beige
+
+option add *filelist*activeBackground #805630
+option add *filelist*foreground #805630
+option add *filelist*background white
+option add *filelist*activeForeground beige
+option add *filelist*font -*-times-medium-r-normal--12-*
+option add *filelist*txt*font -*-courier-medium-r-normal--12-*
+
+option add *output*activeBackground #805630
+option add *output*foreground #805630
+option add *output*background white
+option add *output*activeForeground beige
+option add *output*font -*-times-medium-r-normal--12-*
+option add *output*txt*font -*-courier-medium-r-normal--12-*
+
+option add *output.textent.butp.psmenu*background beige
+option add *output.textent.txtf.sizb.sizemenu*background beige
+option add *output.textent.buto.orientmenu*background beige
+
+option add *help*activeBackground #805630
+option add *help*foreground #805630
+option add *help*background white
+option add *help*activeForeground beige
+option add *help*font -*-times-medium-r-normal--12-*
+option add *help*txt*font -*-times-courier-r-normal--12-*
+
+option add *dialog*activeBackground #805630
+option add *dialog*foreground #805630
+option add *dialog*background white
+option add *dialog*activeForeground beige
+option add *dialog*font -*-times-medium-r-normal--12-*
+option add *dialog*txt*font -*-courier-medium-r-normal--12-*
+
+# End of Resource configuration file.
diff --git a/lib/tcl/selection.tcl b/lib/tcl/selection.tcl
new file mode 100644
index 0000000..8acc29f
--- /dev/null
+++ b/lib/tcl/selection.tcl
@@ -0,0 +1,6 @@
+# selection.tcl --- rebinds middle mouse button in text mode
+# to implement a clipboard paste.
+
+xcircuit::keybind <Button-2> { if {[eventmode] == "text" || \
+ [eventmode] == "etext"} {label insert text "[selection get]"} else { \
+ standardaction %b down %s}}
diff --git a/lib/tcl/sinusoid.tcl b/lib/tcl/sinusoid.tcl
new file mode 100644
index 0000000..1e74e7e
--- /dev/null
+++ b/lib/tcl/sinusoid.tcl
@@ -0,0 +1,11 @@
+proc sinusoid {a b {c 1.0}} {
+ set mylist {}
+ for {set t 0} {$t < [expr int(50.0 * $c)]} {incr t} {
+ set x [expr int($b * $t / 50.0)]
+ set y [expr int($a * sin(2 * 3.1415926 * $t / 50.0))]
+ lappend mylist [list $x $y]
+ }
+ set handle [eval polygon make [llength $mylist] $mylist]
+ refresh
+ return $handle
+}
diff --git a/lib/tcl/sue_xc.tcl b/lib/tcl/sue_xc.tcl
new file mode 100644
index 0000000..695cb0b
--- /dev/null
+++ b/lib/tcl/sue_xc.tcl
@@ -0,0 +1,383 @@
+#------------------------------------------
+# sue_xc.tcl
+#------------------------------------------
+# This script should be sourced into
+# XCircuit and provides the capability to
+# translate .sue files into XCircuit
+# schematics. This script works properly
+# with XCircuit version 3.2.24 or newer.
+#------------------------------------------
+# The primary routine is "make_sue_all",
+# which is a TCL procedure to be run from
+# the XCircuit command line in the directory
+# containing .sue format files. Without
+# options, it creates a single XCircuit
+# PostScript output file "sue_gates.ps",
+# containing all of the gate symbols and
+# associated schematics in a single file.
+#------------------------------------------
+# Written by R. Timothy Edwards
+# 8/23/04
+# MultiGiG, Inc.
+# Scotts Valley, CA
+#------------------------------------------
+
+global fscale
+set fscale 1.6
+
+#------------------------------------------------------------
+# scale an {x y} list value from SUE units to XCircuit units
+#------------------------------------------------------------
+
+proc scale_coord {coord} {
+ global fscale
+ set x [lindex $coord 0]
+ set y [lindex $coord 1]
+ set newc [lreplace $coord 0 1 [expr {int($x * $fscale)}] \
+ [expr {int(-$y * $fscale)}]]
+ return $newc
+}
+
+#------------------------------------------------------------
+# make and make_wire: create the schematic elements
+#------------------------------------------------------------
+
+proc make {type args} {
+ global fscale
+
+ if {[llength $args] == 1} {
+ set args [lindex $args 0]
+ }
+
+ # default values
+ set flipped {}
+ set angle 0
+ set width 1
+ set length 1
+ set name bad_element
+ set origin {0 0}
+ set instance_params {}
+
+ foreach {key value} $args {
+ switch -- $key {
+ -orient {
+ switch -- $value {
+ RXY {
+ set angle 180
+ }
+ RX {
+ set flipped horizontal
+ }
+ RY {
+ set flipped vertical
+ set angle 180
+ }
+ R270 {
+ set angle 270
+ }
+ R90 {
+ set angle 90
+ }
+ R0 {
+ # do nothing
+ }
+ }
+ }
+ -W {
+ set width $value
+ }
+ -L {
+ set length $value
+ }
+ -origin {
+ set origin $value
+ }
+ -name {
+ set name $value
+ }
+ -text {
+ set name $value
+ }
+ default {
+ lappend instance_params [list [string range $key 1 end] $value]
+ }
+ }
+ }
+
+ set origin [scale_coord $origin]
+
+ switch -- $type {
+ pmos {
+ set newgate [instance make pMOS $origin]
+ # SUE pMOS is wider than xcircuit pMOS.
+ set x1 [lindex $origin 0]
+ set s1 [lreplace $origin 0 0 [expr {$x1 - 64}]]
+ set s2 [lreplace $origin 0 0 [expr {$x1 - 96}]]
+ set newpoly [polygon make 2 $s1 $s2]
+ select $newgate
+ parameter set width $width -forward
+ parameter set length $length -forward
+ select [list $newgate $newpoly]
+ rotate $angle $origin
+ if {$flipped != {}} {
+ select [list $newgate $newpoly]
+ flip $flipped $origin
+ }
+ }
+
+ nmos {
+ set newgate [instance make nMOS $origin]
+ # SUE nMOS is wider than xcircuit nMOS.
+ set x1 [lindex $origin 0]
+ set s1 [lreplace $origin 0 0 [expr {$x1 - 64}]]
+ set s2 [lreplace $origin 0 0 [expr {$x1 - 96}]]
+ set newpoly [polygon make 2 $s1 $s2]
+ select $newgate
+ parameter set width $width -forward
+ parameter set length $length -forward
+ select [list $newgate $newpoly]
+ rotate $angle $origin
+ if {$flipped != {}} {
+ select [list $newgate $newpoly]
+ flip $flipped $origin
+ }
+ }
+
+ input -
+ output -
+ name_net -
+ name_net_s {
+ set newtext [label make pin $name $origin]
+ rotate $newtext $angle $origin
+ if {$flipped != {}} {
+ flip $newtext $flipped $origin
+ }
+ }
+
+ global {
+ set newtext [label make global $name $origin]
+ rotate $newtext $angle $origin
+ if {$flipped != {}} {
+ flip $newtext $flipped $origin
+ }
+ }
+
+ text {
+ set newtext [list $name]
+ while {[set rp [string first \n $newtext]] >= 0} {
+ set newtext [string replace $newtext $rp $rp "\} \{return\} \{"]
+ set rp [string first \n $newtext]
+ }
+ set newtext [label make normal $newtext $origin]
+ rotate $newtext $angle $origin
+ if {$flipped != {}} {
+ flip $newtext $flipped $origin
+ }
+ }
+
+ # Default behavior is to generate an object instance of the
+ # given name. This assumes that these are only objects that
+ # have been defined in .sue files already.
+
+ default {
+ set newgate [instance make $type $origin]
+ select $newgate
+ rotate $angle $origin
+ if {$flipped != {}} {
+ select $newgate
+ flip $flipped $origin
+ }
+ if {$instance_params != {}} {
+ select $newgate
+ foreach pair $instance_params {
+ set key [lindex $pair 0]
+ set value [lindex $pair 1]
+ parameter set $key $value -forward
+ }
+ deselect
+ }
+ }
+ }
+ deselect
+}
+
+#------------------------------------------------------------
+# Draw text on the schematic
+#------------------------------------------------------------
+
+proc make_text {args} {
+ make text $args
+}
+
+#------------------------------------------------------------
+# Draw a wire into the schematic
+#------------------------------------------------------------
+
+proc make_wire {x1 y1 x2 y2} {
+ global fscale
+ # Scale the origin from SUE units to XCircuit units
+ set sx1 [expr {int($x1 * $fscale)}]
+ set sy1 [expr {int(-$y1 * $fscale)}]
+ set sx2 [expr {int($x2 * $fscale)}]
+ set sy2 [expr {int(-$y2 * $fscale)}]
+ polygon make 2 [list $sx1 $sy1] [list $sx2 $sy2]
+}
+
+proc make_line {args} {
+ eval "make_wire $args"
+}
+
+#------------------------------------------------------------
+# icon_*: create the symbol
+#------------------------------------------------------------
+
+#------------------------------------------------------------
+# default parameters (deferred)
+#------------------------------------------------------------
+
+proc icon_setup {icon_args params} {
+ global icon_params
+ set icon_params [concat $icon_params $params]
+}
+
+#------------------------------------------------------------
+# pins
+#------------------------------------------------------------
+
+proc icon_term {args} {
+ set pintype "no_pin"
+ set origin {0 0}
+ set name "bad_pin_name"
+
+ foreach {key value} $args {
+ switch -- $key {
+ -type {
+ set pintype $value
+ }
+ -origin {
+ set origin $value
+ }
+ -name {
+ set name $value
+ }
+ }
+ }
+ set newtext [label make pin $name $origin]
+}
+
+#------------------------------------------------------------
+# instance parameters and symbol text labels
+#------------------------------------------------------------
+
+proc icon_property {args} {
+
+ set proptype {}
+ set origin {0 0}
+ set name "bad_parameter"
+
+ foreach {key value} $args {
+ switch -- $key {
+ -origin {
+ set origin $value
+ }
+ -name {
+ set name $value
+ }
+ -type {
+ set proptype $value
+ }
+ -size {
+ # label size. Ignore, for now.
+ }
+ -label {
+ label make normal "$value" [scale_coord $origin]
+ }
+ }
+ }
+}
+
+#------------------------------------------------------------
+# Line drawing on the symbol
+#------------------------------------------------------------
+
+proc icon_line {args} {
+ set coords {}
+ set i 0
+ foreach {x y} $args {
+ set s [scale_coord [list $x $y]]
+ lappend coords $s
+ incr i
+ }
+ eval "polygon make $i $coords"
+}
+
+#------------------------------------------------------------
+# Main routine: Load the .sue file for the indicated
+# gate. Draw the schematic and the (user library) symbol,
+# and associate them.
+#------------------------------------------------------------
+
+proc make_sue_gate {name} {
+ global icon_params
+ source ${name}.sue
+
+ # Go to a new page unless the current one is empty
+ while {[llength [object parts]] > 0} {
+ set p [page]
+ incr p
+ while {[catch {page $p}]} {
+ page make
+ }
+ }
+
+ # Evaluate the symbol. Generate the symbol in xcircuit.
+ # Then clear the page to make the schematic
+ set icon_params {}
+ eval "ICON_${name}"
+ set hlist [object parts]
+ object make $name $hlist
+ set hlist [object parts]
+ push $hlist
+ foreach pair $icon_params {
+ set key [lindex $pair 0]
+ set value [lindex $pair 1]
+ switch -- $key {
+ origin -
+ orient {
+ # Do nothing for now. These are library instance values
+ # in xcircuit, and could be set as such.
+ }
+ default {
+ parameter make substring $key [list $value]
+ }
+ }
+ }
+ pop
+ delete $hlist
+
+ eval "SCHEMATIC_${name}"
+ wm withdraw .select
+ schematic associate $name
+ zoom view
+}
+
+#------------------------------------------------------------
+# Top-level routine: Find all the .sue files in the
+# current directory and generate a library from them
+#------------------------------------------------------------
+
+proc make_all_sue {{name sue_gates}} {
+ set files [glob \*.sue]
+ foreach i $files {
+ set filename [file tail [file root $i]]
+ make_sue_gate $filename
+ page filename $name
+ page orientation 90
+ page encapsulation full
+ page fit true
+ if {[page scale] > 1.0} {
+ page fit false
+ page scale 1.0
+ }
+ }
+}
diff --git a/lib/tcl/symbol.tcl b/lib/tcl/symbol.tcl
new file mode 100644
index 0000000..8197978
--- /dev/null
+++ b/lib/tcl/symbol.tcl
@@ -0,0 +1,672 @@
+#---------------------------------------------------------------------------
+# symbol.tcl ---
+#
+# xcircuit Tcl script for generating
+# a canonical circuit symbol
+#
+# Tim Edwards 12/1/05 for MultiGiG
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Get the info label line declaring the text subcircuit, if one exists.
+#---------------------------------------------------------------------------
+
+proc xcircuit::getsubckttext {name} {
+ global XCOps
+
+ set curhandle [object handle]
+ set handle [page handle $name]
+ if {$curhandle != $handle} {schematic goto}
+
+ set pageparts [object $handle parts]
+
+ set itext {}
+ foreach j $pageparts {
+ set etype [element $j type]
+ if {$etype == "Label"} {
+ set ltype [label $j type]
+ if {$ltype == "info"} {
+ set itext [label $j text]
+ if {[string first ".subckt" $itext] >= 0} {
+ if {$curhandle != $handle} {symbol goto}
+ return $itext
+ }
+ }
+ }
+ }
+ return ""
+}
+
+#---------------------------------------------------------------------------
+# Create a matching symbol for a subcircuit page or SPICE file.
+#
+# This is a replacement for the procedure makesymbol in wrapper.tcl.
+# We make a sub-widget to list, change, and reorder the symbol pins,
+# similar to the "addliblist" procedure in wrapper.tcl
+#
+# Modified 1/5/06: If "filename" is non-null, then it points to a SPICE
+# netlist containing a subcircuit. A symbol is made to correspond to the
+# subcircuit definition, with a link to include the file.
+#
+# Modified 1/7/06: If "orderedpins" is non-null, then it contains the
+# list of pins in proper order.
+#---------------------------------------------------------------------------
+
+proc xcircuit::makesymbol {{filename ""} {orderedpins ""}} {
+ global XCOps
+
+ config suspend true ;# suspend graphics and change count
+
+ set techname [.dialog.techself.techselect cget -text]
+ set symbolname [.dialog.textent.txt get]
+ if {[string length $symbolname] == 0} {
+ set symbolname [page label]
+ if {[string length $symbolname] == 0 || [string first "Page " $symbolname] >= 0} {
+ puts stderr "Symbol/Schematic has no name!"
+ consoleup
+ return
+ }
+ }
+
+ if {[string first :: $symbolname] >= 0} { ;# symbolname has tech name embedded
+ set techname ""
+ } elseif {[string first ( $techname] >= 0} { ;# "(user)" specified
+ set techname "::"
+ } elseif {[string first :: $techname] < 0} {
+ set techname "${techname}::"
+ }
+
+ # If "filename" is specified then we have a netlist, not a schematic.
+ # Therefore, create an object but don't use xcircuit::symbol
+
+ if {$filename == ""} {
+ xcircuit::symbol make ${techname}${symbolname} $XCOps(library);
+ set schematicname [schematic get]
+ set noschem 0
+ } else {
+ set schematicname $symbolname
+ set noschem 1
+ }
+
+ set pinspace 64
+ set halfspace [expr $pinspace / 2]
+ set qtrspace [expr $pinspace / 4]
+
+ # remove the old pin labels
+
+ set oldpinlabels [object parts]
+ foreach j $oldpinlabels {
+ delete $j
+ }
+ set leftpins [.dialog.pinself.left.list index end]
+ set toppins [.dialog.pinself.top.list index end]
+ set rightpins [.dialog.pinself.right.list index end]
+ set botpins [.dialog.pinself.bottom.list index end]
+
+ set hpins $leftpins
+ if {$rightpins > $leftpins} {set hpins $rightpins}
+ set vpins $toppins
+ if {$botpins > $toppins} {set vpins $botpins}
+
+ set boxwidth [expr ($vpins + 1) * $pinspace]
+ set boxheight [expr ($hpins + 1) * $pinspace]
+
+ set hwidth [expr $boxwidth / 2]
+ if {$hwidth < 256} {set hwidth 256}
+ set hheight [expr $boxheight / 2]
+ if {$hheight < 256} {set hheight 256}
+
+ set sbox [polygon make box "-$hwidth -$hheight" "$hwidth $hheight"]
+ set pinlabels {}
+
+ # If we didn't make a symbol using xcircuit::symbol, now is the time
+ # to generate the object.
+
+ if {$noschem == 1} {
+ select $sbox
+ set handle [object make ${techname}${symbolname} $XCOps(library)]
+ push $handle
+ }
+
+ # Ordered right->left->bottom->top, on logical grounds.
+
+ set x [expr $hwidth + $qtrspace]
+ set y [expr -($rightpins - 1) * $halfspace]
+ for {set j 0} {$j < $rightpins} {incr j} {
+ set tabx [expr $x - $qtrspace]
+ polygon make 2 "$x $y" "$tabx $y"
+ set pintext [.dialog.pinself.right.list get $j]
+ lappend pinlabels $pintext
+ set tlab [label make pin "$pintext" "$x $y"]
+ label $tlab justify left
+ label $tlab justify middle
+ set nlab [element $tlab copy relative "-$halfspace 0"]
+ label $nlab type normal
+ label $nlab justify right
+ incr y $pinspace
+ deselect selected
+ }
+ set x [expr -$hwidth - $qtrspace]
+ set y [expr -($leftpins - 1) * $halfspace]
+ for {set j 0} {$j < $leftpins} {incr j} {
+ set tabx [expr $x + $qtrspace]
+ polygon make 2 "$x $y" "$tabx $y"
+ set pintext [.dialog.pinself.left.list get $j]
+ lappend pinlabels $pintext
+ set tlab [label make pin "$pintext" "$x $y"]
+ label $tlab justify right
+ label $tlab justify middle
+ set nlab [element $tlab copy relative "$halfspace 0"]
+ label $nlab type normal
+ label $nlab justify left
+ incr y $pinspace
+ deselect selected
+ }
+ set y [expr -$hheight -$qtrspace]
+ set x [expr -($botpins - 1) * $halfspace]
+ for {set j 0} {$j < $botpins} {incr j} {
+ set taby [expr $y + $qtrspace]
+ polygon make 2 "$x $y" "$x $taby"
+ set pintext [.dialog.pinself.bottom.list get $j]
+ lappend pinlabels $pintext
+ set tlab [label make pin "$pintext" "$x $y"]
+ rotate $tlab 270
+ label $tlab justify right
+ label $tlab justify middle
+ set nlab [element $tlab copy relative "0 $halfspace"]
+ label $nlab type normal
+ label $nlab justify left
+ incr x $pinspace
+ deselect selected
+ }
+ set y [expr $hheight + $qtrspace]
+ set x [expr -($toppins - 1) * $halfspace]
+ for {set j 0} {$j < $toppins} {incr j} {
+ set taby [expr $y - $qtrspace]
+ polygon make 2 "$x $y" "$x $taby"
+ set pintext [.dialog.pinself.top.list get $j]
+ lappend pinlabels $pintext
+ set tlab [label make pin "$pintext" "$x $y"]
+ rotate $tlab 90
+ label $tlab justify right
+ label $tlab justify middle
+ set nlab [element $tlab copy relative "0 -$halfspace"]
+ label $nlab type normal
+ label $nlab justify left
+ incr x $pinspace
+ deselect selected
+ }
+
+ deselect selected
+ set nlab [label make "$symbolname" {0 0}]
+ label $nlab justify middle
+ label $nlab justify center
+ element $nlab color set blue
+
+ deselect selected
+ parameter make substring index "?"
+ parameter make substring class "X"
+ if {$schematicname == $symbolname} {
+ parameter make substring link "%n"
+ } else {
+ parameter make substring link "$schematicname"
+ }
+
+ set nlab [label make "{Parameter class} {Parameter index}" "0 -$pinspace"]
+ label $nlab justify center
+ element $nlab color set blue
+ deselect selected
+
+ # Determine if the schematic already has a "subckt" line. If so,
+ # attempt to arrange the pin ordering from it. If not, create one.
+ if {$noschem == 1} {
+ set subckttext ""
+ set pinlabels $orderedpins
+ } else {
+ set subckttext [xcircuit::getsubckttext $schematicname]
+ }
+
+ if {$subckttext == ""} {
+ set subckttext [list {Text "spice1:.subckt %n"}]
+ set pstring ""
+ foreach j $pinlabels {
+ if {[string length $pstring] > 60} {
+ lappend subckttext [subst {Text "$pstring"}]
+ lappend subckttext {Return}
+ set pstring "+"
+ }
+ set pstring [join [list $pstring "$j"]] ;# preserves whitespace
+ }
+ lappend subckttext [subst {Text "$pstring"}]
+
+ if {$noschem == 0} {
+ schematic goto
+ set bbox [join [page bbox all]]
+ set x [expr ([lindex $bbox 2] + [lindex $bbox 0]) / 2]
+ set y [expr [lindex $bbox 1] - $pinspace]
+ set nlab [label make info "$subckttext" "$x $y"]
+ label $nlab justify center
+ deselect selected
+ set y [expr $y - $pinspace]
+ set nlab [label make info "spice-1:.ends" "$x $y"]
+ symbol goto
+ }
+
+ set itext [list {Text "spice:"} {Parameter class} {Parameter index}]
+ set pstring ""
+ foreach j $pinlabels {
+ if {[string length $pstring] > 60} {
+ lappend itext [subst {Text "$pstring"}]
+ lappend itext {Return}
+ set pstring "+"
+ }
+ set pstring [join [list $pstring "%p$j"]] ;# preserves whitespace
+ }
+ set pstring [join [list $pstring "%n"]] ;# preserves whitespace
+ lappend itext [subst {Text "$pstring"}]
+ } else {
+ set itext [list {Text "spice:"} {Parameter class} {Parameter index}]
+ set pstring ""
+ foreach j [lrange [lindex $subckttext 0] 2 end] {
+ if {[string length $pstring] > 60} {
+ lappend itext [subst {Text "$pstring"}]
+ lappend itext {Return}
+ set pstring "+"
+ }
+ set pstring [join [list $pstring "%p$j"]] ;# preserves whitespace
+ }
+ set pstring [join [list $pstring "%n"]] ;# preserves whitespace
+ lappend itext [subst {Text "$pstring"}]
+ }
+
+ set y [expr -$hheight - 3 * $pinspace]
+
+ deselect selected
+ set nlab [label make info "$itext" "0 $y"]
+ label $nlab justify center
+
+ if {$noschem == 1} {
+ deselect selected
+ if {[string index $filename 0] != "/"} {
+ set filename [join [concat [pwd] $filename] "/"]
+ }
+ set y [expr -$hheight - 4 * $pinspace]
+ set itext [list {Text "spice@1:%F"}]
+ lappend itext [subst {Text "$filename"}]
+ set nlab [label make info "$itext" "0 $y"]
+ label $nlab justify center
+ deselect selected
+ pop
+ } else {
+ library $XCOps(library) compose
+ deselect selected
+ symbol goto
+ zoom view
+ }
+
+ config suspend false ;# unlocked state
+}
+
+#---------------------------------------------------------------------------
+# Get the list of pins for the object. If the schematic has a "subckt"
+# line, then we use the pin names from it, in order. If not, then we
+# compile a list of all unique pin labels and arrange them in dictionary
+# alphabetical order.
+#---------------------------------------------------------------------------
+
+proc xcircuit::getpinlist {schematicname} {
+ global XCOps
+
+ set subckttext [xcircuit::getsubckttext $schematicname]
+
+ if {$subckttext == {}} {
+ set pinlist {}
+ deselect selected
+ set objlist [object parts]
+
+ foreach j $objlist {
+ set etype [element $j type]
+ if {$etype == "Label"} {
+ set ltype [label $j type]
+ if {$ltype == "local" || $ltype == "global"} {
+
+ # Avoid netlist-generated pins by rejecting labels that
+ # don't start with a font specifier.
+
+ set subtype [lindex [lindex [lindex [label $j list] 0] 0] 0]
+ if {$subtype == "Font"} {
+ lappend pinlist [label $j text]
+ }
+ }
+ }
+ }
+ set pinlist [lsort -unique -dictionary $pinlist]
+ } else {
+ set pinlist [lrange [lindex $subckttext 0] 2 end]
+ }
+ deselect selected
+ return $pinlist
+}
+
+#---------------------------------------------------------------------------
+# Figure out which list has the selection
+#---------------------------------------------------------------------------
+
+proc xcircuit::getselectedpinwidget {} {
+ set w .dialog.pinself.left.list
+ set result [$w curselection]
+ if {$result != {}} {return $w}
+
+ set w .dialog.pinself.top.list
+ set result [$w curselection]
+ if {$result != {}} {return $w}
+
+ set w .dialog.pinself.right.list
+ set result [$w curselection]
+ if {$result != {}} {return $w}
+
+ set w .dialog.pinself.bottom.list
+ set result [$w curselection]
+ if {$result != {}} {return $w}
+}
+
+#---------------------------------------------------------------------------
+# Remove a pin from the pin list
+#---------------------------------------------------------------------------
+
+proc xcircuit::removeselectedpin {} {
+ set w [xcircuit::getselectedpinwidget]
+ if {$w != {}} {
+ set idx [$w curselection]
+ $w delete $idx
+ }
+}
+
+#---------------------------------------------------------------------------
+# Move a pin to the left side of the symbol
+#---------------------------------------------------------------------------
+
+proc xcircuit::movepinleft {} {
+ set w [xcircuit::getselectedpinwidget]
+ if {$w != {}} {
+ set idx [$w curselection]
+ set pinname [$w get $idx]
+ $w delete $idx
+ .dialog.pinself.left.list insert end $pinname
+ $w selection set $idx
+ }
+}
+
+#---------------------------------------------------------------------------
+# Move a pin to the top side of the symbol
+#---------------------------------------------------------------------------
+
+proc xcircuit::movepintop {} {
+ set w [xcircuit::getselectedpinwidget]
+ if {$w != {}} {
+ set idx [$w curselection]
+ set pinname [$w get $idx]
+ $w delete $idx
+ .dialog.pinself.top.list insert end $pinname
+ $w selection set $idx
+
+ }
+}
+
+#---------------------------------------------------------------------------
+# Move a pin to the right side of the symbol
+#---------------------------------------------------------------------------
+
+proc xcircuit::movepinright {} {
+ set w [xcircuit::getselectedpinwidget]
+ if {$w != {}} {
+ set idx [$w curselection]
+ set pinname [$w get $idx]
+ $w delete $idx
+ .dialog.pinself.right.list insert end $pinname
+ $w selection set $idx
+ }
+}
+
+#---------------------------------------------------------------------------
+# Move a pin to the bottom side of the symbol
+#---------------------------------------------------------------------------
+
+proc xcircuit::movepinbottom {} {
+ set w [xcircuit::getselectedpinwidget]
+ if {$w != {}} {
+ set idx [$w curselection]
+ set pinname [$w get $idx]
+ $w delete $idx
+ .dialog.pinself.bottom.list insert end $pinname
+ $w selection set $idx
+ }
+}
+
+#---------------------------------------------------------------------------
+# Create the pin arranger widget and add it to the dialog box.
+#---------------------------------------------------------------------------
+
+proc xcircuit::addpinarranger {w {pinlist {}}} {
+
+ frame ${w}.pinself
+ frame ${w}.pinself.left
+ frame ${w}.pinself.top
+ frame ${w}.pinself.right
+ frame ${w}.pinself.bottom
+
+ label ${w}.pinself.left.title -text "Left Pins"
+ label ${w}.pinself.top.title -text "Top Pins"
+ label ${w}.pinself.right.title -text "Right Pins"
+ label ${w}.pinself.bottom.title -text "Bottom Pins"
+
+ listbox ${w}.pinself.left.list
+ listbox ${w}.pinself.top.list
+ listbox ${w}.pinself.right.list
+ listbox ${w}.pinself.bottom.list
+
+ pack ${w}.pinself.left.title -side top
+ pack ${w}.pinself.left.list -side top -fill y -expand true
+ pack ${w}.pinself.top.title -side top
+ pack ${w}.pinself.top.list -side top -fill y -expand true
+ pack ${w}.pinself.right.title -side top
+ pack ${w}.pinself.right.list -side top -fill y -expand true
+ pack ${w}.pinself.bottom.title -side top
+ pack ${w}.pinself.bottom.list -side top -fill y -expand true
+
+ grid ${w}.pinself.left -row 0 -column 0 -sticky news -padx 1 -pady 1
+ grid ${w}.pinself.top -row 0 -column 1 -sticky news -padx 1 -pady 1
+ grid ${w}.pinself.right -row 0 -column 2 -sticky news -padx 1 -pady 1
+ grid ${w}.pinself.bottom -row 0 -column 3 -sticky news -padx 1 -pady 1
+
+ grid columnconfigure ${w}.pinself 0 -weight 1 -minsize 50
+ grid columnconfigure ${w}.pinself 1 -weight 1 -minsize 50
+ grid columnconfigure ${w}.pinself 2 -weight 1 -minsize 50
+ grid columnconfigure ${w}.pinself 3 -weight 1 -minsize 50
+
+ grid rowconfigure ${w}.pinself 0 -weight 1 -minsize 50
+
+ # Determine if the pinlist is fixed by either being taken from a "subckt"
+ # line in a schematic, or being taken from a "subckt" line in a SPICE deck.
+ # If so, we pass the ordered list to the symbol construction routine, and
+ # we also prevent symbol pins from being deleted.
+
+ if {$pinlist == {}} {
+ set pinlist [xcircuit::getpinlist [page label]]
+ if {[xcircuit::getsubckttext [page label]] != {}} {
+ set orderedpins 1
+ } else {
+ set orderedpins 0
+ }
+ } else {
+ set orderedpins 1
+ }
+
+ # Break the pinlist up into 4 parts
+
+ set rightpins [expr [llength $pinlist] / 2]
+ set bottompins [expr [llength $pinlist] - $rightpins]
+ set leftpins [expr $rightpins / 2]
+ set rightpins [expr $rightpins - $leftpins]
+ set toppins [expr $bottompins / 2]
+ set bottompins [expr $bottompins - $toppins]
+ incr leftpins $rightpins
+ incr bottompins $leftpins
+ incr toppins $bottompins
+
+ for {set k 0} {$k < $rightpins} {incr k} {
+ ${w}.pinself.right.list insert end [lindex $pinlist $k]
+ }
+ for {} {$k < $leftpins} {incr k} {
+ ${w}.pinself.left.list insert end [lindex $pinlist $k]
+ }
+ for {} {$k < $bottompins} {incr k} {
+ ${w}.pinself.bottom.list insert end [lindex $pinlist $k]
+ }
+ for {} {$k < $toppins} {incr k} {
+ ${w}.pinself.top.list insert end [lindex $pinlist $k]
+ }
+
+ pack ${w}.pinself -side top -anchor w -padx 20 -pady 5 -fill y -expand true
+
+ catch {
+ if {$orderedpins == 0} {
+ button ${w}.bbar.remove -text "Remove Pin" -bg beige -command \
+ {xcircuit::removeselectedpin}
+ }
+ button ${w}.bbar.moveleft -text "Move Left" -bg beige -command \
+ {xcircuit::movepinleft}
+ button ${w}.bbar.movetop -text "Move Top" -bg beige -command \
+ {xcircuit::movepintop}
+ button ${w}.bbar.moveright -text "Move Right" -bg beige -command \
+ {xcircuit::movepinright}
+ button ${w}.bbar.movebottom -text "Move Bottom" -bg beige -command \
+ {xcircuit::movepinbottom}
+ }
+
+ if {$orderedpins == 0} {
+ pack ${w}.bbar.remove -side left -ipadx 10
+ }
+ pack ${w}.bbar.moveleft -side left -ipadx 10
+ pack ${w}.bbar.movetop -side left -ipadx 10
+ pack ${w}.bbar.moveright -side left -ipadx 10
+ pack ${w}.bbar.movebottom -side left -ipadx 10
+}
+
+#---------------------------------------------------------------------------
+# Remove the pin arranger widget from the dialog box.
+#---------------------------------------------------------------------------
+
+proc xcircuit::removepinarranger {w} {
+ catch {
+ pack forget ${w}.pinself
+ destroy ${w}.pinself
+ pack forget ${w}.bbar.movebottom
+ pack forget ${w}.bbar.moveright
+ pack forget ${w}.bbar.movetop
+ pack forget ${w}.bbar.moveleft
+ pack forget ${w}.bbar.remove
+ }
+}
+
+#---------------------------------------------------------------------------
+# Redefine popupdialog to remove the pin arranger any time it is invoked.
+#---------------------------------------------------------------------------
+
+proc xcircuit::popupdialog {} {
+ xcircuit::removepinarranger .dialog
+ xcircuit::removelists .dialog
+ wm deiconify .dialog
+ focus .dialog.textent.txt
+}
+
+#---------------------------------------------------------------------------
+# Redefine the procedure for the "Make Matching Symbol" menu button.
+#---------------------------------------------------------------------------
+
+proc xcircuit::promptmakesymbol {{name ""}} {
+ global XCOps
+ .dialog.bbar.okay configure -command \
+ {if {[string first "Page " [page label]] >= 0} { \
+ page label [.dialog.textent.txt get]}; \
+ xcircuit::makesymbol; \
+ wm withdraw .dialog}
+ .dialog.textent.title.field configure -text "Confirm symbol name:"
+ .dialog.textent.txt delete 0 end
+ if {[string length $name] == 0 && [string first "Page " [page label]] < 0} {
+ set name [page label]}
+ .dialog.textent.txt insert 0 $name
+
+ xcircuit::popupdialog
+ xcircuit::addtechlist .dialog "Technology: "
+ xcircuit::addliblist .dialog "Place in: "
+ xcircuit::addpinarranger .dialog
+}
+
+#---------------------------------------------------------------------------
+# Routine which parses a spice file for the first .subckt line and
+# generates a symbol to match, with a "%F" escape pointing to the
+# spice file to include.
+#---------------------------------------------------------------------------
+
+proc xcircuit::spice2symbol {filename {subcktname ""}} {
+ global XCOps
+
+ set f [open $filename]
+ set infolabel ""
+ while {[gets $f line] >= 0} {
+ set dnline [string tolower $line]
+ if {[string first .subckt $dnline] == 0} {
+ while {[gets $f nextline] >= 0} {
+ if {[string first + $nextline] != 0} {break}
+ append line [string range $nextline 1 end]
+ }
+ set infolabel $line
+ if {$subcktname == ""} {break}
+ if {[string compare $subcktname [lindex $infolabel 1]] == 0} {break}
+ }
+ }
+ close $f
+
+ if {[string length $infolabel] == 0} {return}
+ set pinlabels [lrange $infolabel 2 end]
+
+ .dialog.bbar.okay configure -command \
+ "if {[string first {Page } [page label]] >= 0} { \
+ page label [.dialog.textent.txt get]}; \
+ xcircuit::makesymbol $filename [list $pinlabels]; \
+ wm withdraw .dialog"
+ .dialog.textent.title.field configure -text "Confirm symbol name:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 [lindex $infolabel 1]
+ xcircuit::popupdialog
+ xcircuit::addliblist .dialog "Place in: "
+ xcircuit::addpinarranger .dialog $pinlabels
+}
+
+#---------------------------------------------------------------------------
+# Procedure that creates the dialog to find a spice file to parse and
+# calls spice2symbol.
+#---------------------------------------------------------------------------
+
+proc xcircuit::promptspicesymbol {} {
+ global XCOps
+ .filelist.bbar.okay configure -command \
+ {xcircuit::spice2symbol [.filelist.textent.txt get] ; \
+ wm withdraw .filelist}
+ .filelist.listwin.win configure -data "cir"
+ .filelist.textent.title.field configure -text "Select spice file to parse:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+ xcircuit::removelists .filelist
+}
+
+#---------------------------------------------------------------------------
+# Add a menu item to invoke promptspicesymbol.
+#---------------------------------------------------------------------------
+
+set m .xcircuit.menubar.netlistbutton.netlistmenu
+$m insert 7 command -label "SPICE to symbol" -command {xcircuit::promptspicesymbol}
+unset m
+
+#---------------------------------------------------------------------------
diff --git a/lib/tcl/text.tcl b/lib/tcl/text.tcl
new file mode 100644
index 0000000..22c2241
--- /dev/null
+++ b/lib/tcl/text.tcl
@@ -0,0 +1,267 @@
+#---------------------------------------------------------------
+# Text regexp manipulation and text file import
+#
+# The core routine text_regexp takes either the selected
+# items or all items, searches them for text labels, and
+# makes the text replacement according to the regular
+# expression "searchstr" and the replacement text "replacestr".
+#
+#---------------------------------------------------------------
+
+# Declare the package by setting variable XCOps(module,text)
+set XCOps(module,text) 1
+
+proc text_regexp {searchstr replacestr {mode all}} {
+ switch -glob -- $mode {
+ select* {set partlist [select get]; set resel 1}
+ default {deselect selected; set partlist [object parts]; set resel 0}
+ }
+ config suspend true
+ undo series start
+ foreach j $partlist {
+ if {[element $j type] == "Label"} {
+ set labelparts [lindex [label $j list] 0]
+ set newparts {}
+ set modified 0
+ foreach k $labelparts {
+ if {[lindex $k 0] == "Text"} {
+ set tstring [lindex $k 1]
+ set newt [regsub [list $searchstr] $tstring $replacestr]
+ set newk [lreplace $k 1 1 $newt]
+ lappend newparts $newk
+ if {"$newt" != "$tstring"} {set modified 1}
+ } else {
+ lappend newparts $k
+ }
+ }
+ if {$modified == 1} {
+ label $j replace $newparts
+ }
+ }
+ }
+ if {$resel == 1} {catch {select $partlist}}
+ undo series end
+ refresh
+ config suspend false
+}
+
+#-----------------------------------------------------------------
+# Procedures to help with label generation (label autoincrement)
+#-----------------------------------------------------------------
+
+# autoincrement the first number found in the text of the indicated
+# label(s). Use argument "amount" to decrement, or increment by 10,
+# etc.
+#
+# example: xcircuit::textincrement selected
+
+proc xcircuit::textincrement {mode {amount 1} {position first}} {
+ switch -glob -- $mode {
+ select* {set handle [select get]; set resel 1}
+ default {deselect selected; set handle [object parts]; set resel 0}
+ }
+ config suspend true
+ undo series start
+
+ foreach h $handle {
+ if {[element $h type] == "Label"} {
+ set tlist [join [label $h list]]
+ set tlen [llength $tlist]
+ for {set i 0} {$i < $tlen} {incr i} {
+ set t [lindex $tlist $i]
+ set esc [lindex $t 0]
+ if {$esc == "Text"} {
+ set ltext [lindex $t 1]
+ set idx 0
+ if {"$position" == "last"} {
+ set result [regexp -indices -all {([+-]?)[0]*[[:digit:]]+} \
+ $ltext lmatch bounds]
+ set idx [lindex $bounds 0]
+ if {$result > 0} {
+ regexp -start $idx {([+-]?)([0]*)([[:digit:]]+)} $ltext \
+ lmatch pre zer num
+ }
+ } else {
+ set result [regexp {([+-]?)([0]*)([[:digit:]]+)} $ltext \
+ lmatch pre zer num]
+ }
+
+ if {$result > 0 && $num != ""} {
+ set num $pre$num
+ incr num $amount
+ if {$num < 0} {
+ set num [expr abs($num)]
+ set pre "-"
+ }
+ if {$num == 0 && "$pre" == "-"} {set pre ""}
+ if {"$position" == "last"} {
+ regsub -start $idx {[+-]?[0]*[[:digit:]]+} $ltext $pre$zer$num ltext
+ } else {
+ regsub {[+-]?[0]*[[:digit:]]+} $ltext $pre$zer$num ltext
+ }
+ set t [lreplace $t 1 1 $ltext]
+ set tlist [lreplace $tlist $i $i $t]
+ label $h replace $tlist
+ break
+ }
+ }
+ }
+ }
+ }
+ if {$resel == 1} {catch {select $handle}}
+ undo series end
+ refresh
+ config suspend false
+}
+
+proc xcircuit::autoincr {{value 1} {position first}} {
+ set e [eventmode]
+ set nopreselect 0
+ if {$e != "text" && $e != "etext" && $e != "epoly"} {
+ if {[select] == 0} {
+ set nopreselect 1
+ undo series start
+ select here
+ }
+ if {[select] > 0} {
+ xcircuit::textincrement selected $value $position
+ if {$nopreselect} {
+ deselect
+ undo series end
+ }
+ } else {
+ if {$nopreselect} {
+ undo series end
+ }
+ error "no selection"
+ }
+ } else {
+ error "no auto-incr in text mode"
+ }
+}
+
+#-----------------------------------------------------------------
+# Create a popup window for text modification
+#-----------------------------------------------------------------
+
+proc xcircuit::maketextmod {} {
+ toplevel .textmod -bg beige
+ wm withdraw .textmod
+
+ frame .textmod.title -bg beige
+ label .textmod.title.field -text "Label text modification for:" -bg beige
+ menubutton .textmod.title.type -text "selected text" -bg beige \
+ -menu .textmod.title.type.seltype
+ button .textmod.title.dbut -text "Dismiss" -bg beige -command \
+ {wm withdraw .textmod}
+
+ menu .textmod.title.type.seltype -tearoff 0
+ .textmod.title.type.seltype add command -label "selected text" -command \
+ {.textmod.title.type configure -text "selected text"}
+ .textmod.title.type.seltype add command -label "all text in page" -command \
+ {.textmod.title.type configure -text "all text in page"}
+
+
+ pack .textmod.title -side top -fill x
+ pack .textmod.title.field -side left -padx 10
+ pack .textmod.title.type -side left -padx 10
+ pack .textmod.title.dbut -side right -ipadx 10
+
+ labelframe .textmod.replace -text "Search and Replace" -bg beige
+ pack .textmod.replace -side top -fill x -expand true -pady 10
+
+ label .textmod.replace.title1 -text "Search for:" -bg beige
+ entry .textmod.replace.original -bg white
+ label .textmod.replace.title2 -text "Replace with:" -bg beige
+ entry .textmod.replace.new -bg white
+ button .textmod.replace.apply -text "Apply" -bg beige -command \
+ {text_regexp [.textmod.replace.original get] \
+ [.textmod.replace.new get] [.textmod.title.type cget -text]}
+
+ pack .textmod.replace.title1 -side left
+ pack .textmod.replace.original -side left
+ pack .textmod.replace.title2 -side left
+ pack .textmod.replace.new -side left
+ pack .textmod.replace.apply -side right -ipadx 10 -padx 10
+
+ # Numeric Increment/Decrement
+
+ labelframe .textmod.numeric -text "Embedded Numbers" -bg beige
+ pack .textmod.numeric -side top -fill x -expand true
+
+ button .textmod.numeric.incr -text "Increment" -bg beige -command \
+ {xcircuit::textincrement [.textmod.title.type cget -text] \
+ [.textmod.numeric.amount get] [.textmod.numeric.pos cget -text]}
+ button .textmod.numeric.decr -text "Decrement" -bg beige -command \
+ {xcircuit::textincrement [.textmod.title.type cget -text] \
+ [expr -[.textmod.numeric.amount get]] [.textmod.numeric.pos cget -text]}
+ label .textmod.numeric.title1 -text "Amount: " -bg beige
+ entry .textmod.numeric.amount -bg white
+
+ menubutton .textmod.numeric.pos -text "first" -bg beige \
+ -menu .textmod.numeric.pos.posmenu
+ menu .textmod.numeric.pos.posmenu -tearoff 0
+ .textmod.numeric.pos.posmenu add command -label "first" -command \
+ {.textmod.numeric.pos configure -text "first"}
+ .textmod.numeric.pos.posmenu add command -label "last" -command \
+ {.textmod.numeric.pos configure -text "last"}
+
+ .textmod.numeric.amount insert 0 "1"
+
+ pack .textmod.numeric.incr -side left -ipadx 10 -padx 10
+ pack .textmod.numeric.decr -side left -ipadx 10 -padx 10
+ pack .textmod.numeric.title1 -side left
+ pack .textmod.numeric.amount -side left
+ pack .textmod.numeric.pos -side left
+}
+
+proc xcircuit::textmod {} {
+
+ if {[catch {wm state .textmod}]} {
+ xcircuit::maketextmod
+ }
+ set wstate [xcircuit::getinitstate .textmod]
+
+ # setup goes here
+
+ if {"$wstate" != "normal"} {
+ wm deiconify .textmod
+ xcircuit::centerwin .textmod
+ }
+ raise .textmod
+}
+
+#--------------------------------------------------------------
+# This procedure reads an entire file into an xcircuit string.
+#--------------------------------------------------------------
+
+proc xcircuit::importtext {filename} {
+ set ffile [open $filename]
+ set tlist {}
+ if {[gets $ffile line] >= 0} {
+ set line [string map {\t " "} $line]
+ lappend tlist [list Text $line]
+ while {[gets $ffile line] >= 0} {
+ set line [string map {\t " "} $line]
+ lappend tlist Return
+ lappend tlist [list Text $line]
+ }
+ }
+ label make normal $tlist "0 0"
+ close $ffile
+ refresh
+}
+
+#-----------------------------------------------------------------
+
+proc xcircuit::promptimporttext {} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::importtext [.filelist.textent.txt get]; \
+ wm withdraw .filelist}
+ .filelist.listwin.win configure -data ""
+ .filelist.textent.title.field configure -text "Select text file:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+}
+
+#-----------------------------------------------------------------
diff --git a/lib/tcl/tkcon.tcl b/lib/tcl/tkcon.tcl
new file mode 100755
index 0000000..bcf4dab
--- /dev/null
+++ b/lib/tcl/tkcon.tcl
@@ -0,0 +1,5328 @@
+#!/bin/sh
+# \
+exec ${XCIRCUIT_WISH:=wish} "$0" ${1+"$@"}
+
+#
+## tkcon.tcl
+## Enhanced Tk Console, part of the VerTcl system
+##
+## Originally based off Brent Welch's Tcl Shell Widget
+## (from "Practical Programming in Tcl and Tk")
+##
+## Thanks to the following (among many) for early bug reports & code ideas:
+## Steven Wahl <steven@indra.com>, Jan Nijtmans <nijtmans@nici.kun.nl>
+## Crimmins <markcrim@umich.edu>, Wart <wart@ugcs.caltech.edu>
+##
+## Copyright 1995-2001 Jeffrey Hobbs
+## Initiated: Thu Aug 17 15:36:47 PDT 1995
+##
+## jeff.hobbs@acm.org, jeff@hobbs.org
+##
+## source standard_disclaimer.tcl
+## source bourbon_ware.tcl
+##
+
+# Proxy support for retrieving the current version of Tkcon.
+#
+# Mon Jun 25 12:19:56 2001 - Pat Thoyts <Pat.Thoyts@bigfoot.com>
+#
+# In your tkcon.cfg or .tkconrc file put your proxy details into the
+# `proxy' member of the `PRIV' array. e.g.:
+#
+# set ::tkcon::PRIV(proxy) wwwproxy:8080
+#
+# If you want to be prompted for proxy authentication details (eg for
+# an NT proxy server) make the second element of this variable non-nil - eg:
+#
+# set ::tkcon::PRIV(proxy) {wwwproxy:8080 1}
+#
+# Or you can set the above variable from within tkcon by calling
+#
+# tkcon master set ::tkcon:PRIV(proxy) wwwproxy:8080
+#
+
+if {$tcl_version < 8.0} {
+ return -code error "tkcon requires at least Tcl/Tk8"
+} else {
+ package require Tk $tcl_version
+}
+
+catch {package require bogus-package-name}
+foreach pkg [info loaded {}] {
+ set file [lindex $pkg 0]
+ set name [lindex $pkg 1]
+ if {![catch {set version [package require $name]}]} {
+ if {[string match {} [package ifneeded $name $version]]} {
+ package ifneeded $name $version [list load $file $name]
+ }
+ }
+}
+catch {unset pkg file name version}
+
+# Tk 8.4 makes previously exposed stuff private.
+# FIX: Update tkcon to not rely on the private Tk code.
+#
+if {![llength [info globals tkPriv]]} {
+ ::tk::unsupported::ExposePrivateVariable tkPriv
+}
+foreach cmd {SetCursor UpDownLine Transpose ScrollPages} {
+ if {![llength [info commands tkText$cmd]]} {
+ ::tk::unsupported::ExposePrivateCommand tkText$cmd
+ }
+}
+
+# Initialize the ::tkcon namespace
+#
+namespace eval ::tkcon {
+ # The OPT variable is an array containing most of the optional
+ # info to configure. COLOR has the color data.
+ variable OPT
+ variable COLOR
+
+ # PRIV is used for internal data that only tkcon should fiddle with.
+ variable PRIV
+ set PRIV(WWW) [info exists embed_args]
+}
+
+## ::tkcon::Init - inits tkcon
+#
+# Calls: ::tkcon::InitUI
+# Outputs: errors found in tkcon's resource file
+##
+proc ::tkcon::Init {} {
+ variable OPT
+ variable COLOR
+ variable PRIV
+ global tcl_platform env argc argv tcl_interactive errorInfo
+
+ if {![info exists argv]} {
+ set argv {}
+ set argc 0
+ }
+
+ set tcl_interactive 1
+
+ if {[info exists PRIV(name)]} {
+ set title $PRIV(name)
+ } else {
+ MainInit
+ # some main initialization occurs later in this proc,
+ # to go after the UI init
+ set MainInit 1
+ set title Main
+ }
+
+ ##
+ ## When setting up all the default values, we always check for
+ ## prior existence. This allows users who embed tkcon to modify
+ ## the initial state before tkcon initializes itself.
+ ##
+
+ # bg == {} will get bg color from the main toplevel (in InitUI)
+ foreach {key default} {
+ bg {}
+ blink \#FFFF00
+ cursor \#000000
+ disabled \#4D4D4D
+ proc \#008800
+ var \#FFC0D0
+ prompt \#8F4433
+ stdin \#000000
+ stdout \#0000FF
+ stderr \#FF0000
+ } {
+ if {![info exists COLOR($key)]} { set COLOR($key) $default }
+ }
+
+ foreach {key default} {
+ autoload {}
+ blinktime 500
+ blinkrange 1
+ buffer 512
+ calcmode 0
+ cols 80
+ debugPrompt {(level \#$level) debug [history nextid] > }
+ dead {}
+ expandorder {Pathname Variable Procname}
+ font {}
+ history 48
+ hoterrors 1
+ library {}
+ lightbrace 1
+ lightcmd 1
+ maineval {}
+ maxmenu 15
+ nontcl 0
+ prompt1 {ignore this, it's set below}
+ rows 20
+ scrollypos right
+ showmenu 1
+ showmultiple 1
+ showstatusbar 0
+ slaveeval {}
+ slaveexit close
+ subhistory 1
+ gc-delay 60000
+ gets {congets}
+ usehistory 1
+
+ exec slave
+ } {
+ if {![info exists OPT($key)]} { set OPT($key) $default }
+ }
+
+ foreach {key default} {
+ app {}
+ appname {}
+ apptype slave
+ namesp ::
+ cmd {}
+ cmdbuf {}
+ cmdsave {}
+ event 1
+ deadapp 0
+ deadsock 0
+ debugging 0
+ displayWin .
+ histid 0
+ find {}
+ find,case 0
+ find,reg 0
+ errorInfo {}
+ showOnStartup 1
+ slavealias { edit more less tkcon }
+ slaveprocs {
+ alias clear dir dump echo idebug lremove
+ tkcon_puts tkcon_gets observe observe_var unalias which what
+ }
+ version 2.3
+ RCS {RCS: @(#) $Id: tkcon.tcl,v 1.1.1.1 2011/04/10 21:15:05 tim Exp $}
+ HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD}
+ docs "http://tkcon.sourceforge.net/"
+ email {jeff@hobbs.org}
+ root .
+ } {
+ if {![info exists PRIV($key)]} { set PRIV($key) $default }
+ }
+
+ ## NOTES FOR STAYING IN PRIMARY INTERPRETER:
+ ##
+ ## If you set ::tkcon::OPT(exec) to {}, then instead of a multiple
+ ## interp model, you get tkcon operating in the main interp by default.
+ ## This can be useful when attaching to programs that like to operate
+ ## in the main interpter (for example, based on special wish'es).
+ ## You can set this from the command line with -exec ""
+ ## A side effect is that all tkcon command line args will be used
+ ## by the first console only.
+ #set OPT(exec) {}
+
+ if {$PRIV(WWW)} {
+ lappend PRIV(slavealias) history
+ set OPT(prompt1) {[history nextid] % }
+ } else {
+ lappend PRIV(slaveprocs) tcl_unknown unknown
+ set OPT(prompt1) {([file tail [pwd]]) [history nextid] % }
+ }
+
+ ## If we are using the default '.' toplevel, and there appear to be
+ ## children of '.', then make sure we use a disassociated toplevel.
+ if {$PRIV(root) == "." && [llength [winfo children .]]} {
+ set PRIV(root) .tkcon
+ }
+
+ ## Do platform specific configuration here, other than defaults
+ ### Use tkcon.cfg filename for resource filename on non-unix systems
+ ### Determine what directory the resource file should be in
+ switch $tcl_platform(platform) {
+ macintosh {
+ if {![interp issafe]} {cd [file dirname [info script]]}
+ set envHome PREF_FOLDER
+ set rcfile tkcon.cfg
+ set histfile tkcon.hst
+ catch {console hide}
+ }
+ windows {
+ set envHome HOME
+ set rcfile tkcon.cfg
+ set histfile tkcon.hst
+ }
+ unix {
+ set envHome HOME
+ set rcfile .tkconrc
+ set histfile .tkcon_history
+ }
+ }
+ if {[info exists env($envHome)]} {
+ if {![info exists PRIV(rcfile)]} {
+ set PRIV(rcfile) [file join $env($envHome) $rcfile]
+ }
+ if {![info exists PRIV(histfile)]} {
+ set PRIV(histfile) [file join $env($envHome) $histfile]
+ }
+ }
+
+ ## Handle command line arguments before sourcing resource file to
+ ## find if resource file is being specified (let other args pass).
+ if {[set i [lsearch -exact $argv -rcfile]] != -1} {
+ set PRIV(rcfile) [lindex $argv [incr i]]
+ }
+
+ if {!$PRIV(WWW) && [file exists $PRIV(rcfile)]} {
+ set code [catch {uplevel \#0 [list source $PRIV(rcfile)]} err]
+ }
+
+ if {[info exists env(TK_CON_LIBRARY)]} {
+ lappend ::auto_path $env(TK_CON_LIBRARY)
+ } else {
+ lappend ::auto_path $OPT(library)
+ }
+
+ if {![info exists ::tcl_pkgPath]} {
+ set dir [file join [file dirname [info nameofexec]] lib]
+ if {[llength [info commands @scope]]} {
+ set dir [file join $dir itcl]
+ }
+ catch {source [file join $dir pkgIndex.tcl]}
+ }
+ catch {tclPkgUnknown dummy-name dummy-version}
+
+ ## Handle rest of command line arguments after sourcing resource file
+ ## and slave is created, but before initializing UI or setting packages.
+ set slaveargs {}
+ set slavefiles {}
+ set truth {^(1|yes|true|on)$}
+ for {set i 0} {$i < $argc} {incr i} {
+ set arg [lindex $argv $i]
+ if {[string match {-*} $arg]} {
+ set val [lindex $argv [incr i]]
+ ## Handle arg based options
+ switch -glob -- $arg {
+ -- - -argv {
+ set argv [concat -- [lrange $argv $i end]]
+ set argc [llength $argv]
+ break
+ }
+ -color-* { set COLOR([string range $arg 7 end]) $val }
+ -exec { set OPT(exec) $val }
+ -main - -e - -eval { append OPT(maineval) \n$val\n }
+ -package - -load { lappend OPT(autoload) $val }
+ -slave { append OPT(slaveeval) \n$val\n }
+ -nontcl { set OPT(nontcl) [regexp -nocase $truth $val]}
+ -root { set PRIV(root) $val }
+ -font { set OPT(font) $val }
+ -rcfile {}
+ default { lappend slaveargs $arg; incr i -1 }
+ }
+ } elseif {[file isfile $arg]} {
+ lappend slavefiles $arg
+ } else {
+ lappend slaveargs $arg
+ }
+ }
+
+ ## Create slave executable
+ if {[string compare {} $OPT(exec)]} {
+ uplevel \#0 ::tkcon::InitSlave $OPT(exec) $slaveargs
+ } else {
+ set argc [llength $slaveargs]
+ set argv $slaveargs
+ uplevel \#0 $slaveargs
+ }
+
+ ## Attach to the slave, EvalAttached will then be effective
+ Attach $PRIV(appname) $PRIV(apptype)
+ InitUI $title
+
+ ## swap puts and gets with the tkcon versions to make sure all
+ ## input and output is handled by tkcon
+ if {![catch {rename ::puts ::tkcon_tcl_puts}]} {
+ interp alias {} ::puts {} ::tkcon_puts
+ }
+ if {($OPT(gets) != "") && ![catch {rename ::gets ::tkcon_tcl_gets}]} {
+ interp alias {} ::gets {} ::tkcon_gets
+ }
+
+ EvalSlave history keep $OPT(history)
+ if {[info exists MainInit]} {
+ # Source history file only for the main console, as all slave
+ # consoles will adopt from the main's history, but still
+ # keep separate histories
+ if {!$PRIV(WWW) && $OPT(usehistory) && [file exists $PRIV(histfile)]} {
+ puts -nonewline "loading history file ... "
+ # The history file is built to be loaded in and
+ # understood by tkcon
+ if {[catch {uplevel \#0 [list source $PRIV(histfile)]} herr]} {
+ puts stderr "error:\n$herr"
+ append PRIV(errorInfo) $errorInfo\n
+ }
+ set PRIV(event) [EvalSlave history nextid]
+ puts "[expr {$PRIV(event)-1}] events added"
+ }
+ }
+
+ ## Autoload specified packages in slave
+ set pkgs [EvalSlave package names]
+ foreach pkg $OPT(autoload) {
+ puts -nonewline "autoloading package \"$pkg\" ... "
+ if {[lsearch -exact $pkgs $pkg]>-1} {
+ if {[catch {EvalSlave package require [list $pkg]} pkgerr]} {
+ puts stderr "error:\n$pkgerr"
+ append PRIV(errorInfo) $errorInfo\n
+ } else { puts "OK" }
+ } else {
+ puts stderr "error: package does not exist"
+ }
+ }
+
+ ## Evaluate maineval in slave
+ if {[string compare {} $OPT(maineval)] && \
+ [catch {uplevel \#0 $OPT(maineval)} merr]} {
+ puts stderr "error in eval:\n$merr"
+ append PRIV(errorInfo) $errorInfo\n
+ }
+
+ ## Source extra command line argument files into slave executable
+ foreach fn $slavefiles {
+ puts -nonewline "slave sourcing \"$fn\" ... "
+ if {[catch {EvalSlave source [list $fn]} fnerr]} {
+ puts stderr "error:\n$fnerr"
+ append PRIV(errorInfo) $errorInfo\n
+ } else { puts "OK" }
+ }
+
+ ## Evaluate slaveeval in slave
+ if {[string compare {} $OPT(slaveeval)] && \
+ [catch {interp eval $OPT(exec) $OPT(slaveeval)} serr]} {
+ puts stderr "error in slave eval:\n$serr"
+ append PRIV(errorInfo) $errorInfo\n
+ }
+ ## Output any error/output that may have been returned from rcfile
+ if {[info exists code] && $code && [string compare {} $err]} {
+ puts stderr "error in $PRIV(rcfile):\n$err"
+ append PRIV(errorInfo) $errorInfo
+ }
+ if {[string compare {} $OPT(exec)]} {
+ StateCheckpoint [concat $PRIV(name) $OPT(exec)] slave
+ }
+ StateCheckpoint $PRIV(name) slave
+
+ Prompt "$title console display active (Tcl$::tcl_patchLevel / Tk$::tk_patchLevel)\n"
+}
+
+## ::tkcon::InitSlave - inits the slave by placing key procs and aliases in it
+## It's arg[cv] are based on passed in options, while argv0 is the same as
+## the master. tcl_interactive is the same as the master as well.
+# ARGS: slave - name of slave to init. If it does not exist, it is created.
+# args - args to pass to a slave as argv/argc
+##
+proc ::tkcon::InitSlave {slave args} {
+ variable OPT
+ variable COLOR
+ variable PRIV
+ global argv0 tcl_interactive tcl_library env auto_path
+
+ if {[string match {} $slave]} {
+ return -code error "Don't init the master interpreter, goofball"
+ }
+ if {![interp exists $slave]} { interp create $slave }
+ if {[interp eval $slave info command source] == ""} {
+ $slave alias source SafeSource $slave
+ $slave alias load SafeLoad $slave
+ $slave alias open SafeOpen $slave
+ $slave alias file file
+ interp eval $slave [dump var -nocomplain tcl_library auto_path env]
+ interp eval $slave { catch {source [file join $tcl_library init.tcl]} }
+ interp eval $slave { catch unknown }
+ }
+ $slave alias exit exit
+ interp eval $slave {
+ # Do package require before changing around puts/gets
+ catch {package require bogus-package-name}
+ catch {rename ::puts ::tkcon_tcl_puts}
+ }
+ foreach cmd $PRIV(slaveprocs) { $slave eval [dump proc $cmd] }
+ foreach cmd $PRIV(slavealias) { $slave alias $cmd $cmd }
+ interp alias $slave ::ls $slave ::dir -full
+ interp alias $slave ::puts $slave ::tkcon_puts
+ if {$OPT(gets) != ""} {
+ interp eval $slave { catch {rename ::gets ::tkcon_tcl_gets} }
+ interp alias $slave ::gets $slave ::tkcon_gets
+ }
+ if {[info exists argv0]} {interp eval $slave [list set argv0 $argv0]}
+ interp eval $slave set tcl_interactive $tcl_interactive \; \
+ set auto_path [list $auto_path] \; \
+ set argc [llength $args] \; \
+ set argv [list $args] \; {
+ if {![llength [info command bgerror]]} {
+ proc bgerror err {
+ global errorInfo
+ set body [info body bgerror]
+ rename ::bgerror {}
+ if {[auto_load bgerror]} { return [bgerror $err] }
+ proc bgerror err $body
+ tkcon bgerror $err $errorInfo
+ }
+ }
+ }
+
+ foreach pkg [lremove [package names] Tcl] {
+ foreach v [package versions $pkg] {
+ interp eval $slave [list package ifneeded $pkg $v \
+ [package ifneeded $pkg $v]]
+ }
+ }
+}
+
+## ::tkcon::InitInterp - inits an interpreter by placing key
+## procs and aliases in it.
+# ARGS: name - interp name
+# type - interp type (slave|interp)
+##
+proc ::tkcon::InitInterp {name type} {
+ variable OPT
+ variable PRIV
+
+ ## Don't allow messing up a local master interpreter
+ if {[string match namespace $type] || ([string match slave $type] && \
+ [regexp {^([Mm]ain|Slave[0-9]+)$} $name])} return
+ set old [Attach]
+ set oldname $PRIV(namesp)
+ catch {
+ Attach $name $type
+ EvalAttached { catch {rename ::puts ::tkcon_tcl_puts} }
+ foreach cmd $PRIV(slaveprocs) { EvalAttached [dump proc $cmd] }
+ switch -exact $type {
+ slave {
+ foreach cmd $PRIV(slavealias) {
+ Main interp alias $name ::$cmd $PRIV(name) ::$cmd
+ }
+ }
+ interp {
+ set thistkcon [tk appname]
+ foreach cmd $PRIV(slavealias) {
+ EvalAttached "proc $cmd args { send [list $thistkcon] $cmd \$args }"
+ }
+ }
+ }
+ ## Catch in case it's a 7.4 (no 'interp alias') interp
+ EvalAttached {
+ catch {interp alias {} ::ls {} ::dir -full}
+ if {[catch {interp alias {} ::puts {} ::tkcon_puts}]} {
+ catch {rename ::tkcon_puts ::puts}
+ }
+ }
+ if {$OPT(gets) != ""} {
+ EvalAttached {
+ catch {rename ::gets ::tkcon_tcl_gets}
+ if {[catch {interp alias {} ::gets {} ::tkcon_gets}]} {
+ catch {rename ::tkcon_gets ::gets}
+ }
+ }
+ }
+ return
+ } {err}
+ eval Attach $old
+ AttachNamespace $oldname
+ if {[string compare {} $err]} { return -code error $err }
+}
+
+## ::tkcon::InitUI - inits UI portion (console) of tkcon
+## Creates all elements of the console window and sets up the text tags
+# ARGS: root - widget pathname of the tkcon console root
+# title - title for the console root and main (.) windows
+# Calls: ::tkcon::InitMenus, ::tkcon::Prompt
+##
+proc ::tkcon::InitUI {title} {
+ variable OPT
+ variable PRIV
+ variable COLOR
+
+ set root $PRIV(root)
+ if {[string match . $root]} { set w {} } else { set w [toplevel $root] }
+ if {!$PRIV(WWW)} {
+ wm withdraw $root
+ wm protocol $root WM_DELETE_WINDOW exit
+ }
+ set PRIV(base) $w
+
+ ## Text Console
+ set PRIV(console) [set con $w.text]
+ text $con -wrap char -yscrollcommand [list $w.sy set] \
+ -foreground $COLOR(stdin) \
+ -insertbackground $COLOR(cursor)
+ $con mark set output 1.0
+ $con mark set limit 1.0
+ if {[string compare {} $COLOR(bg)]} {
+ $con configure -background $COLOR(bg)
+ }
+ set COLOR(bg) [$con cget -background]
+ if {[string compare {} $OPT(font)]} {
+ ## Set user-requested font, if any
+ $con configure -font $OPT(font)
+ } else {
+ ## otherwise make sure the font is monospace
+ set font [$con cget -font]
+ if {![font metrics $font -fixed]} {
+ font create tkconfixed -family Courier -size 12
+ $con configure -font tkconfixed
+ }
+ }
+ set OPT(font) [$con cget -font]
+ if {!$PRIV(WWW)} {
+ $con configure -setgrid 1 -width $OPT(cols) -height $OPT(rows)
+ }
+ bindtags $con [list $con TkConsole TkConsolePost $root all]
+ ## Menus
+ ## catch against use in plugin
+ if {[catch {menu $w.mbar} PRIV(menubar)]} {
+ set PRIV(menubar) [frame $w.mbar -relief raised -bd 1]
+ }
+ ## Scrollbar
+ set PRIV(scrolly) [scrollbar $w.sy -takefocus 0 -bd 1 \
+ -command [list $con yview]]
+
+ InitMenus $PRIV(menubar) $title
+ Bindings
+
+ if {$OPT(showmenu)} {
+ $root configure -menu $PRIV(menubar)
+ }
+ pack $w.sy -side $OPT(scrollypos) -fill y
+ pack $con -fill both -expand 1
+
+ set PRIV(statusbar) [set sbar [frame $w.sbar]]
+ label $sbar.attach -relief sunken -bd 1 -anchor w \
+ -textvariable ::tkcon::PRIV(StatusAttach)
+ label $sbar.mode -relief sunken -bd 1 -anchor w \
+ -textvariable ::tkcon::PRIV(StatusMode)
+ label $sbar.cursor -relief sunken -bd 1 -anchor w -width 6 \
+ -textvariable ::tkcon::PRIV(StatusCursor)
+ grid $sbar.attach $sbar.mode $sbar.cursor -sticky news -padx 1
+ grid columnconfigure $sbar 0 -weight 1
+ grid columnconfigure $sbar 1 -weight 1
+ grid columnconfigure $sbar 2 -weight 0
+
+ if {$OPT(showstatusbar)} {
+ pack $sbar -side bottom -fill x -before $::tkcon::PRIV(scrolly)
+ }
+
+ foreach col {prompt stdout stderr stdin proc} {
+ $con tag configure $col -foreground $COLOR($col)
+ }
+ $con tag configure var -background $COLOR(var)
+ $con tag raise sel
+ $con tag configure blink -background $COLOR(blink)
+ $con tag configure find -background $COLOR(blink)
+
+ if {!$PRIV(WWW)} {
+ wm title $root "tkcon $PRIV(version) $title"
+ bind $con <Configure> {
+ scan [wm geometry [winfo toplevel %W]] "%%dx%%d" \
+ ::tkcon::OPT(cols) ::tkcon::OPT(rows)
+ }
+ if {$PRIV(showOnStartup)} { wm deiconify $root }
+ }
+ if {$PRIV(showOnStartup)} { focus -force $PRIV(console) }
+ if {$OPT(gc-delay)} {
+ after $OPT(gc-delay) ::tkcon::GarbageCollect
+ }
+}
+
+## ::tkcon::GarbageCollect - do various cleanup ops periodically to our setup
+##
+proc ::tkcon::GarbageCollect {} {
+ variable OPT
+ variable PRIV
+
+ set w $PRIV(console)
+ ## Remove error tags that no longer span anything
+ ## Make sure the tag pattern matches the unique tag prefix
+ foreach tag [$w tag names] {
+ if {[string match _tag* $tag] && ![llength [$w tag ranges $tag]]} {
+ $w tag delete $tag
+ }
+ }
+ if {$OPT(gc-delay)} {
+ after $OPT(gc-delay) ::tkcon::GarbageCollect
+ }
+}
+
+## ::tkcon::Eval - evaluates commands input into console window
+## This is the first stage of the evaluating commands in the console.
+## They need to be broken up into consituent commands (by ::tkcon::CmdSep) in
+## case a multiple commands were pasted in, then each is eval'ed (by
+## ::tkcon::EvalCmd) in turn. Any uncompleted command will not be eval'ed.
+# ARGS: w - console text widget
+# Calls: ::tkcon::CmdGet, ::tkcon::CmdSep, ::tkcon::EvalCmd
+##
+proc ::tkcon::Eval {w} {
+ set incomplete [CmdSep [CmdGet $w] cmds last]
+ $w mark set insert end-1c
+ $w insert end \n
+ if {[llength $cmds]} {
+ foreach c $cmds {EvalCmd $w $c}
+ $w insert insert $last {}
+ } elseif {!$incomplete} {
+ EvalCmd $w $last
+ }
+ $w see insert
+}
+
+## ::tkcon::EvalCmd - evaluates a single command, adding it to history
+# ARGS: w - console text widget
+# cmd - the command to evaluate
+# Calls: ::tkcon::Prompt
+# Outputs: result of command to stdout (or stderr if error occured)
+# Returns: next event number
+##
+proc ::tkcon::EvalCmd {w cmd} {
+ variable OPT
+ variable PRIV
+
+ $w mark set output end
+ if {[string compare {} $cmd]} {
+ set code 0
+ if {$OPT(subhistory)} {
+ set ev [EvalSlave history nextid]
+ incr ev -1
+ if {[string match !! $cmd]} {
+ set code [catch {EvalSlave history event $ev} cmd]
+ if {!$code} {$w insert output $cmd\n stdin}
+ } elseif {[regexp {^!(.+)$} $cmd dummy event]} {
+ ## Check last event because history event is broken
+ set code [catch {EvalSlave history event $ev} cmd]
+ if {!$code && ![string match ${event}* $cmd]} {
+ set code [catch {EvalSlave history event $event} cmd]
+ }
+ if {!$code} {$w insert output $cmd\n stdin}
+ } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $cmd dummy old new]} {
+ set code [catch {EvalSlave history event $ev} cmd]
+ if {!$code} {
+ regsub -all -- $old $cmd $new cmd
+ $w insert output $cmd\n stdin
+ }
+ } elseif {$OPT(calcmode) && ![catch {expr $cmd} err]} {
+ EvalSlave history add $cmd
+ set cmd $err
+ set code -1
+ }
+ }
+ if {$code} {
+ $w insert output $cmd\n stderr
+ } else {
+ ## We are about to evaluate the command, so move the limit
+ ## mark to ensure that further <Return>s don't cause double
+ ## evaluation of this command - for cases like the command
+ ## has a vwait or something in it
+ $w mark set limit end
+ if {$OPT(nontcl) && [string match interp $PRIV(apptype)]} {
+ set code [catch {EvalSend $cmd} res]
+ if {$code == 1} {
+ set PRIV(errorInfo) "Non-Tcl errorInfo not available"
+ }
+ } elseif {[string match socket $PRIV(apptype)]} {
+ set code [catch {EvalSocket $cmd} res]
+ if {$code == 1} {
+ set PRIV(errorInfo) "Socket-based errorInfo not available"
+ }
+ } else {
+ set code [catch {EvalAttached $cmd} res]
+ if {$code == 1} {
+ if {[catch {EvalAttached [list set errorInfo]} err]} {
+ set PRIV(errorInfo) "Error getting errorInfo:\n$err"
+ } else {
+ set PRIV(errorInfo) $err
+ }
+ }
+ }
+ EvalSlave history add $cmd
+ if {$code} {
+ if {$OPT(hoterrors)} {
+ set tag [UniqueTag $w]
+ $w insert output $res [list stderr $tag] \n stderr
+ $w tag bind $tag <Enter> \
+ [list $w tag configure $tag -under 1]
+ $w tag bind $tag <Leave> \
+ [list $w tag configure $tag -under 0]
+ $w tag bind $tag <ButtonRelease-1> \
+ "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \
+ {[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}"
+ } else {
+ $w insert output $res\n stderr
+ }
+ } elseif {[string compare {} $res]} {
+ $w insert output $res\n stdout
+ }
+ }
+ }
+ Prompt
+ set PRIV(event) [EvalSlave history nextid]
+}
+
+## ::tkcon::EvalSlave - evaluates the args in the associated slave
+## args should be passed to this procedure like they would be at
+## the command line (not like to 'eval').
+# ARGS: args - the command and args to evaluate
+##
+proc ::tkcon::EvalSlave args {
+ interp eval $::tkcon::OPT(exec) $args
+}
+
+## ::tkcon::EvalOther - evaluate a command in a foreign interp or slave
+## without attaching to it. No check for existence is made.
+# ARGS: app - interp/slave name
+# type - (slave|interp)
+##
+proc ::tkcon::EvalOther { app type args } {
+ if {[string compare slave $type]==0} {
+ return [Slave $app $args]
+ } else {
+ return [uplevel 1 send [list $app] $args]
+ }
+}
+
+## ::tkcon::EvalSend - sends the args to the attached interpreter
+## Varies from 'send' by determining whether attachment is dead
+## when an error is received
+# ARGS: cmd - the command string to send across
+# Returns: the result of the command
+##
+proc ::tkcon::EvalSend cmd {
+ variable OPT
+ variable PRIV
+
+ if {$PRIV(deadapp)} {
+ if {[lsearch -exact [winfo interps] $PRIV(app)]<0} {
+ return
+ } else {
+ set PRIV(appname) [string range $PRIV(appname) 5 end]
+ set PRIV(deadapp) 0
+ Prompt "\n\"$PRIV(app)\" alive\n" [CmdGet $PRIV(console)]
+ }
+ }
+ set code [catch {send -displayof $PRIV(displayWin) $PRIV(app) $cmd} result]
+ if {$code && [lsearch -exact [winfo interps] $PRIV(app)]<0} {
+ ## Interpreter disappeared
+ if {[string compare leave $OPT(dead)] && \
+ ([string match ignore $OPT(dead)] || \
+ [tk_dialog $PRIV(base).dead "Dead Attachment" \
+ "\"$PRIV(app)\" appears to have died.\
+ \nReturn to primary slave interpreter?" questhead 0 OK No])} {
+ set PRIV(appname) "DEAD:$PRIV(appname)"
+ set PRIV(deadapp) 1
+ } else {
+ set err "Attached Tk interpreter \"$PRIV(app)\" died."
+ Attach {}
+ set PRIV(deadapp) 0
+ EvalSlave set errorInfo $err
+ }
+ Prompt \n [CmdGet $PRIV(console)]
+ }
+ return -code $code $result
+}
+
+## ::tkcon::EvalSocket - sends the string to an interpreter attached via
+## a tcp/ip socket
+##
+## In the EvalSocket case, ::tkcon::PRIV(app) is the socket id
+##
+## Must determine whether socket is dead when an error is received
+# ARGS: cmd - the data string to send across
+# Returns: the result of the command
+##
+proc ::tkcon::EvalSocket cmd {
+ variable OPT
+ variable PRIV
+ global tcl_version
+
+ if {$PRIV(deadapp)} {
+ if {![info exists PRIV(app)] || \
+ [catch {eof $PRIV(app)} eof] || $eof} {
+ return
+ } else {
+ set PRIV(appname) [string range $PRIV(appname) 5 end]
+ set PRIV(deadapp) 0
+ Prompt "\n\"$PRIV(app)\" alive\n" [CmdGet $PRIV(console)]
+ }
+ }
+ # Sockets get \'s interpreted, so that users can
+ # send things like \n\r or explicit hex values
+ set cmd [subst -novariables -nocommands $cmd]
+ #puts [list $PRIV(app) $cmd]
+ set code [catch {puts $PRIV(app) $cmd ; flush $PRIV(app)} result]
+ if {$code && [eof $PRIV(app)]} {
+ ## Interpreter died or disappeared
+ puts "$code eof [eof $PRIV(app)]"
+ EvalSocketClosed
+ }
+ return -code $code $result
+}
+
+## ::tkcon::EvalSocketEvent - fileevent command for an interpreter attached
+## via a tcp/ip socket
+## Must determine whether socket is dead when an error is received
+# ARGS: args - the args to send across
+# Returns: the result of the command
+##
+proc ::tkcon::EvalSocketEvent {} {
+ variable PRIV
+
+ if {[gets $PRIV(app) line] == -1} {
+ if {[eof $PRIV(app)]} {
+ EvalSocketClosed
+ }
+ return
+ }
+ puts $line
+}
+
+## ::tkcon::EvalSocketClosed - takes care of handling a closed eval socket
+##
+# ARGS: args - the args to send across
+# Returns: the result of the command
+##
+proc ::tkcon::EvalSocketClosed {} {
+ variable OPT
+ variable PRIV
+
+ catch {close $PRIV(app)}
+ if {[string compare leave $OPT(dead)] && \
+ ([string match ignore $OPT(dead)] || \
+ [tk_dialog $PRIV(base).dead "Dead Attachment" \
+ "\"$PRIV(app)\" appears to have died.\
+ \nReturn to primary slave interpreter?" questhead 0 OK No])} {
+ set PRIV(appname) "DEAD:$PRIV(appname)"
+ set PRIV(deadapp) 1
+ } else {
+ set err "Attached Tk interpreter \"$PRIV(app)\" died."
+ Attach {}
+ set PRIV(deadapp) 0
+ EvalSlave set errorInfo $err
+ }
+ Prompt \n [CmdGet $PRIV(console)]
+}
+
+## ::tkcon::EvalNamespace - evaluates the args in a particular namespace
+## This is an override for ::tkcon::EvalAttached for when the user wants
+## to attach to a particular namespace of the attached interp
+# ARGS: attached
+# namespace the namespace to evaluate in
+# args the args to evaluate
+# RETURNS: the result of the command
+##
+proc ::tkcon::EvalNamespace { attached namespace args } {
+ if {[llength $args]} {
+ uplevel \#0 $attached \
+ [list [concat [list namespace eval $namespace] $args]]
+ }
+}
+
+
+## ::tkcon::Namespaces - return all the namespaces descendent from $ns
+##
+#
+##
+proc ::tkcon::Namespaces {{ns ::} {l {}}} {
+ if {[string compare {} $ns]} { lappend l $ns }
+ foreach i [EvalAttached [list namespace children $ns]] {
+ set l [Namespaces $i $l]
+ }
+ return $l
+}
+
+## ::tkcon::CmdGet - gets the current command from the console widget
+# ARGS: w - console text widget
+# Returns: text which compromises current command line
+##
+proc ::tkcon::CmdGet w {
+ if {![llength [$w tag nextrange prompt limit end]]} {
+ $w tag add stdin limit end-1c
+ return [$w get limit end-1c]
+ }
+}
+
+## ::tkcon::CmdSep - separates multiple commands into a list and remainder
+# ARGS: cmd - (possible) multiple command to separate
+# list - varname for the list of commands that were separated.
+# last - varname of any remainder (like an incomplete final command).
+# If there is only one command, it's placed in this var.
+# Returns: constituent command info in varnames specified by list & rmd.
+##
+proc ::tkcon::CmdSep {cmd list last} {
+ upvar 1 $list cmds $last inc
+ set inc {}
+ set cmds {}
+ foreach c [split [string trimleft $cmd] \n] {
+ if {[string compare $inc {}]} {
+ append inc \n$c
+ } else {
+ append inc [string trimleft $c]
+ }
+ if {[info complete $inc] && ![regexp {[^\\]\\$} $inc]} {
+ if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc}
+ set inc {}
+ }
+ }
+ set i [string compare $inc {}]
+ if {!$i && [string compare $cmds {}] && ![string match *\n $cmd]} {
+ set inc [lindex $cmds end]
+ set cmds [lreplace $cmds end end]
+ }
+ return $i
+}
+
+## ::tkcon::CmdSplit - splits multiple commands into a list
+# ARGS: cmd - (possible) multiple command to separate
+# Returns: constituent commands in a list
+##
+proc ::tkcon::CmdSplit {cmd} {
+ set inc {}
+ set cmds {}
+ foreach cmd [split [string trimleft $cmd] \n] {
+ if {[string compare {} $inc]} {
+ append inc \n$cmd
+ } else {
+ append inc [string trimleft $cmd]
+ }
+ if {[info complete $inc] && ![regexp {[^\\]\\$} $inc]} {
+ #set inc [string trimright $inc]
+ if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc}
+ set inc {}
+ }
+ }
+ if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc}
+ return $cmds
+}
+
+## ::tkcon::UniqueTag - creates a uniquely named tag, reusing names
+## Called by ::tkcon::EvalCmd
+# ARGS: w - text widget
+# Outputs: tag name guaranteed unique in the widget
+##
+proc ::tkcon::UniqueTag {w} {
+ set tags [$w tag names]
+ set idx 0
+ while {[lsearch -exact $tags _tag[incr idx]] != -1} {}
+ return _tag$idx
+}
+
+## ::tkcon::ConstrainBuffer - This limits the amount of data in the text widget
+## Called by ::tkcon::Prompt and in tkcon proc buffer/console switch cases
+# ARGS: w - console text widget
+# size - # of lines to constrain to
+# Outputs: may delete data in console widget
+##
+proc ::tkcon::ConstrainBuffer {w size} {
+ if {[$w index end] > $size} {
+ $w delete 1.0 [expr {int([$w index end])-$size}].0
+ }
+}
+
+## ::tkcon::Prompt - displays the prompt in the console widget
+# ARGS: w - console text widget
+# Outputs: prompt (specified in ::tkcon::OPT(prompt1)) to console
+##
+proc ::tkcon::Prompt {{pre {}} {post {}} {prompt {}}} {
+ variable OPT
+ variable PRIV
+
+ set w $PRIV(console)
+ if {[string compare {} $pre]} { $w insert end $pre stdout }
+ set i [$w index end-1c]
+ if {!$OPT(showstatusbar)} {
+ if {[string compare {} $PRIV(appname)]} {
+ $w insert end ">$PRIV(appname)< " prompt
+ }
+ if {[string compare :: $PRIV(namesp)]} {
+ $w insert end "<$PRIV(namesp)> " prompt
+ }
+ }
+ if {[string compare {} $prompt]} {
+ $w insert end $prompt prompt
+ } else {
+ $w insert end [EvalSlave subst $OPT(prompt1)] prompt
+ }
+ $w mark set output $i
+ $w mark set insert end
+ $w mark set limit insert
+ $w mark gravity limit left
+ if {[string compare {} $post]} { $w insert end $post stdin }
+ ConstrainBuffer $w $OPT(buffer)
+ set ::tkcon::PRIV(StatusCursor) [$w index insert]
+ $w see end
+}
+
+## ::tkcon::About - gives about info for tkcon
+##
+proc ::tkcon::About {} {
+ variable OPT
+ variable PRIV
+ variable COLOR
+
+ set w $PRIV(base).about
+ if {[winfo exists $w]} {
+ wm deiconify $w
+ } else {
+ global tk_patchLevel tcl_patchLevel tcl_version
+ toplevel $w
+ wm title $w "About tkcon v$PRIV(version)"
+ button $w.b -text Dismiss -command [list wm withdraw $w]
+ text $w.text -height 9 -bd 1 -width 60 \
+ -foreground $COLOR(stdin) \
+ -background $COLOR(bg) \
+ -font $OPT(font)
+ pack $w.b -fill x -side bottom
+ pack $w.text -fill both -side left -expand 1
+ $w.text tag config center -justify center
+ $w.text tag config title -justify center -font {Courier -18 bold}
+ # strip down the RCS info displayed in the about box
+ regexp {,v ([0-9\./: ]*)} $PRIV(RCS) -> RCS
+ $w.text insert 1.0 "About tkcon v$PRIV(version)" title \
+ "\n\nCopyright 1995-2001 Jeffrey Hobbs, $PRIV(email)\
+ \nRelease Info: v$PRIV(version), CVS v$RCS\
+ \nDocumentation available at:\n$PRIV(docs)\
+ \nUsing: Tcl v$tcl_patchLevel / Tk v$tk_patchLevel" center
+ $w.text config -state disabled
+ }
+}
+
+## ::tkcon::InitMenus - inits the menubar and popup for the console
+# ARGS: w - console text widget
+##
+proc ::tkcon::InitMenus {w title} {
+ variable OPT
+ variable PRIV
+ variable COLOR
+ global tcl_platform
+
+ if {[catch {menu $w.pop -tearoff 0}]} {
+ label $w.label -text "Menus not available in plugin mode"
+ pack $w.label
+ return
+ }
+ menu $w.context -tearoff 0 -disabledforeground $COLOR(disabled)
+ set PRIV(context) $w.context
+ set PRIV(popup) $w.pop
+
+ proc MenuButton {w m l} {
+ $w add cascade -label $m -underline 0 -menu $w.$l
+ return $w.$l
+ }
+
+ foreach m [list File Console Edit Interp Prefs History Help] {
+ set l [string tolower $m]
+ MenuButton $w $m $l
+ $w.pop add cascade -label $m -underline 0 -menu $w.pop.$l
+ }
+
+ ## File Menu
+ ##
+ foreach m [list [menu $w.file -disabledforeground $COLOR(disabled)] \
+ [menu $w.pop.file -disabledforeground $COLOR(disabled)]] {
+ $m add command -label "Load File" -underline 0 -command ::tkcon::Load
+ $m add cascade -label "Save ..." -underline 0 -menu $m.save
+ $m add separator
+ $m add command -label "Quit" -underline 0 -accel Ctrl-q -command exit
+
+ ## Save Menu
+ ##
+ set s $m.save
+ menu $s -disabledforeground $COLOR(disabled) -tearoff 0
+ $s add command -label "All" -underline 0 \
+ -command {::tkcon::Save {} all}
+ $s add command -label "History" -underline 0 \
+ -command {::tkcon::Save {} history}
+ $s add command -label "Stdin" -underline 3 \
+ -command {::tkcon::Save {} stdin}
+ $s add command -label "Stdout" -underline 3 \
+ -command {::tkcon::Save {} stdout}
+ $s add command -label "Stderr" -underline 3 \
+ -command {::tkcon::Save {} stderr}
+ }
+
+ ## Console Menu
+ ##
+ foreach m [list [menu $w.console -disabledfore $COLOR(disabled)] \
+ [menu $w.pop.console -disabledfore $COLOR(disabled)]] {
+ $m add command -label "$title Console" -state disabled
+ $m add command -label "New Console" -underline 0 -accel Ctrl-N \
+ -command ::tkcon::New
+ $m add command -label "Close Console" -underline 0 -accel Ctrl-w \
+ -command ::tkcon::Destroy
+ $m add command -label "Clear Console" -underline 1 -accel Ctrl-l \
+ -command { clear; ::tkcon::Prompt }
+ if {[string match unix $tcl_platform(platform)]} {
+ $m add separator
+ $m add command -label "Make Xauth Secure" -und 5 \
+ -command ::tkcon::XauthSecure
+ }
+ $m add separator
+ $m add cascade -label "Attach To ..." -underline 0 -menu $m.attach
+
+ ## Attach Console Menu
+ ##
+ set sub [menu $m.attach -disabledforeground $COLOR(disabled)]
+ $sub add cascade -label "Interpreter" -underline 0 -menu $sub.apps
+ $sub add cascade -label "Namespace" -underline 1 -menu $sub.name
+ $sub add cascade -label "Socket" -underline 1 -menu $sub.sock \
+ -state [expr {([info tclversion] < 8.3)?"disabled":"normal"}]
+
+ ## Attach Console Menu
+ ##
+ menu $sub.apps -disabledforeground $COLOR(disabled) \
+ -postcommand [list ::tkcon::AttachMenu $sub.apps]
+
+ ## Attach Namespace Menu
+ ##
+ menu $sub.name -disabledforeground $COLOR(disabled) -tearoff 0 \
+ -postcommand [list ::tkcon::NamespaceMenu $sub.name]
+
+ if {$::tcl_version >= 8.3} {
+ # This uses [file channels] to create the menu, so we only
+ # want it for newer versions of Tcl.
+
+ ## Attach Socket Menu
+ ##
+ menu $sub.sock -disabledforeground $COLOR(disabled) -tearoff 0 \
+ -postcommand [list ::tkcon::SocketMenu $sub.sock]
+ }
+
+ ## Attach Display Menu
+ ##
+ if {![string compare "unix" $tcl_platform(platform)]} {
+ $sub add cascade -label "Display" -und 1 -menu $sub.disp
+ menu $sub.disp -disabledforeground $COLOR(disabled) \
+ -tearoff 0 \
+ -postcommand [list ::tkcon::DisplayMenu $sub.disp]
+ }
+ }
+
+ ## Edit Menu
+ ##
+ set text $PRIV(console)
+ foreach m [list [menu $w.edit] [menu $w.pop.edit]] {
+ $m add command -label "Cut" -underline 2 -accel Ctrl-x \
+ -command [list ::tkcon::Cut $text]
+ $m add command -label "Copy" -underline 0 -accel Ctrl-c \
+ -command [list ::tkcon::Copy $text]
+ $m add command -label "Paste" -underline 0 -accel Ctrl-v \
+ -command [list ::tkcon::Paste $text]
+ $m add separator
+ $m add command -label "Find" -underline 0 -accel Ctrl-F \
+ -command [list ::tkcon::FindBox $text]
+ }
+
+ ## Interp Menu
+ ##
+ foreach m [list $w.interp $w.pop.interp] {
+ menu $m -disabledforeground $COLOR(disabled) \
+ -postcommand [list ::tkcon::InterpMenu $m]
+ }
+
+ ## Prefs Menu
+ ##
+ foreach m [list [menu $w.prefs] [menu $w.pop.prefs]] {
+ $m add check -label "Brace Highlighting" \
+ -underline 0 -variable ::tkcon::OPT(lightbrace)
+ $m add check -label "Command Highlighting" \
+ -underline 0 -variable ::tkcon::OPT(lightcmd)
+ $m add check -label "History Substitution" \
+ -underline 0 -variable ::tkcon::OPT(subhistory)
+ $m add check -label "Hot Errors" \
+ -underline 0 -variable ::tkcon::OPT(hoterrors)
+ $m add check -label "Non-Tcl Attachments" \
+ -underline 0 -variable ::tkcon::OPT(nontcl)
+ $m add check -label "Calculator Mode" \
+ -underline 1 -variable ::tkcon::OPT(calcmode)
+ $m add check -label "Show Multiple Matches" \
+ -underline 0 -variable ::tkcon::OPT(showmultiple)
+ $m add check -label "Show Menubar" \
+ -underline 5 -variable ::tkcon::OPT(showmenu) \
+ -command {$::tkcon::PRIV(root) configure -menu [expr \
+ {$::tkcon::OPT(showmenu) ? $::tkcon::PRIV(menubar) : {}}]}
+ $m add check -label "Show Statusbar" \
+ -underline 5 -variable ::tkcon::OPT(showstatusbar) \
+ -command {
+ if {$::tkcon::OPT(showstatusbar)} {
+ pack $::tkcon::PRIV(statusbar) -side bottom -fill x \
+ -before $::tkcon::PRIV(scrolly)
+ } else { pack forget $::tkcon::PRIV(statusbar) }
+ }
+ $m add cascade -label "Scrollbar" -underline 2 -menu $m.scroll
+
+ ## Scrollbar Menu
+ ##
+ set m [menu $m.scroll -tearoff 0]
+ $m add radio -label "Left" -value left \
+ -variable ::tkcon::OPT(scrollypos) \
+ -command { pack config $::tkcon::PRIV(scrolly) -side left }
+ $m add radio -label "Right" -value right \
+ -variable ::tkcon::OPT(scrollypos) \
+ -command { pack config $::tkcon::PRIV(scrolly) -side right }
+ }
+
+ ## History Menu
+ ##
+ foreach m [list $w.history $w.pop.history] {
+ menu $m -disabledforeground $COLOR(disabled) \
+ -postcommand [list ::tkcon::HistoryMenu $m]
+ }
+
+ ## Help Menu
+ ##
+ foreach m [list [menu $w.help] [menu $w.pop.help]] {
+ $m add command -label "About " -underline 0 -accel Ctrl-A \
+ -command ::tkcon::About
+ $m add command -label "Retrieve Latest Version" -underline 0 \
+ -command ::tkcon::Retrieve
+ }
+}
+
+## ::tkcon::HistoryMenu - dynamically build the menu for attached interpreters
+##
+# ARGS: m - menu widget
+##
+proc ::tkcon::HistoryMenu m {
+ variable PRIV
+
+ if {![winfo exists $m]} return
+ set id [EvalSlave history nextid]
+ if {$PRIV(histid)==$id} return
+ set PRIV(histid) $id
+ $m delete 0 end
+ while {($id>1) && ($id>$PRIV(histid)-10) && \
+ ![catch {EvalSlave history event [incr id -1]} tmp]} {
+ set lbl $tmp
+ if {[string len $lbl]>32} { set lbl [string range $tmp 0 28]... }
+ $m add command -label "$id: $lbl" -command "
+ $::tkcon::PRIV(console) delete limit end
+ $::tkcon::PRIV(console) insert limit [list $tmp]
+ $::tkcon::PRIV(console) see end
+ ::tkcon::Eval $::tkcon::PRIV(console)"
+ }
+}
+
+## ::tkcon::InterpMenu - dynamically build the menu for attached interpreters
+##
+# ARGS: w - menu widget
+##
+proc ::tkcon::InterpMenu w {
+ variable OPT
+ variable PRIV
+ variable COLOR
+
+ if {![winfo exists $w]} return
+ $w delete 0 end
+ foreach {app type} [Attach] break
+ $w add command -label "[string toupper $type]: $app" -state disabled
+ if {($OPT(nontcl) && [string match interp $type]) || $PRIV(deadapp)} {
+ $w add separator
+ $w add command -state disabled -label "Communication disabled to"
+ $w add command -state disabled -label "dead or non-Tcl interps"
+ return
+ }
+
+ ## Show Last Error
+ ##
+ $w add separator
+ $w add command -label "Show Last Error" \
+ -command [list tkcon error $app $type]
+
+ ## Packages Cascaded Menu
+ ##
+ $w add separator
+ $w add cascade -label Packages -underline 0 -menu $w.pkg
+ set m $w.pkg
+ if {![winfo exists $m]} {
+ menu $m -tearoff no -disabledforeground $COLOR(disabled) \
+ -postcommand [list ::tkcon::PkgMenu $m $app $type]
+ }
+
+ ## State Checkpoint/Revert
+ ##
+ $w add separator
+ $w add command -label "Checkpoint State" \
+ -command [list ::tkcon::StateCheckpoint $app $type]
+ $w add command -label "Revert State" \
+ -command [list ::tkcon::StateRevert $app $type]
+ $w add command -label "View State Change" \
+ -command [list ::tkcon::StateCompare $app $type]
+
+ ## Init Interp
+ ##
+ $w add separator
+ $w add command -label "Send tkcon Commands" \
+ -command [list ::tkcon::InitInterp $app $type]
+}
+
+## ::tkcon::PkgMenu - fill in in the applications sub-menu
+## with a list of all the applications that currently exist.
+##
+proc ::tkcon::PkgMenu {m app type} {
+ # just in case stuff has been added to the auto_path
+ # we have to make sure that the errorInfo doesn't get screwed up
+ EvalAttached {
+ set __tkcon_error $errorInfo
+ catch {package require bogus-package-name}
+ set errorInfo ${__tkcon_error}
+ unset __tkcon_error
+ }
+ $m delete 0 end
+ foreach pkg [EvalAttached [list info loaded {}]] {
+ set loaded([lindex $pkg 1]) [package provide $pkg]
+ }
+ foreach pkg [lremove [EvalAttached {package names}] Tcl] {
+ set version [EvalAttached [list package provide $pkg]]
+ if {[string compare {} $version]} {
+ set loaded($pkg) $version
+ } elseif {![info exists loaded($pkg)]} {
+ set loadable($pkg) [list package require $pkg]
+ }
+ }
+ foreach pkg [EvalAttached {info loaded}] {
+ set pkg [lindex $pkg 1]
+ if {![info exists loaded($pkg)] && ![info exists loadable($pkg)]} {
+ set loadable($pkg) [list load {} $pkg]
+ }
+ }
+ set npkg 0
+ foreach pkg [lsort -dictionary [array names loadable]] {
+ foreach v [EvalAttached [list package version $pkg]] {
+ set brkcol [expr {([incr npkg]%16)==0}]
+ $m add command -label "Load $pkg ($v)" -command \
+ "::tkcon::EvalOther [list $app] $type $loadable($pkg) $v" \
+ -columnbreak $brkcol
+ }
+ }
+ if {[info exists loaded] && [info exists loadable]} {
+ $m add separator
+ }
+ foreach pkg [lsort -dictionary [array names loaded]] {
+ $m add command -label "${pkg}$loaded($pkg) Loaded" -state disabled
+ }
+}
+
+## ::tkcon::AttachMenu - fill in in the applications sub-menu
+## with a list of all the applications that currently exist.
+##
+proc ::tkcon::AttachMenu m {
+ variable OPT
+ variable PRIV
+
+ array set interps [set tmp [Interps]]
+ foreach {i j} $tmp { set tknames($j) {} }
+
+ $m delete 0 end
+ set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}
+ $m add radio -label {None (use local slave) } -accel Ctrl-1 \
+ -variable ::tkcon::PRIV(app) \
+ -value [concat $::tkcon::PRIV(name) $::tkcon::OPT(exec)] \
+ -command "::tkcon::Attach {}; $cmd"
+ $m add separator
+ $m add command -label "Foreign Tk Interpreters" -state disabled
+ foreach i [lsort [lremove [winfo interps] [array names tknames]]] {
+ $m add radio -label $i -variable ::tkcon::PRIV(app) -value $i \
+ -command "::tkcon::Attach [list $i] interp; $cmd"
+ }
+ $m add separator
+
+ $m add command -label "tkcon Interpreters" -state disabled
+ foreach i [lsort [array names interps]] {
+ if {[string match {} $interps($i)]} { set interps($i) "no Tk" }
+ if {[regexp {^Slave[0-9]+} $i]} {
+ set opts [list -label "$i ($interps($i))" \
+ -variable ::tkcon::PRIV(app) -value $i \
+ -command "::tkcon::Attach [list $i] slave; $cmd"]
+ if {[string match $PRIV(name) $i]} {
+ append opts " -accel Ctrl-2"
+ }
+ eval $m add radio $opts
+ } else {
+ set name [concat Main $i]
+ if {[string match Main $name]} {
+ $m add radio -label "$name ($interps($i))" -accel Ctrl-3 \
+ -variable ::tkcon::PRIV(app) -value Main \
+ -command "::tkcon::Attach [list $name] slave; $cmd"
+ } else {
+ $m add radio -label "$name ($interps($i))" \
+ -variable ::tkcon::PRIV(app) -value $i \
+ -command "::tkcon::Attach [list $name] slave; $cmd"
+ }
+ }
+ }
+}
+
+## Displays Cascaded Menu
+##
+proc ::tkcon::DisplayMenu m {
+ $m delete 0 end
+ set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}
+
+ $m add command -label "New Display" -command ::tkcon::NewDisplay
+ foreach disp [Display] {
+ $m add separator
+ $m add command -label $disp -state disabled
+ set res [Display $disp]
+ set win [lindex $res 0]
+ foreach i [lsort [lindex $res 1]] {
+ $m add radio -label $i -variable ::tkcon::PRIV(app) -value $i \
+ -command "::tkcon::Attach [list $i] [list dpy:$win]; $cmd"
+ }
+ }
+}
+
+## Sockets Cascaded Menu
+##
+proc ::tkcon::SocketMenu m {
+ $m delete 0 end
+ set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}
+
+ $m add command -label "Create Connection" \
+ -command "::tkcon::NewSocket; $cmd"
+ foreach sock [file channels sock*] {
+ $m add radio -label $sock -variable ::tkcon::PRIV(app) -value $sock \
+ -command "::tkcon::Attach $sock socket; $cmd"
+ }
+}
+
+## Namepaces Cascaded Menu
+##
+proc ::tkcon::NamespaceMenu m {
+ variable PRIV
+ variable OPT
+
+ $m delete 0 end
+ if {($PRIV(deadapp) || [string match socket $PRIV(apptype)] || \
+ ($OPT(nontcl) && [string match interp $PRIV(apptype)]))} {
+ $m add command -label "No Namespaces" -state disabled
+ return
+ }
+
+ ## Same command as for ::tkcon::AttachMenu items
+ set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}
+
+ set names [lsort [Namespaces ::]]
+ if {[llength $names] > $OPT(maxmenu)} {
+ $m add command -label "Attached to $PRIV(namesp)" -state disabled
+ $m add command -label "List Namespaces" \
+ -command [list ::tkcon::NamespacesList $names]
+ } else {
+ foreach i $names {
+ if {[string match :: $i]} {
+ $m add radio -label "Main" -value $i \
+ -variable ::tkcon::PRIV(namesp) \
+ -command "::tkcon::AttachNamespace [list $i]; $cmd"
+ } else {
+ $m add radio -label $i -value $i \
+ -variable ::tkcon::PRIV(namesp) \
+ -command "::tkcon::AttachNamespace [list $i]; $cmd"
+ }
+ }
+ }
+}
+
+## Namepaces List
+##
+proc ::tkcon::NamespacesList {names} {
+ variable PRIV
+
+ set f $PRIV(base).namespaces
+ catch {destroy $f}
+ toplevel $f
+ listbox $f.names -width 30 -height 15 -selectmode single \
+ -yscrollcommand [list $f.scrollv set] \
+ -xscrollcommand [list $f.scrollh set]
+ scrollbar $f.scrollv -command [list $f.names yview]
+ scrollbar $f.scrollh -command [list $f.names xview] -orient horizontal
+ frame $f.buttons
+ button $f.cancel -text "Cancel" -command [list destroy $f]
+
+ grid $f.names $f.scrollv -sticky nesw
+ grid $f.scrollh -sticky ew
+ grid $f.buttons -sticky nesw
+ grid $f.cancel -in $f.buttons -pady 6
+
+ grid columnconfigure $f 0 -weight 1
+ grid rowconfigure $f 0 -weight 1
+ #fill the listbox
+ foreach i $names {
+ if {[string match :: $i]} {
+ $f.names insert 0 Main
+ } else {
+ $f.names insert end $i
+ }
+ }
+ #Bindings
+ bind $f.names <Double-1> {
+ ## Catch in case the namespace disappeared on us
+ catch { ::tkcon::AttachNamespace [%W get [%W nearest %y]] }
+ ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]
+ destroy [winfo toplevel %W]
+ }
+}
+
+# ::tkcon::XauthSecure --
+#
+# This removes all the names in the xhost list, and secures
+# the display for Tk send commands. Of course, this prevents
+# what might have been otherwise allowable X connections
+#
+# Arguments:
+# none
+# Results:
+# Returns nothing
+#
+proc ::tkcon::XauthSecure {} {
+ global tcl_platform
+
+ if {[string compare unix $tcl_platform(platform)]} {
+ # This makes no sense outside of Unix
+ return
+ }
+ set hosts [exec xhost]
+ # the first line is info only
+ foreach host [lrange [split $hosts \n] 1 end] {
+ exec xhost -$host
+ }
+ exec xhost -
+ tk_messageBox -title "Xhost secured" -message "Xhost secured" -icon info
+}
+
+## ::tkcon::FindBox - creates minimal dialog interface to ::tkcon::Find
+# ARGS: w - text widget
+# str - optional seed string for ::tkcon::PRIV(find)
+##
+proc ::tkcon::FindBox {w {str {}}} {
+ variable PRIV
+
+ set base $PRIV(base).find
+ if {![winfo exists $base]} {
+ toplevel $base
+ wm withdraw $base
+ wm title $base "tkcon Find"
+
+ pack [frame $base.f] -fill x -expand 1
+ label $base.f.l -text "Find:"
+ entry $base.f.e -textvariable ::tkcon::PRIV(find)
+ pack [frame $base.opt] -fill x
+ checkbutton $base.opt.c -text "Case Sensitive" \
+ -variable ::tkcon::PRIV(find,case)
+ checkbutton $base.opt.r -text "Use Regexp" -variable ::tkcon::PRIV(find,reg)
+ pack $base.f.l -side left
+ pack $base.f.e $base.opt.c $base.opt.r -side left -fill both -expand 1
+ pack [frame $base.sep -bd 2 -relief sunken -height 4] -fill x
+ pack [frame $base.btn] -fill both
+ button $base.btn.fnd -text "Find" -width 6
+ button $base.btn.clr -text "Clear" -width 6
+ button $base.btn.dis -text "Dismiss" -width 6
+ eval pack [winfo children $base.btn] -padx 4 -pady 2 \
+ -side left -fill both
+
+ focus $base.f.e
+
+ bind $base.f.e <Return> [list $base.btn.fnd invoke]
+ bind $base.f.e <Escape> [list $base.btn.dis invoke]
+ }
+ $base.btn.fnd config -command "::tkcon::Find [list $w] \$::tkcon::PRIV(find) \
+ -case \$::tkcon::PRIV(find,case) -reg \$::tkcon::PRIV(find,reg)"
+ $base.btn.clr config -command "
+ [list $w] tag remove find 1.0 end
+ set ::tkcon::PRIV(find) {}
+ "
+ $base.btn.dis config -command "
+ [list $w] tag remove find 1.0 end
+ wm withdraw [list $base]
+ "
+ if {[string compare {} $str]} {
+ set PRIV(find) $str
+ $base.btn.fnd invoke
+ }
+
+ if {[string compare normal [wm state $base]]} {
+ wm deiconify $base
+ } else { raise $base }
+ $base.f.e select range 0 end
+}
+
+## ::tkcon::Find - searches in text widget $w for $str and highlights it
+## If $str is empty, it just deletes any highlighting
+# ARGS: w - text widget
+# str - string to search for
+# -case TCL_BOOLEAN whether to be case sensitive DEFAULT: 0
+# -regexp TCL_BOOLEAN whether to use $str as pattern DEFAULT: 0
+##
+proc ::tkcon::Find {w str args} {
+ $w tag remove find 1.0 end
+ set truth {^(1|yes|true|on)$}
+ set opts {}
+ foreach {key val} $args {
+ switch -glob -- $key {
+ -c* { if {[regexp -nocase $truth $val]} { set case 1 } }
+ -r* { if {[regexp -nocase $truth $val]} { lappend opts -regexp } }
+ default { return -code error "Unknown option $key" }
+ }
+ }
+ if {![info exists case]} { lappend opts -nocase }
+ if {[string match {} $str]} return
+ $w mark set findmark 1.0
+ while {[string compare {} [set ix [eval $w search $opts -count numc -- \
+ [list $str] findmark end]]]} {
+ $w tag add find $ix ${ix}+${numc}c
+ $w mark set findmark ${ix}+1c
+ }
+ $w tag configure find -background $::tkcon::COLOR(blink)
+ catch {$w see find.first}
+ return [expr {[llength [$w tag ranges find]]/2}]
+}
+
+## ::tkcon::Attach - called to attach tkcon to an interpreter
+# ARGS: name - application name to which tkcon sends commands
+# This is either a slave interperter name or tk appname.
+# type - (slave|interp) type of interpreter we're attaching to
+# slave means it's a tkcon interpreter
+# interp means we'll need to 'send' to it.
+# Results: ::tkcon::EvalAttached is recreated to evaluate in the
+# appropriate interpreter
+##
+proc ::tkcon::Attach {{name <NONE>} {type slave}} {
+ variable PRIV
+ variable OPT
+
+ if {[llength [info level 0]] == 1} {
+ # no args were specified, return the attach info instead
+ if {[string match {} $PRIV(appname)]} {
+ return [list [concat $PRIV(name) $OPT(exec)] $PRIV(apptype)]
+ } else {
+ return [list $PRIV(appname) $PRIV(apptype)]
+ }
+ }
+ set path [concat $PRIV(name) $OPT(exec)]
+
+ set PRIV(displayWin) .
+ if {[string match namespace $type]} {
+ return [uplevel 1 ::tkcon::AttachNamespace $name]
+ } elseif {[string match dpy:* $type]} {
+ set PRIV(displayWin) [string range $type 4 end]
+ } elseif {[string match sock* $type]} {
+ global tcl_version
+ if {[catch {eof $name} res]} {
+ return -code error "No known channel \"$name\""
+ } elseif {$res} {
+ catch {close $name}
+ return -code error "Channel \"$name\" returned EOF"
+ }
+ set app $name
+ set type socket
+ } elseif {[string compare {} $name]} {
+ array set interps [Interps]
+ if {[string match {[Mm]ain} [lindex $name 0]]} {
+ set name [lrange $name 1 end]
+ }
+ if {[string match $path $name]} {
+ set name {}
+ set app $path
+ set type slave
+ } elseif {[info exists interps($name)]} {
+ if {[string match {} $name]} { set name Main; set app Main }
+ set type slave
+ } elseif {[interp exists $name]} {
+ set name [concat $PRIV(name) $name]
+ set type slave
+ } elseif {[interp exists [concat $OPT(exec) $name]]} {
+ set name [concat $path $name]
+ set type slave
+ } elseif {[lsearch -exact [winfo interps] $name] > -1} {
+ if {[EvalSlave info exists tk_library] \
+ && [string match $name [EvalSlave tk appname]]} {
+ set name {}
+ set app $path
+ set type slave
+ } elseif {[set i [lsearch -exact \
+ [Main set ::tkcon::PRIV(interps)] $name]] != -1} {
+ set name [lindex [Main set ::tkcon::PRIV(slaves)] $i]
+ if {[string match {[Mm]ain} $name]} { set app Main }
+ set type slave
+ } else {
+ set type interp
+ }
+ } else {
+ return -code error "No known interpreter \"$name\""
+ }
+ } else {
+ set app $path
+ }
+ if {![info exists app]} { set app $name }
+ array set PRIV [list app $app appname $name apptype $type deadapp 0]
+
+ ## ::tkcon::EvalAttached - evaluates the args in the attached interp
+ ## args should be passed to this procedure as if they were being
+ ## passed to the 'eval' procedure. This procedure is dynamic to
+ ## ensure evaluation occurs in the right interp.
+ # ARGS: args - the command and args to evaluate
+ ##
+ switch -glob -- $type {
+ slave {
+ if {[string match {} $name]} {
+ interp alias {} ::tkcon::EvalAttached {} \
+ ::tkcon::EvalSlave uplevel \#0
+ } elseif {[string match Main $PRIV(app)]} {
+ interp alias {} ::tkcon::EvalAttached {} ::tkcon::Main
+ } elseif {[string match $PRIV(name) $PRIV(app)]} {
+ interp alias {} ::tkcon::EvalAttached {} uplevel \#0
+ } else {
+ interp alias {} ::tkcon::EvalAttached {} \
+ ::tkcon::Slave $::tkcon::PRIV(app)
+ }
+ }
+ sock* {
+ interp alias {} ::tkcon::EvalAttached {} \
+ ::tkcon::EvalSlave uplevel \#0
+ # The file event will just puts whatever data is found
+ # into the interpreter
+ fconfigure $name -buffering line -blocking 0
+ fileevent $name readable ::tkcon::EvalSocketEvent
+ }
+ dpy:* -
+ interp {
+ if {$OPT(nontcl)} {
+ interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSlave
+ set PRIV(namesp) ::
+ } else {
+ interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSend
+ }
+ }
+ default {
+ return -code error "[lindex [info level 0] 0] did not specify\
+ a valid type: must be slave or interp"
+ }
+ }
+ if {[string match slave $type] || \
+ (!$OPT(nontcl) && [regexp {^(interp|dpy)} $type])} {
+ set PRIV(namesp) ::
+ }
+ set PRIV(StatusAttach) "$PRIV(app) ($PRIV(apptype))"
+ return
+}
+
+## ::tkcon::AttachNamespace - called to attach tkcon to a namespace
+# ARGS: name - namespace name in which tkcon should eval commands
+# Results: ::tkcon::EvalAttached will be modified
+##
+proc ::tkcon::AttachNamespace { name } {
+ variable PRIV
+ variable OPT
+
+ if {($OPT(nontcl) && [string match interp $PRIV(apptype)]) \
+ || [string match socket $PRIV(apptype)] \
+ || $PRIV(deadapp)} {
+ return -code error "can't attach to namespace in attached environment"
+ }
+ if {[string match Main $name]} {set name ::}
+ if {[string compare {} $name] && \
+ [lsearch [Namespaces ::] $name] == -1} {
+ return -code error "No known namespace \"$name\""
+ }
+ if {[regexp {^(|::)$} $name]} {
+ ## If name=={} || ::, we want the primary namespace
+ set alias [interp alias {} ::tkcon::EvalAttached]
+ if {[string match ::tkcon::EvalNamespace* $alias]} {
+ eval [list interp alias {} ::tkcon::EvalAttached {}] \
+ [lindex $alias 1]
+ }
+ set name ::
+ } else {
+ interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalNamespace \
+ [interp alias {} ::tkcon::EvalAttached] [list $name]
+ }
+ set PRIV(namesp) $name
+ set PRIV(StatusAttach) "$PRIV(app) $PRIV(namesp) ($PRIV(apptype))"
+}
+
+## ::tkcon::NewSocket - called to create a socket to connect to
+# ARGS: none
+# Results: It will create a socket, and attach if requested
+##
+proc ::tkcon::NewSocket {} {
+ variable PRIV
+
+ set t $PRIV(base).newsock
+ if {![winfo exists $t]} {
+ toplevel $t
+ wm withdraw $t
+ wm title $t "tkcon Create Socket"
+ label $t.lhost -text "Host: "
+ entry $t.host -width 20
+ label $t.lport -text "Port: "
+ entry $t.port -width 4
+ button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1}
+ bind $t.host <Return> [list focus $t.port]
+ bind $t.port <Return> [list focus $t.ok]
+ bind $t.ok <Return> [list $t.ok invoke]
+ grid $t.lhost $t.host $t.lport $t.port -sticky ew
+ grid $t.ok - - - -sticky ew
+ grid columnconfig $t 1 -weight 1
+ grid rowconfigure $t 1 -weight 1
+ wm transient $t $PRIV(root)
+ wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \
+ reqwidth $t]) / 2}]+[expr {([winfo \
+ screenheight $t]-[winfo reqheight $t]) / 2}]
+ }
+ #$t.host delete 0 end
+ #$t.port delete 0 end
+ wm deiconify $t
+ raise $t
+ grab $t
+ focus $t.host
+ vwait ::tkcon::PRIV(grab)
+ grab release $t
+ wm withdraw $t
+ set host [$t.host get]
+ set port [$t.port get]
+ if {$host == ""} { return }
+ if {[catch {
+ set sock [socket $host $port]
+ } err]} {
+ tk_messageBox -title "Socket Connection Error" \
+ -message "Unable to connect to \"$host:$port\":\n$err" \
+ -icon error -type ok
+ } else {
+ Attach $sock socket
+ }
+}
+
+## ::tkcon::Load - sources a file into the console
+## The file is actually sourced in the currently attached's interp
+# ARGS: fn - (optional) filename to source in
+# Returns: selected filename ({} if nothing was selected)
+##
+proc ::tkcon::Load { {fn ""} } {
+ set types {
+ {{Tcl Files} {.tcl .tk}}
+ {{Text Files} {.txt}}
+ {{All Files} *}
+ }
+ if {
+ [string match {} $fn] &&
+ ([catch {tk_getOpenFile -filetypes $types \
+ -title "Source File"} fn] || [string match {} $fn])
+ } { return }
+ EvalAttached [list source $fn]
+}
+
+## ::tkcon::Save - saves the console or other widget buffer to a file
+## This does not eval in a slave because it's not necessary
+# ARGS: w - console text widget
+# fn - (optional) filename to save to
+##
+proc ::tkcon::Save { {fn ""} {type ""} {opt ""} {mode w} } {
+ variable PRIV
+
+ if {![regexp -nocase {^(all|history|stdin|stdout|stderr|widget)$} $type]} {
+ array set s { 0 All 1 History 2 Stdin 3 Stdout 4 Stderr 5 Cancel }
+ ## Allow user to specify what kind of stuff to save
+ set type [tk_dialog $PRIV(base).savetype "Save Type" \
+ "What part of the text do you want to save?" \
+ questhead 0 $s(0) $s(1) $s(2) $s(3) $s(4) $s(5)]
+ if {$type == 5 || $type == -1} return
+ set type $s($type)
+ }
+ if {[string match {} $fn]} {
+ set types {
+ {{Tcl Files} {.tcl .tk}}
+ {{Text Files} {.txt}}
+ {{All Files} *}
+ }
+ if {[catch {tk_getSaveFile -defaultextension .tcl -filetypes $types \
+ -title "Save $type"} fn] || [string match {} $fn]} return
+ }
+ set type [string tolower $type]
+ switch $type {
+ stdin - stdout - stderr {
+ set data {}
+ foreach {first last} [$PRIV(console) tag ranges $type] {
+ lappend data [$PRIV(console) get $first $last]
+ }
+ set data [join $data \n]
+ }
+ history { set data [tkcon history] }
+ all - default { set data [$PRIV(console) get 1.0 end-1c] }
+ widget {
+ set data [$opt get 1.0 end-1c]
+ }
+ }
+ if {[catch {open $fn $mode} fid]} {
+ return -code error "Save Error: Unable to open '$fn' for writing\n$fid"
+ }
+ puts -nonewline $fid $data
+ close $fid
+}
+
+## ::tkcon::MainInit
+## This is only called for the main interpreter to include certain procs
+## that we don't want to include (or rather, just alias) in slave interps.
+##
+proc ::tkcon::MainInit {} {
+ variable PRIV
+
+ if {![info exists PRIV(slaves)]} {
+ array set PRIV [list slave 0 slaves Main name {} \
+ interps [list [tk appname]]]
+ }
+ interp alias {} ::tkcon::Main {} ::tkcon::InterpEval Main
+ interp alias {} ::tkcon::Slave {} ::tkcon::InterpEval
+
+ proc ::tkcon::GetSlaveNum {} {
+ set i -1
+ while {[interp exists Slave[incr i]]} {
+ # oh my god, an empty loop!
+ }
+ return $i
+ }
+
+ ## ::tkcon::New - create new console window
+ ## Creates a slave interpreter and sources in this script.
+ ## All other interpreters also get a command to eval function in the
+ ## new interpreter.
+ ##
+ proc ::tkcon::New {} {
+ variable PRIV
+ global argv0 argc argv
+
+ set tmp [interp create Slave[GetSlaveNum]]
+ lappend PRIV(slaves) $tmp
+ load {} Tk $tmp
+ lappend PRIV(interps) [$tmp eval [list tk appname \
+ "[tk appname] $tmp"]]
+ if {[info exist argv0]} {$tmp eval [list set argv0 $argv0]}
+ $tmp eval set argc $argc
+ $tmp eval [list set argv $argv]
+ $tmp eval [list namespace eval ::tkcon {}]
+ $tmp eval [list set ::tkcon::PRIV(name) $tmp]
+ $tmp eval [list set ::tkcon::PRIV(SCRIPT) $::tkcon::PRIV(SCRIPT)]
+ $tmp alias exit ::tkcon::Exit $tmp
+ $tmp alias ::tkcon::Destroy ::tkcon::Destroy $tmp
+ $tmp alias ::tkcon::New ::tkcon::New
+ $tmp alias ::tkcon::Main ::tkcon::InterpEval Main
+ $tmp alias ::tkcon::Slave ::tkcon::InterpEval
+ $tmp alias ::tkcon::Interps ::tkcon::Interps
+ $tmp alias ::tkcon::NewDisplay ::tkcon::NewDisplay
+ $tmp alias ::tkcon::Display ::tkcon::Display
+ $tmp alias ::tkcon::StateCheckpoint ::tkcon::StateCheckpoint
+ $tmp alias ::tkcon::StateCleanup ::tkcon::StateCleanup
+ $tmp alias ::tkcon::StateCompare ::tkcon::StateCompare
+ $tmp alias ::tkcon::StateRevert ::tkcon::StateRevert
+ $tmp eval {
+ if [catch {source -rsrc tkcon}] { source $::tkcon::PRIV(SCRIPT) }
+ }
+ return $tmp
+ }
+
+ ## ::tkcon::Exit - full exit OR destroy slave console
+ ## This proc should only be called in the main interpreter from a slave.
+ ## The master determines whether we do a full exit or just kill the slave.
+ ##
+ proc ::tkcon::Exit {slave args} {
+ variable PRIV
+ variable OPT
+
+ ## Slave interpreter exit request
+ if {[string match exit $OPT(slaveexit)]} {
+ ## Only exit if it specifically is stated to do so
+ uplevel 1 exit $args
+ }
+ ## Otherwise we will delete the slave interp and associated data
+ set name [InterpEval $slave]
+ set PRIV(interps) [lremove $PRIV(interps) [list $name]]
+ set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]]
+ interp delete $slave
+ StateCleanup $slave
+ return
+ }
+
+ ## ::tkcon::Destroy - destroy console window
+ ## This proc should only be called by the main interpreter. If it is
+ ## called from there, it will ask before exiting tkcon. All others
+ ## (slaves) will just have their slave interpreter deleted, closing them.
+ ##
+ proc ::tkcon::Destroy {{slave {}}} {
+ variable PRIV
+
+ if {[string match {} $slave]} {
+ ## Main interpreter close request
+ if {[tk_dialog $PRIV(base).destroyme {Quit tkcon?} \
+ {Closing the Main console will quit tkcon} \
+ warning 0 "Don't Quit" "Quit tkcon"]} exit
+ } else {
+ ## Slave interpreter close request
+ set name [InterpEval $slave]
+ set PRIV(interps) [lremove $PRIV(interps) [list $name]]
+ set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]]
+ interp delete $slave
+ }
+ StateCleanup $slave
+ return
+ }
+
+ ## We want to do a couple things before exiting...
+ if {[catch {rename ::exit ::tkcon::FinalExit} err]} {
+ puts stderr "tkcon might panic:\n$err"
+ }
+ proc ::exit args {
+ if {$::tkcon::OPT(usehistory)} {
+ if {[catch {open $::tkcon::PRIV(histfile) w} fid]} {
+ puts stderr "unable to save history file:\n$fid"
+ # pause a moment, because we are about to die finally...
+ after 1000
+ } else {
+ set max [::tkcon::EvalSlave history nextid]
+ set id [expr {$max - $::tkcon::OPT(history)}]
+ if {$id < 1} { set id 1 }
+ ## FIX: This puts history in backwards!!
+ while {($id < $max) && \
+ ![catch {::tkcon::EvalSlave history event $id} cmd]} {
+ if {[string compare {} $cmd]} {
+ puts $fid "::tkcon::EvalSlave history add [list $cmd]"
+ }
+ incr id
+ }
+ close $fid
+ }
+ }
+ uplevel 1 ::tkcon::FinalExit $args
+ }
+
+ ## ::tkcon::InterpEval - passes evaluation to another named interpreter
+ ## If the interpreter is named, but no args are given, it returns the
+ ## [tk appname] of that interps master (not the associated eval slave).
+ ##
+ proc ::tkcon::InterpEval {{slave {}} args} {
+ variable PRIV
+
+ if {[string match {} $slave]} {
+ return $PRIV(slaves)
+ } elseif {[string match {[Mm]ain} $slave]} {
+ set slave {}
+ }
+ if {[llength $args]} {
+ return [interp eval $slave uplevel \#0 $args]
+ } else {
+ return [interp eval $slave tk appname]
+ }
+ }
+
+ proc ::tkcon::Interps {{ls {}} {interp {}}} {
+ if {[string match {} $interp]} { lappend ls {} [tk appname] }
+ foreach i [interp slaves $interp] {
+ if {[string compare {} $interp]} { set i "$interp $i" }
+ if {[string compare {} [interp eval $i package provide Tk]]} {
+ lappend ls $i [interp eval $i tk appname]
+ } else {
+ lappend ls $i {}
+ }
+ set ls [Interps $ls $i]
+ }
+ return $ls
+ }
+
+ proc ::tkcon::Display {{disp {}}} {
+ variable DISP
+
+ set res {}
+ if {$disp != ""} {
+ if {![info exists DISP($disp)]} { return }
+ return [list $DISP($disp) [winfo interps -displayof $DISP($disp)]]
+ }
+ return [lsort -dictionary [array names DISP]]
+ }
+
+ proc ::tkcon::NewDisplay {} {
+ variable PRIV
+ variable DISP
+
+ set t $PRIV(base).newdisp
+ if {![winfo exists $t]} {
+ toplevel $t
+ wm withdraw $t
+ wm title $t "tkcon Attach to Display"
+ label $t.gets -text "New Display: "
+ entry $t.data -width 32
+ button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1}
+ bind $t.data <Return> [list $t.ok invoke]
+ bind $t.ok <Return> [list $t.ok invoke]
+ grid $t.gets $t.data -sticky ew
+ grid $t.ok - -sticky ew
+ grid columnconfig $t 1 -weight 1
+ grid rowconfigure $t 1 -weight 1
+ wm transient $t $PRIV(root)
+ wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \
+ reqwidth $t]) / 2}]+[expr {([winfo \
+ screenheight $t]-[winfo reqheight $t]) / 2}]
+ }
+ $t.data delete 0 end
+ wm deiconify $t
+ raise $t
+ grab $t
+ focus $t.data
+ vwait ::tkcon::PRIV(grab)
+ grab release $t
+ wm withdraw $t
+ set disp [$t.data get]
+ if {$disp == ""} { return }
+ regsub -all {\.} [string tolower $disp] ! dt
+ set dt $PRIV(base).$dt
+ destroy $dt
+ if {[catch {
+ toplevel $dt -screen $disp
+ set interps [winfo interps -displayof $dt]
+ if {![llength $interps]} {
+ error "No other Tk interpreters on $disp"
+ }
+ send -displayof $dt [lindex $interps 0] [list info tclversion]
+ } err]} {
+ global env
+ if {[info exists env(DISPLAY)]} {
+ set myd $env(DISPLAY)
+ } else {
+ set myd "myDisplay:0"
+ }
+ tk_messageBox -title "Display Connection Error" \
+ -message "Unable to connect to \"$disp\":\n$err\
+ \nMake sure you have xauth-based permissions\
+ (xauth add $myd . `mcookie`), and xhost is disabled\
+ (xhost -) on \"$disp\"" \
+ -icon error -type ok
+ destroy $dt
+ return
+ }
+ set DISP($disp) $dt
+ wm withdraw $dt
+ bind $dt <Destroy> [subst {catch {unset ::tkcon::DISP($disp)}}]
+ tk_messageBox -title "$disp Connection" \
+ -message "Connected to \"$disp\", found:\n[join $interps \n]" \
+ -type ok
+ }
+
+ ##
+ ## The following state checkpoint/revert procedures are very sketchy
+ ## and prone to problems. They do not track modifications to currently
+ ## existing procedures/variables, and they can really screw things up
+ ## if you load in libraries (especially Tk) between checkpoint and
+ ## revert. Only with this knowledge in mind should you use these.
+ ##
+
+ ## ::tkcon::StateCheckpoint - checkpoints the current state of the system
+ ## This allows you to return to this state with ::tkcon::StateRevert
+ # ARGS:
+ ##
+ proc ::tkcon::StateCheckpoint {app type} {
+ variable CPS
+ variable PRIV
+
+ if {[info exists CPS($type,$app,cmd)] && \
+ [tk_dialog $PRIV(base).warning "Overwrite Previous State?" \
+ "Are you sure you want to lose previously checkpointed\
+ state of $type \"$app\"?" questhead 1 "Do It" "Cancel"]} return
+ set CPS($type,$app,cmd) [EvalOther $app $type info commands *]
+ set CPS($type,$app,var) [EvalOther $app $type info vars *]
+ return
+ }
+
+ ## ::tkcon::StateCompare - compare two states and output difference
+ # ARGS:
+ ##
+ proc ::tkcon::StateCompare {app type {verbose 0}} {
+ variable CPS
+ variable PRIV
+ variable OPT
+ variable COLOR
+
+ if {![info exists CPS($type,$app,cmd)]} {
+ return -code error \
+ "No previously checkpointed state for $type \"$app\""
+ }
+ set w $PRIV(base).compare
+ if {[winfo exists $w]} {
+ $w.text config -state normal
+ $w.text delete 1.0 end
+ } else {
+ toplevel $w
+ frame $w.btn
+ scrollbar $w.sy -takefocus 0 -bd 1 -command [list $w.text yview]
+ text $w.text -yscrollcommand [list $w.sy set] -height 12 \
+ -foreground $COLOR(stdin) \
+ -background $COLOR(bg) \
+ -insertbackground $COLOR(cursor) \
+ -font $OPT(font)
+ pack $w.btn -side bottom -fill x
+ pack $w.sy -side right -fill y
+ pack $w.text -fill both -expand 1
+ button $w.btn.close -text "Dismiss" -width 11 \
+ -command [list destroy $w]
+ button $w.btn.check -text "Recheckpoint" -width 11
+ button $w.btn.revert -text "Revert" -width 11
+ button $w.btn.expand -text "Verbose" -width 11
+ button $w.btn.update -text "Update" -width 11
+ pack $w.btn.check $w.btn.revert $w.btn.expand $w.btn.update \
+ $w.btn.close -side left -fill x -padx 4 -pady 2 -expand 1
+ $w.text tag config red -foreground red
+ }
+ wm title $w "Compare State: $type [list $app]"
+
+ $w.btn.check config \
+ -command "::tkcon::StateCheckpoint [list $app] $type; \
+ ::tkcon::StateCompare [list $app] $type $verbose"
+ $w.btn.revert config \
+ -command "::tkcon::StateRevert [list $app] $type; \
+ ::tkcon::StateCompare [list $app] $type $verbose"
+ $w.btn.update config -command [info level 0]
+ if {$verbose} {
+ $w.btn.expand config -text Brief \
+ -command [list ::tkcon::StateCompare $app $type 0]
+ } else {
+ $w.btn.expand config -text Verbose \
+ -command [list ::tkcon::StateCompare $app $type 1]
+ }
+ ## Don't allow verbose mode unless 'dump' exists in $app
+ ## We're assuming this is tkcon's dump command
+ set hasdump [llength [EvalOther $app $type info commands dump]]
+ if {$hasdump} {
+ $w.btn.expand config -state normal
+ } else {
+ $w.btn.expand config -state disabled
+ }
+
+ set cmds [lremove [EvalOther $app $type info commands *] \
+ $CPS($type,$app,cmd)]
+ set vars [lremove [EvalOther $app $type info vars *] \
+ $CPS($type,$app,var)]
+
+ if {$hasdump && $verbose} {
+ set cmds [EvalOther $app $type eval dump c -nocomplain $cmds]
+ set vars [EvalOther $app $type eval dump v -nocomplain $vars]
+ }
+ $w.text insert 1.0 "NEW COMMANDS IN \"$app\":\n" red \
+ $cmds {} "\n\nNEW VARIABLES IN \"$app\":\n" red $vars {}
+
+ raise $w
+ $w.text config -state disabled
+ }
+
+ ## ::tkcon::StateRevert - reverts interpreter to previous state
+ # ARGS:
+ ##
+ proc ::tkcon::StateRevert {app type} {
+ variable CPS
+ variable PRIV
+
+ if {![info exists CPS($type,$app,cmd)]} {
+ return -code error \
+ "No previously checkpointed state for $type \"$app\""
+ }
+ if {![tk_dialog $PRIV(base).warning "Revert State?" \
+ "Are you sure you want to revert the state in $type \"$app\"?"\
+ questhead 1 "Do It" "Cancel"]} {
+ foreach i [lremove [EvalOther $app $type info commands *] \
+ $CPS($type,$app,cmd)] {
+ catch {EvalOther $app $type rename $i {}}
+ }
+ foreach i [lremove [EvalOther $app $type info vars *] \
+ $CPS($type,$app,var)] {
+ catch {EvalOther $app $type unset $i}
+ }
+ }
+ }
+
+ ## ::tkcon::StateCleanup - cleans up state information in master array
+ #
+ ##
+ proc ::tkcon::StateCleanup {args} {
+ variable CPS
+
+ if {![llength $args]} {
+ foreach state [array names CPS slave,*] {
+ if {![interp exists [string range $state 6 end]]} {
+ unset CPS($state)
+ }
+ }
+ } else {
+ set app [lindex $args 0]
+ set type [lindex $args 1]
+ if {[regexp {^(|slave)$} $type]} {
+ foreach state [array names CPS "slave,$app\[, \]*"] {
+ if {![interp exists [string range $state 6 end]]} {
+ unset CPS($state)
+ }
+ }
+ } else {
+ catch {unset CPS($type,$app)}
+ }
+ }
+ }
+}
+
+## ::tkcon::Event - get history event, search if string != {}
+## look forward (next) if $int>0, otherwise look back (prev)
+# ARGS: W - console widget
+##
+proc ::tkcon::Event {int {str {}}} {
+ if {!$int} return
+
+ variable PRIV
+ set w $PRIV(console)
+
+ set nextid [EvalSlave history nextid]
+ if {[string compare {} $str]} {
+ ## String is not empty, do an event search
+ set event $PRIV(event)
+ if {$int < 0 && $event == $nextid} { set PRIV(cmdbuf) $str }
+ set len [string len $PRIV(cmdbuf)]
+ incr len -1
+ if {$int > 0} {
+ ## Search history forward
+ while {$event < $nextid} {
+ if {[incr event] == $nextid} {
+ $w delete limit end
+ $w insert limit $PRIV(cmdbuf)
+ break
+ } elseif {
+ ![catch {EvalSlave history event $event} res] &&
+ [set p [string first $PRIV(cmdbuf) $res]] > -1
+ } {
+ set p2 [expr {$p + [string length $PRIV(cmdbuf)]}]
+ $w delete limit end
+ $w insert limit $res
+ Blink $w "limit + $p c" "limit + $p2 c"
+ break
+ }
+ }
+ set PRIV(event) $event
+ } else {
+ ## Search history reverse
+ while {![catch {EvalSlave history event [incr event -1]} res]} {
+ if {[set p [string first $PRIV(cmdbuf) $res]] > -1} {
+ set p2 [expr {$p + [string length $PRIV(cmdbuf)]}]
+ $w delete limit end
+ $w insert limit $res
+ set PRIV(event) $event
+ Blink $w "limit + $p c" "limit + $p2 c"
+ break
+ }
+ }
+ }
+ } else {
+ ## String is empty, just get next/prev event
+ if {$int > 0} {
+ ## Goto next command in history
+ if {$PRIV(event) < $nextid} {
+ $w delete limit end
+ if {[incr PRIV(event)] == $nextid} {
+ $w insert limit $PRIV(cmdbuf)
+ } else {
+ $w insert limit [EvalSlave history event $PRIV(event)]
+ }
+ }
+ } else {
+ ## Goto previous command in history
+ if {$PRIV(event) == $nextid} {
+ set PRIV(cmdbuf) [CmdGet $w]
+ }
+ if {[catch {EvalSlave history event [incr PRIV(event) -1]} res]} {
+ incr PRIV(event)
+ } else {
+ $w delete limit end
+ $w insert limit $res
+ }
+ }
+ }
+ $w mark set insert end
+ $w see end
+}
+
+## ::tkcon::ErrorHighlight - magic error highlighting
+## beware: voodoo included
+# ARGS:
+##
+proc ::tkcon::ErrorHighlight w {
+ variable COLOR
+
+ ## do voodoo here
+ set app [Attach]
+ # we have to pull the text out, because text regexps are screwed on \n's.
+ set info [$w get 1.0 end-1c]
+ # Check for specific line error in a proc
+ set exp(proc) "\"(\[^\"\]+)\"\n\[\t \]+\\\(procedure \"(\[^\"\]+)\""
+ # Check for too few args to a proc
+ set exp(param) "parameter \"(\[^\"\]+)\" to \"(\[^\"\]+)\""
+ set start 1.0
+ while {
+ [regexp -indices -- $exp(proc) $info junk what cmd] ||
+ [regexp -indices -- $exp(param) $info junk what cmd]
+ } {
+ foreach {w0 w1} $what {c0 c1} $cmd {break}
+ set what [string range $info $w0 $w1]
+ set cmd [string range $info $c0 $c1]
+ if {[string match *::* $cmd]} {
+ set res [uplevel 1 ::tkcon::EvalOther $app namespace eval \
+ [list [namespace qualifiers $cmd] \
+ [list info procs [namespace tail $cmd]]]]
+ } else {
+ set res [uplevel 1 ::tkcon::EvalOther $app info procs [list $cmd]]
+ }
+ if {[llength $res]==1} {
+ set tag [UniqueTag $w]
+ $w tag add $tag $start+${c0}c $start+1c+${c1}c
+ $w tag configure $tag -foreground $COLOR(stdout)
+ $w tag bind $tag <Enter> [list $w tag configure $tag -under 1]
+ $w tag bind $tag <Leave> [list $w tag configure $tag -under 0]
+ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
+ {[list edit -attach $app -type proc -find $what -- $cmd]}"
+ }
+ set info [string range $info $c1 end]
+ set start [$w index $start+${c1}c]
+ }
+ ## Next stage, check for procs that start a line
+ set start 1.0
+ set exp(cmd) "^\"\[^\" \t\n\]+"
+ while {
+ [string compare {} [set ix \
+ [$w search -regexp -count numc -- $exp(cmd) $start end]]]
+ } {
+ set start [$w index $ix+${numc}c]
+ # +1c to avoid the first quote
+ set cmd [$w get $ix+1c $start]
+ if {[string match *::* $cmd]} {
+ set res [uplevel 1 ::tkcon::EvalOther $app namespace eval \
+ [list [namespace qualifiers $cmd] \
+ [list info procs [namespace tail $cmd]]]]
+ } else {
+ set res [uplevel 1 ::tkcon::EvalOther $app info procs [list $cmd]]
+ }
+ if {[llength $res]==1} {
+ set tag [UniqueTag $w]
+ $w tag add $tag $ix+1c $start
+ $w tag configure $tag -foreground $COLOR(proc)
+ $w tag bind $tag <Enter> [list $w tag configure $tag -under 1]
+ $w tag bind $tag <Leave> [list $w tag configure $tag -under 0]
+ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
+ {[list edit -attach $app -type proc -- $cmd]}"
+ }
+ }
+}
+
+## tkcon - command that allows control over the console
+## This always exists in the main interpreter, and is aliased into
+## other connected interpreters
+# ARGS: totally variable, see internal comments
+##
+proc tkcon {cmd args} {
+ global errorInfo
+
+ switch -glob -- $cmd {
+ buf* {
+ ## 'buffer' Sets/Query the buffer size
+ if {[llength $args]} {
+ if {[regexp {^[1-9][0-9]*$} $args]} {
+ set ::tkcon::OPT(buffer) $args
+ # catch in case the console doesn't exist yet
+ catch {::tkcon::ConstrainBuffer $::tkcon::PRIV(console) \
+ $::tkcon::OPT(buffer)}
+ } else {
+ return -code error "buffer must be a valid integer"
+ }
+ }
+ return $::tkcon::OPT(buffer)
+ }
+ bg* {
+ ## 'bgerror' Brings up an error dialog
+ set errorInfo [lindex $args 1]
+ bgerror [lindex $args 0]
+ }
+ cl* {
+ ## 'close' Closes the console
+ ::tkcon::Destroy
+ }
+ cons* {
+ ## 'console' - passes the args to the text widget of the console.
+ set result [uplevel 1 $::tkcon::PRIV(console) $args]
+ ::tkcon::ConstrainBuffer $::tkcon::PRIV(console) \
+ $::tkcon::OPT(buffer)
+ return $result
+ }
+ congets {
+ ## 'congets' a replacement for [gets stdin]
+ # Use the 'gets' alias of 'tkcon_gets' command instead of
+ # calling the *get* methods directly for best compatability
+ if {[llength $args] > 1} {
+ return -code error "wrong # args: must be \"tkcon congets [pfix]\""
+ }
+ tkcon show
+ set old [bind TkConsole <<TkCon_Eval>>]
+ bind TkConsole <<TkCon_Eval>> { set ::tkcon::PRIV(wait) 0 }
+ set w $::tkcon::PRIV(console)
+ # Make sure to move the limit to get the right data
+ $w mark set insert end
+ if {[llength $args]} {
+ $w mark set limit insert
+ $w insert end $args
+ } else {
+ $w mark set limit insert
+ }
+ $w see end
+ vwait ::tkcon::PRIV(wait)
+ set line [::tkcon::CmdGet $w]
+ $w insert end \n
+ bind TkConsole <<TkCon_Eval>> $old
+ return $line
+ }
+ getc* {
+ ## 'getcommand' a replacement for [gets stdin]
+ ## This forces a complete command to be input though
+ if {[llength $args]} {
+ return -code error "wrong # args: must be \"tkcon getcommand\""
+ }
+ tkcon show
+ set old [bind TkConsole <<TkCon_Eval>>]
+ bind TkConsole <<TkCon_Eval>> { set ::tkcon::PRIV(wait) 0 }
+ set w $::tkcon::PRIV(console)
+ # Make sure to move the limit to get the right data
+ $w mark set insert end
+ $w mark set limit insert
+ $w see end
+ vwait ::tkcon::PRIV(wait)
+ set line [::tkcon::CmdGet $w]
+ $w insert end \n
+ while {![info complete $line] || [regexp {[^\\]\\$} $line]} {
+ vwait ::tkcon::PRIV(wait)
+ set line [::tkcon::CmdGet $w]
+ $w insert end \n
+ $w see end
+ }
+ bind TkConsole <<TkCon_Eval>> $old
+ return $line
+ }
+ get - gets {
+ ## 'gets' - a replacement for [gets stdin]
+ ## This pops up a text widget to be used for stdin (local grabbed)
+ if {[llength $args]} {
+ return -code error "wrong # args: should be \"tkcon gets\""
+ }
+ set t $::tkcon::PRIV(base).gets
+ if {![winfo exists $t]} {
+ toplevel $t
+ wm withdraw $t
+ wm title $t "tkcon gets stdin request"
+ label $t.gets -text "\"gets stdin\" request:"
+ text $t.data -width 32 -height 5 -wrap none \
+ -xscrollcommand [list $t.sx set] \
+ -yscrollcommand [list $t.sy set]
+ scrollbar $t.sx -orient h -takefocus 0 -highlightthick 0 \
+ -command [list $t.data xview]
+ scrollbar $t.sy -orient v -takefocus 0 -highlightthick 0 \
+ -command [list $t.data yview]
+ button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1}
+ bind $t.ok <Return> { %W invoke }
+ grid $t.gets - -sticky ew
+ grid $t.data $t.sy -sticky news
+ grid $t.sx -sticky ew
+ grid $t.ok - -sticky ew
+ grid columnconfig $t 0 -weight 1
+ grid rowconfig $t 1 -weight 1
+ wm transient $t $::tkcon::PRIV(root)
+ wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \
+ reqwidth $t]) / 2}]+[expr {([winfo \
+ screenheight $t]-[winfo reqheight $t]) / 2}]
+ }
+ $t.data delete 1.0 end
+ wm deiconify $t
+ raise $t
+ grab $t
+ focus $t.data
+ vwait ::tkcon::PRIV(grab)
+ grab release $t
+ wm withdraw $t
+ return [$t.data get 1.0 end-1c]
+ }
+ err* {
+ ## Outputs stack caused by last error.
+ ## error handling with pizazz (but with pizza would be nice too)
+ if {[llength $args]==2} {
+ set app [lindex $args 0]
+ set type [lindex $args 1]
+ if {[catch {::tkcon::EvalOther $app $type set errorInfo} info]} {
+ set info "error getting info from $type $app:\n$info"
+ }
+ } else {
+ set info $::tkcon::PRIV(errorInfo)
+ }
+ if {[string match {} $info]} { set info "errorInfo empty" }
+ ## If args is empty, the -attach switch just ignores it
+ edit -attach $args -type error -- $info
+ }
+ fi* {
+ ## 'find' string
+ ::tkcon::Find $::tkcon::PRIV(console) $args
+ }
+ fo* {
+ ## 'font' ?fontname? - gets/sets the font of the console
+ if {[llength $args]} {
+ if {[info exists ::tkcon::PRIV(console)] && \
+ [winfo exists $::tkcon::PRIV(console)]} {
+ $::tkcon::PRIV(console) config -font $args
+ set ::tkcon::OPT(font) [$::tkcon::PRIV(console) cget -font]
+ } else {
+ set ::tkcon::OPT(font) $args
+ }
+ }
+ return $::tkcon::OPT(font)
+ }
+ hid* - with* {
+ ## 'hide' 'withdraw' - hides the console.
+ wm withdraw $::tkcon::PRIV(root)
+ }
+ his* {
+ ## 'history'
+ set sub {\2}
+ if {[string match -new* $args]} { append sub "\n"}
+ set h [::tkcon::EvalSlave history]
+ regsub -all "( *\[0-9\]+ |\t)(\[^\n\]*\n?)" $h $sub h
+ return $h
+ }
+ ico* {
+ ## 'iconify' - iconifies the console with 'iconify'.
+ wm iconify $::tkcon::PRIV(root)
+ }
+ mas* - eval {
+ ## 'master' - evals contents in master interpreter
+ uplevel \#0 $args
+ }
+ set {
+ ## 'set' - set (or get, or unset) simple vars (not whole arrays)
+ ## from the master console interpreter
+ ## possible formats:
+ ## tkcon set <var>
+ ## tkcon set <var> <value>
+ ## tkcon set <var> <interp> <var1> <var2> w
+ ## tkcon set <var> <interp> <var1> <var2> u
+ ## tkcon set <var> <interp> <var1> <var2> r
+ if {[llength $args]==5} {
+ ## This is for use w/ 'tkcon upvar' and only works with slaves
+ foreach {var i var1 var2 op} $args break
+ if {[string compare {} $var2]} { append var1 "($var2)" }
+ switch $op {
+ u { uplevel \#0 [list unset $var] }
+ w {
+ return [uplevel \#0 [list set $var \
+ [interp eval $i [list set $var1]]]]
+ }
+ r {
+ return [interp eval $i [list set $var1 \
+ [uplevel \#0 [list set $var]]]]
+ }
+ }
+ } elseif {[llength $args] == 1} {
+ upvar \#0 [lindex $args 0] var
+ if {[array exists var]} {
+ return [array get var]
+ } else {
+ return $var
+ }
+ }
+ return [uplevel \#0 set $args]
+ }
+ append {
+ ## Modify a var in the master environment using append
+ return [uplevel \#0 append $args]
+ }
+ lappend {
+ ## Modify a var in the master environment using lappend
+ return [uplevel \#0 lappend $args]
+ }
+ sh* - dei* {
+ ## 'show|deiconify' - deiconifies the console.
+ wm deiconify $::tkcon::PRIV(root)
+ raise $::tkcon::PRIV(root)
+ focus -force $::tkcon::PRIV(console)
+ }
+ ti* {
+ ## 'title' ?title? - gets/sets the console's title
+ if {[llength $args]} {
+ return [wm title $::tkcon::PRIV(root) [join $args]]
+ } else {
+ return [wm title $::tkcon::PRIV(root)]
+ }
+ }
+ upv* {
+ ## 'upvar' masterVar slaveVar
+ ## link slave variable slaveVar to the master variable masterVar
+ ## only works masters<->slave
+ set masterVar [lindex $args 0]
+ set slaveVar [lindex $args 1]
+ if {[info exists $masterVar]} {
+ interp eval $::tkcon::OPT(exec) \
+ [list set $slaveVar [set $masterVar]]
+ } else {
+ catch {interp eval $::tkcon::OPT(exec) [list unset $slaveVar]}
+ }
+ interp eval $::tkcon::OPT(exec) \
+ [list trace variable $slaveVar rwu \
+ [list tkcon set $masterVar $::tkcon::OPT(exec)]]
+ return
+ }
+ v* {
+ return $::tkcon::PRIV(version)
+ }
+ default {
+ ## tries to determine if the command exists, otherwise throws error
+ set new ::tkcon::[string toupper \
+ [string index $cmd 0]][string range $cmd 1 end]
+ if {[llength [info command $new]]} {
+ uplevel \#0 $new $args
+ } else {
+ return -code error "bad option \"$cmd\": must be\
+ [join [lsort [list attach close console destroy \
+ font hide iconify load main master new save show \
+ slave deiconify version title bgerror]] {, }]"
+ }
+ }
+ }
+}
+
+##
+## Some procedures to make up for lack of built-in shell commands
+##
+
+## tkcon_puts -
+## This allows me to capture all stdout/stderr to the console window
+## This will be renamed to 'puts' at the appropriate time during init
+##
+# ARGS: same as usual
+# Outputs: the string with a color-coded text tag
+##
+proc tkcon_puts args {
+ set len [llength $args]
+ foreach {arg1 arg2 arg3} $args { break }
+
+ if {$len == 1} {
+ set sarg $arg1
+ set nl 1
+ set farg stdout
+ } elseif {$len == 2} {
+ if {![string compare $arg1 -nonewline]} {
+ set sarg $arg2
+ set farg stdout
+ set nl 0
+ } elseif {![string compare $arg1 stdout] \
+ || ![string compare $arg1 stderr]} {
+ set sarg $arg2
+ set farg $arg1
+ set nl 1
+ } else {
+ set len 0
+ }
+ } elseif {$len == 3} {
+ if {![string compare $arg1 -nonewline] \
+ && (![string compare $arg2 stdout] \
+ || ![string compare $arg2 stderr])} {
+ set sarg $arg3
+ set farg $arg2
+ set nl 0
+ } elseif {(![string compare $arg1 stdout] \
+ || ![string compare $arg1 stderr]) \
+ && ![string compare $arg3 nonewline]} {
+ set sarg $arg2
+ set farg $arg1
+ set nl 0
+ } else {
+ set len 0
+ }
+ } else {
+ set len 0
+ }
+
+ ## $len == 0 means it wasn't handled by tkcon above.
+ ##
+
+ if {$len != 0} {
+
+ ## "poor man's" \r substitution---erase everything on the output
+ ## line and print from character after the \r
+
+ set rpt [string last \r $sarg]
+ if {$rpt >= 0} {
+ tkcon console delete "insert linestart" "insert lineend"
+ set sarg [string range $sarg [expr {$rpt + 1}] end]
+ }
+
+ set bpt [string first \b $sarg]
+ if {$bpt >= 0} {
+ set narg [string range $sarg [expr {$bpt + 1}] end]
+ set sarg [string range $sarg 0 [expr {$bpt - 1}]]
+ set nl 0
+ }
+
+
+ if {$nl == 0} {
+ tkcon console insert output $sarg $farg
+ } else {
+ tkcon console insert output "$sarg\n" $farg
+ }
+
+ if {$bpt >= 0} {
+ tkcon console delete "insert -1 char" insert
+ if {$nl == 0} {
+ tkcon_puts $farg $narg nonewline
+ } else {
+ tkcon_puts $farg $narg
+ }
+ }
+
+ } else {
+ global errorCode errorInfo
+ if {[catch "tkcon_tcl_puts $args" msg]} {
+ regsub tkcon_tcl_puts $msg puts msg
+ regsub -all tkcon_tcl_puts $errorInfo puts errorInfo
+ return -code error $msg
+ }
+ return $msg
+ }
+
+ ## WARNING: This update should behave well because it uses idletasks,
+ ## however, if there are weird looping problems with events, or
+ ## hanging in waits, try commenting this out.
+ if {$len} {
+ tkcon console see output
+ update idletasks
+ }
+}
+
+## tkcon_gets -
+## This allows me to capture all stdin input without needing to stdin
+## This will be renamed to 'gets' at the appropriate time during init
+##
+# ARGS: same as gets
+# Outputs: same as gets
+##
+proc tkcon_gets args {
+ set len [llength $args]
+ if {$len != 1 && $len != 2} {
+ return -code error \
+ "wrong # args: should be \"gets channelId ?varName?\""
+ }
+ if {[string compare stdin [lindex $args 0]]} {
+ return [uplevel 1 tkcon_tcl_gets $args]
+ }
+ set gtype [tkcon set ::tkcon::OPT(gets)]
+ if {$gtype == ""} { set gtype congets }
+ set data [tkcon $gtype]
+ if {$len == 2} {
+ upvar 1 [lindex $args 1] var
+ set var $data
+ return [string length $data]
+ }
+ return $data
+}
+
+## edit - opens a file/proc/var for reading/editing
+##
+# Arguments:
+# type proc/file/var
+# what the actual name of the item
+# Returns: nothing
+##
+proc edit {args} {
+ array set opts {-find {} -type {} -attach {}}
+ while {[string match -* [lindex $args 0]]} {
+ switch -glob -- [lindex $args 0] {
+ -f* { set opts(-find) [lindex $args 1] }
+ -a* { set opts(-attach) [lindex $args 1] }
+ -t* { set opts(-type) [lindex $args 1] }
+ -- { set args [lreplace $args 0 0]; break }
+ default {return -code error "unknown option \"[lindex $args 0]\""}
+ }
+ set args [lreplace $args 0 1]
+ }
+ # determine who we are dealing with
+ if {[llength $opts(-attach)]} {
+ foreach {app type} $opts(-attach) {break}
+ } else {
+ foreach {app type} [tkcon attach] {break}
+ }
+
+ set word [lindex $args 0]
+ if {[string match {} $opts(-type)]} {
+ if {[llength [::tkcon::EvalOther $app $type info commands [list $word]]]} {
+ set opts(-type) "proc"
+ } elseif {[llength [::tkcon::EvalOther $app $type info vars [list $word]]]} {
+ set opts(-type) "var"
+ } elseif {[::tkcon::EvalOther $app $type file isfile [list $word]]} {
+ set opts(-type) "file"
+ }
+ }
+ if {[string compare $opts(-type) {}]} {
+ # Create unique edit window toplevel
+ set w $::tkcon::PRIV(base).__edit
+ set i 0
+ while {[winfo exists $w[incr i]]} {}
+ append w $i
+ toplevel $w
+ wm withdraw $w
+ if {[string length $word] > 12} {
+ wm title $w "tkcon Edit: [string range $word 0 9]..."
+ } else {
+ wm title $w "tkcon Edit: $word"
+ }
+
+ text $w.text -wrap none \
+ -xscrollcommand [list $w.sx set] \
+ -yscrollcommand [list $w.sy set] \
+ -foreground $::tkcon::COLOR(stdin) \
+ -background $::tkcon::COLOR(bg) \
+ -insertbackground $::tkcon::COLOR(cursor) \
+ -font $::tkcon::OPT(font)
+ scrollbar $w.sx -orient h -takefocus 0 -bd 1 \
+ -command [list $w.text xview]
+ scrollbar $w.sy -orient v -takefocus 0 -bd 1 \
+ -command [list $w.text yview]
+
+ set menu [menu $w.mbar]
+ $w configure -menu $menu
+
+ ## File Menu
+ ##
+ set m [menu [::tkcon::MenuButton $menu File file]]
+ $m add command -label "Save As..." -underline 0 \
+ -command [list ::tkcon::Save {} widget $w.text]
+ $m add command -label "Append To..." -underline 0 \
+ -command [list ::tkcon::Save {} widget $w.text a+]
+ $m add separator
+ $m add command -label "Dismiss" -underline 0 -accel "Ctrl-w" \
+ -command [list destroy $w]
+ bind $w <Control-w> [list destroy $w]
+ bind $w <$::tkcon::PRIV(meta)-w> [list destroy $w]
+
+ ## Edit Menu
+ ##
+ set text $w.text
+ set m [menu [::tkcon::MenuButton $menu Edit edit]]
+ $m add command -label "Cut" -under 2 \
+ -command [list tk_textCut $text]
+ $m add command -label "Copy" -under 0 \
+ -command [list tk_textCopy $text]
+ $m add command -label "Paste" -under 0 \
+ -command [list tk_textPaste $text]
+ $m add separator
+ $m add command -label "Find" -under 0 \
+ -command [list ::tkcon::FindBox $text]
+
+ ## Send To Menu
+ ##
+ set m [menu [::tkcon::MenuButton $menu "Send To..." send]]
+ $m add command -label "Send To $app" -underline 0 \
+ -command "::tkcon::EvalOther [list $app] $type \
+ eval \[$w.text get 1.0 end-1c\]"
+ set other [tkcon attach]
+ if {[string compare $other [list $app $type]]} {
+ $m add command -label "Send To [lindex $other 0]" \
+ -command "::tkcon::EvalOther $other \
+ eval \[$w.text get 1.0 end-1c\]"
+ }
+
+ grid $w.text - $w.sy -sticky news
+ grid $w.sx - -sticky ew
+ grid columnconfigure $w 0 -weight 1
+ grid columnconfigure $w 1 -weight 1
+ grid rowconfigure $w 0 -weight 1
+ } else {
+ return -code error "unrecognized type '$word'"
+ }
+ switch -glob -- $opts(-type) {
+ proc* {
+ $w.text insert 1.0 \
+ [::tkcon::EvalOther $app $type dump proc [list $word]]
+ }
+ var* {
+ $w.text insert 1.0 \
+ [::tkcon::EvalOther $app $type dump var [list $word]]
+ }
+ file {
+ $w.text insert 1.0 [::tkcon::EvalOther $app $type eval \
+ [subst -nocommands {
+ set __tkcon(fid) [open $word r]
+ set __tkcon(data) [read \$__tkcon(fid)]
+ close \$__tkcon(fid)
+ after 1000 unset __tkcon
+ return \$__tkcon(data)
+ }
+ ]]
+ }
+ error* {
+ $w.text insert 1.0 [join $args \n]
+ ::tkcon::ErrorHighlight $w.text
+ }
+ default {
+ $w.text insert 1.0 [join $args \n]
+ }
+ }
+ wm deiconify $w
+ focus $w.text
+ if {[string compare $opts(-find) {}]} {
+ ::tkcon::Find $w.text $opts(-find) -case 1
+ }
+}
+interp alias {} ::more {} ::edit
+interp alias {} ::less {} ::edit
+
+## echo
+## Relaxes the one string restriction of 'puts'
+# ARGS: any number of strings to output to stdout
+##
+proc echo args { puts [concat $args] }
+
+## clear - clears the buffer of the console (not the history though)
+## This is executed in the parent interpreter
+##
+proc clear {{pcnt 100}} {
+ if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} {
+ return -code error \
+ "invalid percentage to clear: must be 1-100 (100 default)"
+ } elseif {$pcnt == 100} {
+ tkcon console delete 1.0 end
+ } else {
+ set tmp [expr {$pcnt/100.0*[tkcon console index end]}]
+ tkcon console delete 1.0 "$tmp linestart"
+ }
+}
+
+## alias - akin to the csh alias command
+## If called with no args, then it dumps out all current aliases
+## If called with one arg, returns the alias of that arg (or {} if none)
+# ARGS: newcmd - (optional) command to bind alias to
+# args - command and args being aliased
+##
+proc alias {{newcmd {}} args} {
+ if {[string match {} $newcmd]} {
+ set res {}
+ foreach a [interp aliases] {
+ lappend res [list $a -> [interp alias {} $a]]
+ }
+ return [join $res \n]
+ } elseif {![llength $args]} {
+ interp alias {} $newcmd
+ } else {
+ eval interp alias [list {} $newcmd {}] $args
+ }
+}
+
+## unalias - unaliases an alias'ed command
+# ARGS: cmd - command to unbind as an alias
+##
+proc unalias {cmd} {
+ interp alias {} $cmd {}
+}
+
+## dump - outputs variables/procedure/widget info in source'able form.
+## Accepts glob style pattern matching for the names
+#
+# ARGS: type - type of thing to dump: must be variable, procedure, widget
+#
+# OPTS: -nocomplain
+# don't complain if no items of the specified type are found
+# -filter pattern
+# specifies a glob filter pattern to be used by the variable
+# method as an array filter pattern (it filters down for
+# nested elements) and in the widget method as a config
+# option filter pattern
+# -- forcibly ends options recognition
+#
+# Returns: the values of the requested items in a 'source'able form
+##
+proc dump {type args} {
+ set whine 1
+ set code ok
+ if {![llength $args]} {
+ ## If no args, assume they gave us something to dump and
+ ## we'll try anything
+ set args $type
+ set type any
+ }
+ while {[string match -* [lindex $args 0]]} {
+ switch -glob -- [lindex $args 0] {
+ -n* { set whine 0; set args [lreplace $args 0 0] }
+ -f* { set fltr [lindex $args 1]; set args [lreplace $args 0 1] }
+ -- { set args [lreplace $args 0 0]; break }
+ default {return -code error "unknown option \"[lindex $args 0]\""}
+ }
+ }
+ if {$whine && ![llength $args]} {
+ return -code error "wrong \# args: [lindex [info level 0] 0] type\
+ ?-nocomplain? ?-filter pattern? ?--? pattern ?pattern ...?"
+ }
+ set res {}
+ switch -glob -- $type {
+ c* {
+ # command
+ # outputs commands by figuring out, as well as possible, what it is
+ # this does not attempt to auto-load anything
+ foreach arg $args {
+ if {[llength [set cmds [info commands $arg]]]} {
+ foreach cmd [lsort $cmds] {
+ if {[lsearch -exact [interp aliases] $cmd] > -1} {
+ append res "\#\# ALIAS: $cmd =>\
+ [interp alias {} $cmd]\n"
+ } elseif {
+ [llength [info procs $cmd]] ||
+ ([string match *::* $cmd] &&
+ [llength [namespace eval [namespace qual $cmd] \
+ info procs [namespace tail $cmd]]])
+ } {
+ if {[catch {dump p -- $cmd} msg] && $whine} {
+ set code error
+ }
+ append res $msg\n
+ } else {
+ append res "\#\# COMMAND: $cmd\n"
+ }
+ }
+ } elseif {$whine} {
+ append res "\#\# No known command $arg\n"
+ set code error
+ }
+ }
+ }
+ v* {
+ # variable
+ # outputs variables value(s), whether array or simple.
+ if {![info exists fltr]} { set fltr * }
+ foreach arg $args {
+ if {![llength [set vars [uplevel 1 info vars [list $arg]]]]} {
+ if {[uplevel 1 info exists $arg]} {
+ set vars $arg
+ } elseif {$whine} {
+ append res "\#\# No known variable $arg\n"
+ set code error
+ continue
+ } else { continue }
+ }
+ foreach var [lsort $vars] {
+ if {[uplevel 1 [list info locals $var]] == ""} {
+ # use the proper scope of the var, but
+ # namespace which won't id locals correctly
+ set var [uplevel 1 \
+ [list namespace which -variable $var]]
+ }
+ upvar 1 $var v
+ if {[array exists v] || [catch {string length $v}]} {
+ set nst {}
+ append res "array set [list $var] \{\n"
+ if {[array size v]} {
+ foreach i [lsort [array names v $fltr]] {
+ upvar 0 v\($i\) __a
+ if {[array exists __a]} {
+ append nst "\#\# NESTED ARRAY ELEM: $i\n"
+ append nst "upvar 0 [list $var\($i\)] __a;\
+ [dump v -filter $fltr __a]\n"
+ } else {
+ append res " [list $i]\t[list $v($i)]\n"
+ }
+ }
+ } else {
+ ## empty array
+ append res " empty array\n"
+ append nst "unset [list $var](empty)\n"
+ }
+ append res "\}\n$nst"
+ } else {
+ append res [list set $var $v]\n
+ }
+ }
+ }
+ }
+ p* {
+ # procedure
+ foreach arg $args {
+ if {
+ ![llength [set procs [info proc $arg]]] &&
+ ([string match *::* $arg] &&
+ [llength [set ps [namespace eval \
+ [namespace qualifier $arg] \
+ info procs [namespace tail $arg]]]])
+ } {
+ set procs {}
+ set namesp [namespace qualifier $arg]
+ foreach p $ps {
+ lappend procs ${namesp}::$p
+ }
+ }
+ if {[llength $procs]} {
+ foreach p [lsort $procs] {
+ set as {}
+ foreach a [info args $p] {
+ if {[info default $p $a tmp]} {
+ lappend as [list $a $tmp]
+ } else {
+ lappend as $a
+ }
+ }
+ append res [list proc $p $as [info body $p]]\n
+ }
+ } elseif {$whine} {
+ append res "\#\# No known proc $arg\n"
+ set code error
+ }
+ }
+ }
+ w* {
+ # widget
+ ## The user should have Tk loaded
+ if {![llength [info command winfo]]} {
+ return -code error "winfo not present, cannot dump widgets"
+ }
+ if {![info exists fltr]} { set fltr .* }
+ foreach arg $args {
+ if {[llength [set ws [info command $arg]]]} {
+ foreach w [lsort $ws] {
+ if {[winfo exists $w]} {
+ if {[catch {$w configure} cfg]} {
+ append res "\#\# Widget $w\
+ does not support configure method"
+ set code error
+ } else {
+ append res "\#\# [winfo class $w]\
+ $w\n$w configure"
+ foreach c $cfg {
+ if {[llength $c] != 5} continue
+ ## Check to see that the option does
+ ## not match the default, then check
+ ## the item against the user filter
+ if {[string compare [lindex $c 3] \
+ [lindex $c 4]] && \
+ [regexp -nocase -- $fltr $c]} {
+ append res " \\\n\t[list [lindex $c 0]\
+ [lindex $c 4]]"
+ }
+ }
+ append res \n
+ }
+ }
+ }
+ } elseif {$whine} {
+ append res "\#\# No known widget $arg\n"
+ set code error
+ }
+ }
+ }
+ a* {
+ ## see if we recognize it, other complain
+ if {[regexp {(var|com|proc|widget)} \
+ [set types [uplevel 1 what $args]]]} {
+ foreach type $types {
+ if {[regexp {(var|com|proc|widget)} $type]} {
+ append res "[uplevel 1 dump $type $args]\n"
+ }
+ }
+ } else {
+ set res "dump was unable to resolve type for \"$args\""
+ set code error
+ }
+ }
+ default {
+ return -code error "bad [lindex [info level 0] 0] option\
+ \"$type\": must be variable, command, procedure,\
+ or widget"
+ }
+ }
+ return -code $code [string trimright $res \n]
+}
+
+## idebug - interactive debugger
+#
+# idebug body ?level?
+#
+# Prints out the body of the command (if it is a procedure) at the
+# specified level. <i>level</i> defaults to the current level.
+#
+# idebug break
+#
+# Creates a breakpoint within a procedure. This will only trigger
+# if idebug is on and the id matches the pattern. If so, TkCon will
+# pop to the front with the prompt changed to an idebug prompt. You
+# are given the basic ability to observe the call stack an query/set
+# variables or execute Tcl commands at any level. A separate history
+# is maintained in debugging mode.
+#
+# idebug echo|{echo ?id?} ?args?
+#
+# Behaves just like "echo", but only triggers when idebug is on.
+# You can specify an optional id to further restrict triggering.
+# If no id is specified, it defaults to the name of the command
+# in which the call was made.
+#
+# idebug id ?id?
+#
+# Query or set the idebug id. This id is used by other idebug
+# methods to determine if they should trigger or not. The idebug
+# id can be a glob pattern and defaults to *.
+#
+# idebug off
+#
+# Turns idebug off.
+#
+# idebug on ?id?
+#
+# Turns idebug on. If 'id' is specified, it sets the id to it.
+#
+# idebug puts|{puts ?id?} args
+#
+# Behaves just like "puts", but only triggers when idebug is on.
+# You can specify an optional id to further restrict triggering.
+# If no id is specified, it defaults to the name of the command
+# in which the call was made.
+#
+# idebug show type ?level? ?VERBOSE?
+#
+# 'type' must be one of vars, locals or globals. This method
+# will output the variables/locals/globals present in a particular
+# level. If VERBOSE is added, then it actually 'dump's out the
+# values as well. 'level' defaults to the level in which this
+# method was called.
+#
+# idebug trace ?level?
+#
+# Prints out the stack trace from the specified level up to the top
+# level. 'level' defaults to the current level.
+#
+##
+proc idebug {opt args} {
+ global IDEBUG
+
+ if {![info exists IDEBUG(on)]} {
+ array set IDEBUG { on 0 id * debugging 0 }
+ }
+ set level [expr {[info level]-1}]
+ switch -glob -- $opt {
+ on {
+ if {[llength $args]} { set IDEBUG(id) $args }
+ return [set IDEBUG(on) 1]
+ }
+ off { return [set IDEBUG(on) 0] }
+ id {
+ if {![llength $args]} {
+ return $IDEBUG(id)
+ } else { return [set IDEBUG(id) $args] }
+ }
+ break {
+ if {!$IDEBUG(on) || $IDEBUG(debugging) || \
+ ([llength $args] && \
+ ![string match $IDEBUG(id) $args]) || [info level]<1} {
+ return
+ }
+ set IDEBUG(debugging) 1
+ puts stderr "idebug at level \#$level: [lindex [info level -1] 0]"
+ set tkcon [llength [info command tkcon]]
+ if {$tkcon} {
+ tkcon master eval set ::tkcon::OPT(prompt2) \$::tkcon::OPT(prompt1)
+ tkcon master eval set ::tkcon::OPT(prompt1) \$::tkcon::OPT(debugPrompt)
+ set slave [tkcon set ::tkcon::OPT(exec)]
+ set event [tkcon set ::tkcon::PRIV(event)]
+ tkcon set ::tkcon::OPT(exec) [tkcon master interp create debugger]
+ tkcon set ::tkcon::PRIV(event) 1
+ }
+ set max $level
+ while 1 {
+ set err {}
+ if {$tkcon} {
+ # tkcon's overload of gets is advanced enough to not need
+ # this, but we get a little better control this way.
+ tkcon evalSlave set level $level
+ tkcon prompt
+ set line [tkcon getcommand]
+ tkcon console mark set output end
+ } else {
+ puts -nonewline stderr "(level \#$level) debug > "
+ gets stdin line
+ while {![info complete $line]} {
+ puts -nonewline "> "
+ append line "\n[gets stdin]"
+ }
+ }
+ if {[string match {} $line]} continue
+ set key [lindex $line 0]
+ if {![regexp {^([#-]?[0-9]+)} [lreplace $line 0 0] lvl]} {
+ set lvl \#$level
+ }
+ set res {}; set c 0
+ switch -- $key {
+ + {
+ ## Allow for jumping multiple levels
+ if {$level < $max} {
+ idebug trace [incr level] $level 0 VERBOSE
+ }
+ }
+ - {
+ ## Allow for jumping multiple levels
+ if {$level > 1} {
+ idebug trace [incr level -1] $level 0 VERBOSE
+ }
+ }
+ . { set c [catch {idebug trace $level $level 0 VERBOSE} res] }
+ v { set c [catch {idebug show vars $lvl } res] }
+ V { set c [catch {idebug show vars $lvl VERBOSE} res] }
+ l { set c [catch {idebug show locals $lvl } res] }
+ L { set c [catch {idebug show locals $lvl VERBOSE} res] }
+ g { set c [catch {idebug show globals $lvl } res] }
+ G { set c [catch {idebug show globals $lvl VERBOSE} res] }
+ t { set c [catch {idebug trace 1 $max $level } res] }
+ T { set c [catch {idebug trace 1 $max $level VERBOSE} res]}
+ b { set c [catch {idebug body $lvl} res] }
+ o { set res [set IDEBUG(on) [expr {!$IDEBUG(on)}]] }
+ h - ? {
+ puts stderr " + Move down in call stack
+ - Move up in call stack
+ . Show current proc name and params
+
+ v Show names of variables currently in scope
+ V Show names of variables currently in scope with values
+ l Show names of local (transient) variables
+ L Show names of local (transient) variables with values
+ g Show names of declared global variables
+ G Show names of declared global variables with values
+ t Show a stack trace
+ T Show a verbose stack trace
+
+ b Show body of current proc
+ o Toggle on/off any further debugging
+ c,q Continue regular execution (Quit debugger)
+ h,? Print this help
+ default Evaluate line at current level (\#$level)"
+ }
+ c - q break
+ default { set c [catch {uplevel \#$level $line} res] }
+ }
+ if {$tkcon} {
+ tkcon set ::tkcon::PRIV(event) \
+ [tkcon evalSlave eval history add [list $line]\
+ \; history nextid]
+ }
+ if {$c} {
+ puts stderr $res
+ } elseif {[string compare {} $res]} {
+ puts $res
+ }
+ }
+ set IDEBUG(debugging) 0
+ if {$tkcon} {
+ tkcon master interp delete debugger
+ tkcon master eval set ::tkcon::OPT(prompt1) \$::tkcon::OPT(prompt2)
+ tkcon set ::tkcon::OPT(exec) $slave
+ tkcon set ::tkcon::PRIV(event) $event
+ tkcon prompt
+ }
+ }
+ bo* {
+ if {[regexp {^([#-]?[0-9]+)} $args level]} {
+ return [uplevel $level {dump c -no [lindex [info level 0] 0]}]
+ }
+ }
+ t* {
+ if {[llength $args]<2} return
+ set min [set max [set lvl $level]]
+ set exp {^#?([0-9]+)? ?#?([0-9]+) ?#?([0-9]+)? ?(VERBOSE)?}
+ if {![regexp $exp $args junk min max lvl verbose]} return
+ for {set i $max} {
+ $i>=$min && ![catch {uplevel \#$i info level 0} info]
+ } {incr i -1} {
+ if {$i==$lvl} {
+ puts -nonewline stderr "* \#$i:\t"
+ } else {
+ puts -nonewline stderr " \#$i:\t"
+ }
+ set name [lindex $info 0]
+ if {[string compare VERBOSE $verbose] || \
+ ![llength [info procs $name]]} {
+ puts $info
+ } else {
+ puts "proc $name {[info args $name]} { ... }"
+ set idx 0
+ foreach arg [info args $name] {
+ if {[string match args $arg]} {
+ puts "\t$arg = [lrange $info [incr idx] end]"
+ break
+ } else {
+ puts "\t$arg = [lindex $info [incr idx]]"
+ }
+ }
+ }
+ }
+ }
+ s* {
+ #var, local, global
+ set level \#$level
+ if {![regexp {^([vgl][^ ]*) ?([#-]?[0-9]+)? ?(VERBOSE)?} \
+ $args junk type level verbose]} return
+ switch -glob -- $type {
+ v* { set vars [uplevel $level {lsort [info vars]}] }
+ l* { set vars [uplevel $level {lsort [info locals]}] }
+ g* { set vars [lremove [uplevel $level {info vars}] \
+ [uplevel $level {info locals}]] }
+ }
+ if {[string match VERBOSE $verbose]} {
+ return [uplevel $level dump var -nocomplain $vars]
+ } else {
+ return $vars
+ }
+ }
+ e* - pu* {
+ if {[llength $opt]==1 && [catch {lindex [info level -1] 0} id]} {
+ set id [lindex [info level 0] 0]
+ } else {
+ set id [lindex $opt 1]
+ }
+ if {$IDEBUG(on) && [string match $IDEBUG(id) $id]} {
+ if {[string match e* $opt]} {
+ puts [concat $args]
+ } else { eval puts $args }
+ }
+ }
+ default {
+ return -code error "bad [lindex [info level 0] 0] option \"$opt\",\
+ must be: [join [lsort [list on off id break print body\
+ trace show puts echo]] {, }]"
+ }
+ }
+}
+
+## observe - like trace, but not
+# ARGS: opt - option
+# name - name of variable or command
+##
+proc observe {opt name args} {
+ global tcl_observe
+ switch -glob -- $opt {
+ co* {
+ if {[regexp {^(catch|lreplace|set|puts|for|incr|info|uplevel)$} \
+ $name]} {
+ return -code error "cannot observe \"$name\":\
+ infinite eval loop will occur"
+ }
+ set old ${name}@
+ while {[llength [info command $old]]} { append old @ }
+ rename $name $old
+ set max 4
+ regexp {^[0-9]+} $args max
+ ## idebug trace could be used here
+ proc $name args "
+ for {set i \[info level\]; set max \[expr \[info level\]-$max\]} {
+ \$i>=\$max && !\[catch {uplevel \#\$i info level 0} info\]
+ } {incr i -1} {
+ puts -nonewline stderr \" \#\$i:\t\"
+ puts \$info
+ }
+ uplevel \[lreplace \[info level 0\] 0 0 $old\]
+ "
+ set tcl_observe($name) $old
+ }
+ cd* {
+ if {[info exists tcl_observe($name)] && [catch {
+ rename $name {}
+ rename $tcl_observe($name) $name
+ unset tcl_observe($name)
+ } err]} { return -code error $err }
+ }
+ ci* {
+ ## What a useless method...
+ if {[info exists tcl_observe($name)]} {
+ set i $tcl_observe($name)
+ set res "\"$name\" observes true command \"$i\""
+ while {[info exists tcl_observe($i)]} {
+ append res "\n\"$name\" observes true command \"$i\""
+ set i $tcl_observe($name)
+ }
+ return $res
+ }
+ }
+ va* - vd* {
+ set type [lindex $args 0]
+ set args [lrange $args 1 end]
+ if {![regexp {^[rwu]} $type type]} {
+ return -code error "bad [lindex [info level 0] 0] $opt type\
+ \"$type\", must be: read, write or unset"
+ }
+ if {![llength $args]} { set args observe_var }
+ uplevel 1 [list trace $opt $name $type $args]
+ }
+ vi* {
+ uplevel 1 [list trace vinfo $name]
+ }
+ default {
+ return -code error "bad [lindex [info level 0] 0] option\
+ \"[lindex $args 0]\", must be: [join [lsort \
+ [list command cdelete cinfo variable vdelete vinfo]] {, }]"
+ }
+ }
+}
+
+## observe_var - auxilary function for observing vars, called by trace
+## via observe
+# ARGS: name - variable name
+# el - array element name, if any
+# op - operation type (rwu)
+##
+proc observe_var {name el op} {
+ if {[string match u $op]} {
+ if {[string compare {} $el]} {
+ puts "unset \"${name}($el)\""
+ } else {
+ puts "unset \"$name\""
+ }
+ } else {
+ upvar 1 $name $name
+ if {[info exists ${name}($el)]} {
+ puts [dump v ${name}($el)]
+ } else {
+ puts [dump v $name]
+ }
+ }
+}
+
+## which - tells you where a command is found
+# ARGS: cmd - command name
+# Returns: where command is found (internal / external / unknown)
+##
+proc which cmd {
+ ## This tries to auto-load a command if not recognized
+ set types [uplevel 1 [list what $cmd 1]]
+ if {[llength $types]} {
+ set out {}
+
+ foreach type $types {
+ switch -- $type {
+ alias { set res "$cmd: aliased to [alias $cmd]" }
+ procedure { set res "$cmd: procedure" }
+ command { set res "$cmd: internal command" }
+ executable { lappend out [auto_execok $cmd] }
+ variable { lappend out "$cmd: $type" }
+ }
+ if {[info exists res]} {
+ global auto_index
+ if {[info exists auto_index($cmd)]} {
+ ## This tells you where the command MIGHT have come from -
+ ## not true if the command was redefined interactively or
+ ## existed before it had to be auto_loaded. This is just
+ ## provided as a hint at where it MAY have come from
+ append res " ($auto_index($cmd))"
+ }
+ lappend out $res
+ unset res
+ }
+ }
+ return [join $out \n]
+ } else {
+ return -code error "$cmd: command not found"
+ }
+}
+
+## what - tells you what a string is recognized as
+# ARGS: str - string to id
+# Returns: id types of command as list
+##
+proc what {str {autoload 0}} {
+ set types {}
+ if {[llength [info commands $str]] || ($autoload && \
+ [auto_load $str] && [llength [info commands $str]])} {
+ if {[lsearch -exact [interp aliases] $str] > -1} {
+ lappend types "alias"
+ } elseif {
+ [llength [info procs $str]] ||
+ ([string match *::* $str] &&
+ [llength [namespace eval [namespace qualifier $str] \
+ info procs [namespace tail $str]]])
+ } {
+ lappend types "procedure"
+ } else {
+ lappend types "command"
+ }
+ }
+ if {[llength [uplevel 1 info vars $str]]} {
+ upvar 1 $str var
+ if {[array exists var]} {
+ lappend types array variable
+ } else {
+ lappend types scalar variable
+ }
+ }
+ if {[file isdirectory $str]} {
+ lappend types "directory"
+ }
+ if {[file isfile $str]} {
+ lappend types "file"
+ }
+ if {[llength [info commands winfo]] && [winfo exists $str]} {
+ lappend types "widget"
+ }
+ if {[string compare {} [auto_execok $str]]} {
+ lappend types "executable"
+ }
+ return $types
+}
+
+## dir - directory list
+# ARGS: args - names/glob patterns of directories to list
+# OPTS: -all - list hidden files as well (Unix dot files)
+# -long - list in full format "permissions size date filename"
+# -full - displays / after directories and link paths for links
+# Returns: a directory listing
+##
+proc dir {args} {
+ array set s {
+ all 0 full 0 long 0
+ 0 --- 1 --x 2 -w- 3 -wx 4 r-- 5 r-x 6 rw- 7 rwx
+ }
+ while {[string match \-* [lindex $args 0]]} {
+ set str [lindex $args 0]
+ set args [lreplace $args 0 0]
+ switch -glob -- $str {
+ -a* {set s(all) 1} -f* {set s(full) 1}
+ -l* {set s(long) 1} -- break
+ default {
+ return -code error "unknown option \"$str\",\
+ should be one of: -all, -full, -long"
+ }
+ }
+ }
+ set sep [string trim [file join . .] .]
+ if {![llength $args]} { set args . }
+ if {$::tcl_version >= 8.3} {
+ # Newer glob args allow safer dir processing. The user may still
+ # want glob chars, but really only for file matching.
+ foreach arg $args {
+ if {[file isdirectory $arg]} {
+ if {$s(all)} {
+ lappend out [list $arg [lsort \
+ [glob -nocomplain -directory $arg .* *]]]
+ } else {
+ lappend out [list $arg [lsort \
+ [glob -nocomplain -directory $arg *]]]
+ }
+ } else {
+ set dir [file dirname $arg]
+ lappend out [list $dir$sep [lsort \
+ [glob -nocomplain -directory $dir [file tail $arg]]]]
+ }
+ }
+ } else {
+ foreach arg $args {
+ if {[file isdirectory $arg]} {
+ set arg [string trimright $arg $sep]$sep
+ if {$s(all)} {
+ lappend out [list $arg [lsort [glob -nocomplain -- $arg.* $arg*]]]
+ } else {
+ lappend out [list $arg [lsort [glob -nocomplain -- $arg*]]]
+ }
+ } else {
+ lappend out [list [file dirname $arg]$sep \
+ [lsort [glob -nocomplain -- $arg]]]
+ }
+ }
+ }
+ if {$s(long)} {
+ set old [clock scan {1 year ago}]
+ set fmt "%s%9d %s %s\n"
+ foreach o $out {
+ set d [lindex $o 0]
+ append res $d:\n
+ foreach f [lindex $o 1] {
+ file lstat $f st
+ set f [file tail $f]
+ if {$s(full)} {
+ switch -glob $st(type) {
+ d* { append f $sep }
+ l* { append f "@ -> [file readlink $d$sep$f]" }
+ default { if {[file exec $d$sep$f]} { append f * } }
+ }
+ }
+ if {[string match file $st(type)]} {
+ set mode -
+ } else {
+ set mode [string index $st(type) 0]
+ }
+ foreach j [split [format %03o [expr {$st(mode)&0777}]] {}] {
+ append mode $s($j)
+ }
+ if {$st(mtime)>$old} {
+ set cfmt {%b %d %H:%M}
+ } else {
+ set cfmt {%b %d %Y}
+ }
+ append res [format $fmt $mode $st(size) \
+ [clock format $st(mtime) -format $cfmt] $f]
+ }
+ append res \n
+ }
+ } else {
+ foreach o $out {
+ set d [lindex $o 0]
+ append res "$d:\n"
+ set i 0
+ foreach f [lindex $o 1] {
+ if {[string len [file tail $f]] > $i} {
+ set i [string len [file tail $f]]
+ }
+ }
+ set i [expr {$i+2+$s(full)}]
+ set j 80
+ ## This gets the number of cols in the tkcon console widget
+ if {[llength [info commands tkcon]]} {
+ set j [expr {[tkcon master set ::tkcon::OPT(cols)]/$i}]
+ }
+ set k 0
+ foreach f [lindex $o 1] {
+ set f [file tail $f]
+ if {$s(full)} {
+ switch -glob [file type $d$sep$f] {
+ d* { append f $sep }
+ l* { append f @ }
+ default { if {[file exec $d$sep$f]} { append f * } }
+ }
+ }
+ append res [format "%-${i}s" $f]
+ if {$j == 0 || [incr k]%$j == 0} {
+ set res [string trimright $res]\n
+ }
+ }
+ append res \n\n
+ }
+ }
+ return [string trimright $res]
+}
+interp alias {} ::ls {} ::dir -full
+
+## lremove - remove items from a list
+# OPTS:
+# -all remove all instances of each item
+# -glob remove all instances matching glob pattern
+# -regexp remove all instances matching regexp pattern
+# ARGS: l a list to remove items from
+# args items to remove (these are 'join'ed together)
+##
+proc lremove {args} {
+ array set opts {-all 0 pattern -exact}
+ while {[string match -* [lindex $args 0]]} {
+ switch -glob -- [lindex $args 0] {
+ -a* { set opts(-all) 1 }
+ -g* { set opts(pattern) -glob }
+ -r* { set opts(pattern) -regexp }
+ -- { set args [lreplace $args 0 0]; break }
+ default {return -code error "unknown option \"[lindex $args 0]\""}
+ }
+ set args [lreplace $args 0 0]
+ }
+ set l [lindex $args 0]
+ foreach i [join [lreplace $args 0 0]] {
+ if {[set ix [lsearch $opts(pattern) $l $i]] == -1} continue
+ set l [lreplace $l $ix $ix]
+ if {$opts(-all)} {
+ while {[set ix [lsearch $opts(pattern) $l $i]] != -1} {
+ set l [lreplace $l $ix $ix]
+ }
+ }
+ }
+ return $l
+}
+
+if {!$::tkcon::PRIV(WWW)} {;
+
+## Unknown changed to get output into tkcon window
+# unknown:
+# Invoked automatically whenever an unknown command is encountered.
+# Works through a list of "unknown handlers" that have been registered
+# to deal with unknown commands. Extensions can integrate their own
+# handlers into the 'unknown' facility via 'unknown_handler'.
+#
+# If a handler exists that recognizes the command, then it will
+# take care of the command action and return a valid result or a
+# Tcl error. Otherwise, it should return "-code continue" (=2)
+# and responsibility for the command is passed to the next handler.
+#
+# Arguments:
+# args - A list whose elements are the words of the original
+# command, including the command name.
+
+proc unknown args {
+ global unknown_handler_order unknown_handlers errorInfo errorCode
+
+ #
+ # Be careful to save error info now, and restore it later
+ # for each handler. Some handlers generate their own errors
+ # and disrupt handling.
+ #
+ set savedErrorCode $errorCode
+ set savedErrorInfo $errorInfo
+
+ if {![info exists unknown_handler_order] || \
+ ![info exists unknown_handlers]} {
+ set unknown_handlers(tcl) tcl_unknown
+ set unknown_handler_order tcl
+ }
+
+ foreach handler $unknown_handler_order {
+ set status [catch {uplevel 1 $unknown_handlers($handler) $args} result]
+
+ if {$status == 1} {
+ #
+ # Strip the last five lines off the error stack (they're
+ # from the "uplevel" command).
+ #
+ set new [split $errorInfo \n]
+ set new [join [lrange $new 0 [expr {[llength $new]-6}]] \n]
+ return -code $status -errorcode $errorCode \
+ -errorinfo $new $result
+
+ } elseif {$status != 4} {
+ return -code $status $result
+ }
+
+ set errorCode $savedErrorCode
+ set errorInfo $savedErrorInfo
+ }
+
+ set name [lindex $args 0]
+ return -code error "invalid command name \"$name\""
+}
+
+# tcl_unknown:
+# Invoked when a Tcl command is invoked that doesn't exist in the
+# interpreter:
+#
+# 1. See if the autoload facility can locate the command in a
+# Tcl script file. If so, load it and execute it.
+# 2. If the command was invoked interactively at top-level:
+# (a) see if the command exists as an executable UNIX program.
+# If so, "exec" the command.
+# (b) see if the command requests csh-like history substitution
+# in one of the common forms !!, !<number>, or ^old^new. If
+# so, emulate csh's history substitution.
+# (c) see if the command is a unique abbreviation for another
+# command. If so, invoke the command.
+#
+# Arguments:
+# args - A list whose elements are the words of the original
+# command, including the command name.
+
+proc tcl_unknown args {
+ global auto_noexec auto_noload env unknown_pending tcl_interactive
+ global errorCode errorInfo
+
+ # If the command word has the form "namespace inscope ns cmd"
+ # then concatenate its arguments onto the end and evaluate it.
+
+ set cmd [lindex $args 0]
+ if {[regexp "^namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} {
+ set arglist [lrange $args 1 end]
+ set ret [catch {uplevel 1 $cmd $arglist} result]
+ if {$ret == 0} {
+ return $result
+ } else {
+ return -code $ret -errorcode $errorCode $result
+ }
+ }
+
+ # CAD tools special:
+ # Check for commands which were renamed to tcl_(command)
+
+ if {[lsearch [info commands] tcl_$cmd] >= 0} {
+ set arglist [concat tcl_$cmd [lrange $args 1 end]]
+ set ret [catch {eval $arglist} result]
+ if {$ret == 0} {
+ return $result
+ } else {
+ return -code $ret -errorcode $errorCode $result
+ }
+ }
+
+ # Save the values of errorCode and errorInfo variables, since they
+ # may get modified if caught errors occur below. The variables will
+ # be restored just before re-executing the missing command.
+
+ set savedErrorCode $errorCode
+ set savedErrorInfo $errorInfo
+ set name [lindex $args 0]
+ if {![info exists auto_noload]} {
+ #
+ # Make sure we're not trying to load the same proc twice.
+ #
+ if {[info exists unknown_pending($name)]} {
+ return -code error "self-referential recursion in \"unknown\" for command \"$name\""
+ }
+ set unknown_pending($name) pending
+ if {[llength [info args auto_load]]==1} {
+ set ret [catch {auto_load $name} msg]
+ } else {
+ set ret [catch {auto_load $name [uplevel 1 {namespace current}]} msg]
+ }
+ unset unknown_pending($name)
+ if {$ret} {
+ return -code $ret -errorcode $errorCode \
+ "error while autoloading \"$name\": $msg"
+ }
+ #
+ # Avoid problems with renaming "array"! (for tcl-based magic only)
+ #
+ set arraycmd array
+ if {[lsearch [info commands] tcl_array] >= 0} {set arraycmd tcl_array}
+
+ if {![$arraycmd size unknown_pending]} { unset unknown_pending }
+ if {$msg} {
+ set errorCode $savedErrorCode
+ set errorInfo $savedErrorInfo
+ set code [catch {uplevel 1 $args} msg]
+ if {$code == 1} {
+ #
+ # Strip the last five lines off the error stack (they're
+ # from the "uplevel" command).
+ #
+
+ set new [split $errorInfo \n]
+ set new [join [lrange $new 0 [expr {[llength $new]-6}]] \n]
+ return -code error -errorcode $errorCode \
+ -errorinfo $new $msg
+ } else {
+ return -code $code $msg
+ }
+ }
+ }
+ if {[info level] == 1 && [string match {} [info script]] \
+ && [info exists tcl_interactive] && $tcl_interactive} {
+ if {![info exists auto_noexec]} {
+ set new [auto_execok $name]
+ if {[string compare {} $new]} {
+ set errorCode $savedErrorCode
+ set errorInfo $savedErrorInfo
+ return [uplevel 1 exec $new [lrange $args 1 end]]
+ #return [uplevel exec >&@stdout <@stdin $new [lrange $args 1 end]]
+ }
+ }
+ set errorCode $savedErrorCode
+ set errorInfo $savedErrorInfo
+ ##
+ ## History substitution moved into ::tkcon::EvalCmd
+ ##
+ set ret [catch {set cmds [info commands $name*]} msg]
+ if {[string compare $name "::"] == 0} {
+ set name ""
+ }
+ if {$ret != 0} {
+ return -code $ret -errorcode $errorCode \
+ "error in unknown while checking if \"$name\" is a unique command abbreviation: $msg"
+ }
+ set cmds [info commands $name*]
+ if {[llength $cmds] == 1} {
+ return [uplevel 1 [lreplace $args 0 0 $cmds]]
+ }
+ if {[llength $cmds]} {
+ if {$name == ""} {
+ return -code error "empty command name \"\""
+ } else {
+ return -code error \
+ "ambiguous command name \"$name\": [lsort $cmds]"
+ }
+ }
+ ## We've got nothing so far
+ ## Check and see if Tk wasn't loaded, but it appears to be a Tk cmd
+ if {![uplevel \#0 info exists tk_version]} {
+ lappend tkcmds bell bind bindtags button \
+ canvas checkbutton clipboard destroy \
+ entry event focus font frame grab grid image \
+ label listbox lower menu menubutton message \
+ option pack place radiobutton raise \
+ scale scrollbar selection send spinbox \
+ text tk tkwait toplevel winfo wm
+ if {[lsearch -exact $tkcmds $name] >= 0 && \
+ [tkcon master tk_messageBox -icon question -parent . \
+ -title "Load Tk?" -type retrycancel -default retry \
+ -message "This appears to be a Tk command, but Tk\
+ has not yet been loaded. Shall I retry the command\
+ with loading Tk first?"] == "retry"} {
+ return [uplevel 1 "load {} Tk; $args"]
+ }
+ }
+ }
+ return -code continue
+}
+
+} ; # end exclusionary code for WWW
+
+proc ::tkcon::Bindings {} {
+ variable PRIV
+ global tcl_platform tk_version
+
+ #-----------------------------------------------------------------------
+ # Elements of tkPriv that are used in this file:
+ #
+ # char - Character position on the line; kept in order
+ # to allow moving up or down past short lines while
+ # still remembering the desired position.
+ # mouseMoved - Non-zero means the mouse has moved a significant
+ # amount since the button went down (so, for example,
+ # start dragging out a selection).
+ # prevPos - Used when moving up or down lines via the keyboard.
+ # Keeps track of the previous insert position, so
+ # we can distinguish a series of ups and downs, all
+ # in a row, from a new up or down.
+ # selectMode - The style of selection currently underway:
+ # char, word, or line.
+ # x, y - Last known mouse coordinates for scanning
+ # and auto-scanning.
+ #-----------------------------------------------------------------------
+
+ switch -glob $tcl_platform(platform) {
+ win* { set PRIV(meta) Alt }
+ mac* { set PRIV(meta) Command }
+ default { set PRIV(meta) Meta }
+ }
+
+ ## Get all Text bindings into TkConsole
+ foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] }
+ ## We really didn't want the newline insertion
+ bind TkConsole <Control-Key-o> {}
+
+ ## in 8.6b3, the virtual events <<NextLine>> and <<PrevLine>>
+ # mess up our history feature
+ bind TkConsole <<NextLine>> {}
+ bind TkConsole <<PrevLine>> {}
+
+ ## Now make all our virtual event bindings
+ foreach {ev key} [subst -nocommand -noback {
+ <<TkCon_Exit>> <Control-q>
+ <<TkCon_New>> <Control-N>
+ <<TkCon_Close>> <Control-w>
+ <<TkCon_About>> <Control-A>
+ <<TkCon_Help>> <Control-H>
+ <<TkCon_Find>> <Control-F>
+ <<TkCon_Slave>> <Control-Key-1>
+ <<TkCon_Master>> <Control-Key-2>
+ <<TkCon_Main>> <Control-Key-3>
+ <<TkCon_Expand>> <Key-Tab>
+ <<TkCon_ExpandFile>> <Key-Escape>
+ <<TkCon_ExpandProc>> <Control-P>
+ <<TkCon_ExpandVar>> <Control-V>
+ <<TkCon_Tab>> <Control-i>
+ <<TkCon_Tab>> <$PRIV(meta)-i>
+ <<TkCon_Newline>> <Control-o>
+ <<TkCon_Newline>> <$PRIV(meta)-o>
+ <<TkCon_Newline>> <Control-Key-Return>
+ <<TkCon_Newline>> <Control-Key-KP_Enter>
+ <<TkCon_Eval>> <Return>
+ <<TkCon_Eval>> <KP_Enter>
+ <<TkCon_Clear>> <Control-l>
+ <<TkCon_Previous>> <Up>
+ <<TkCon_PreviousImmediate>> <Control-p>
+ <<TkCon_PreviousSearch>> <Control-r>
+ <<TkCon_Next>> <Down>
+ <<TkCon_NextImmediate>> <Control-n>
+ <<TkCon_NextSearch>> <Control-s>
+ <<TkCon_Transpose>> <Control-t>
+ <<TkCon_ClearLine>> <Control-u>
+ <<TkCon_SaveCommand>> <Control-z>
+ <<TkCon_Popup>> <Button-3>
+ }] {
+ event add $ev $key
+ ## Make sure the specific key won't be defined
+ bind TkConsole $key {}
+ }
+
+ ## Make the ROOT bindings
+ bind $PRIV(root) <<TkCon_Exit>> exit
+ bind $PRIV(root) <<TkCon_New>> { ::tkcon::New }
+ bind $PRIV(root) <<TkCon_Close>> { ::tkcon::Destroy }
+ bind $PRIV(root) <<TkCon_About>> { ::tkcon::About }
+ bind $PRIV(root) <<TkCon_Help>> { ::tkcon::Help }
+ bind $PRIV(root) <<TkCon_Find>> { ::tkcon::FindBox $::tkcon::PRIV(console) }
+ bind $PRIV(root) <<TkCon_Slave>> {
+ ::tkcon::Attach {}
+ ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]
+ }
+ bind $PRIV(root) <<TkCon_Master>> {
+ if {[string compare {} $::tkcon::PRIV(name)]} {
+ ::tkcon::Attach $::tkcon::PRIV(name)
+ } else {
+ ::tkcon::Attach Main
+ }
+ ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]
+ }
+ bind $PRIV(root) <<TkCon_Main>> {
+ ::tkcon::Attach Main
+ ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]
+ }
+ bind $PRIV(root) <<TkCon_Popup>> {
+ ::tkcon::PopupMenu %X %Y
+ }
+
+ ## Menu items need null TkConsolePost bindings to avoid the TagProc
+ ##
+ foreach ev [bind $PRIV(root)] {
+ bind TkConsolePost $ev {
+ # empty
+ }
+ }
+
+
+ # ::tkcon::ClipboardKeysyms --
+ # This procedure is invoked to identify the keys that correspond to
+ # the copy, cut, and paste functions for the clipboard.
+ #
+ # Arguments:
+ # copy - Name of the key (keysym name plus modifiers, if any,
+ # such as "Meta-y") used for the copy operation.
+ # cut - Name of the key used for the cut operation.
+ # paste - Name of the key used for the paste operation.
+
+ proc ::tkcon::ClipboardKeysyms {copy cut paste} {
+ bind TkConsole <$copy> {::tkcon::Copy %W}
+ bind TkConsole <$cut> {::tkcon::Cut %W}
+ bind TkConsole <$paste> {::tkcon::Paste %W}
+ }
+
+ proc ::tkcon::GetSelection {w} {
+ if {
+ ![catch {selection get -displayof $w -type UTF8_STRING} txt] ||
+ ![catch {selection get -displayof $w} txt] ||
+ ![catch {selection get -displayof $w -selection CLIPBOARD} txt]
+ } {
+ return $txt
+ }
+ return -code error "could not find default selection"
+ }
+
+ proc ::tkcon::Cut w {
+ if {[string match $w [selection own -displayof $w]]} {
+ clipboard clear -displayof $w
+ catch {
+ set txt [selection get -displayof $w]
+ clipboard append -displayof $w $txt
+ if {[$w compare sel.first >= limit]} {
+ $w delete sel.first sel.last
+ }
+ }
+ }
+ }
+ proc ::tkcon::Copy w {
+ if {[string match $w [selection own -displayof $w]]} {
+ clipboard clear -displayof $w
+ catch {
+ set txt [selection get -displayof $w]
+ clipboard append -displayof $w $txt
+ }
+ }
+ }
+ proc ::tkcon::Paste w {
+ if {![catch {GetSelection $w} txt]} {
+ if {[$w compare insert < limit]} { $w mark set insert end }
+ $w insert insert $txt
+ $w see insert
+ if {[string match *\n* $txt]} { ::tkcon::Eval $w }
+ }
+ }
+
+ ## Redefine for TkConsole what we need
+ ##
+ event delete <<Paste>> <Control-V>
+ ::tkcon::ClipboardKeysyms <Copy> <Cut> <Paste>
+
+ bind TkConsole <Insert> {
+ catch { ::tkcon::Insert %W [::tkcon::GetSelection %W] }
+ }
+
+ bind TkConsole <Triple-1> {+
+ catch {
+ eval %W tag remove sel [%W tag nextrange prompt sel.first sel.last]
+ eval %W tag remove sel sel.last-1c
+ %W mark set insert sel.first
+ }
+ }
+
+ ## binding editor needed
+ ## binding <events> for .tkconrc
+
+ bind TkConsole <<TkCon_ExpandFile>> {
+ if {[%W compare insert > limit]} {::tkcon::Expand %W path}
+ break
+ }
+ bind TkConsole <<TkCon_ExpandProc>> {
+ if {[%W compare insert > limit]} {::tkcon::Expand %W proc}
+ }
+ bind TkConsole <<TkCon_ExpandVar>> {
+ if {[%W compare insert > limit]} {::tkcon::Expand %W var}
+ }
+ bind TkConsole <<TkCon_Expand>> {
+ if {[%W compare insert > limit]} {::tkcon::Expand %W}
+ }
+ bind TkConsole <<TkCon_Tab>> {
+ if {[%W compare insert >= limit]} {
+ ::tkcon::Insert %W \t
+ }
+ }
+ bind TkConsole <<TkCon_Newline>> {
+ if {[%W compare insert >= limit]} {
+ ::tkcon::Insert %W \n
+ }
+ }
+ bind TkConsole <<TkCon_Eval>> {
+ ::tkcon::Eval %W
+ }
+ bind TkConsole <Delete> {
+ if {[llength [%W tag nextrange sel 1.0 end]] \
+ && [%W compare sel.first >= limit]} {
+ %W delete sel.first sel.last
+ } elseif {[%W compare insert >= limit]} {
+ %W delete insert
+ %W see insert
+ }
+ }
+ bind TkConsole <BackSpace> {
+ if {[llength [%W tag nextrange sel 1.0 end]] \
+ && [%W compare sel.first >= limit]} {
+ %W delete sel.first sel.last
+ } elseif {[%W compare insert != 1.0] && [%W compare insert > limit]} {
+ %W delete insert-1c
+ %W see insert
+ }
+ }
+ bind TkConsole <Control-h> [bind TkConsole <BackSpace>]
+
+ bind TkConsole <KeyPress> {
+ ::tkcon::Insert %W %A
+ }
+
+ bind TkConsole <Control-a> {
+ if {[%W compare {limit linestart} == {insert linestart}]} {
+ tkTextSetCursor %W limit
+ } else {
+ tkTextSetCursor %W {insert linestart}
+ }
+ }
+ bind TkConsole <Key-Home> [bind TkConsole <Control-a>]
+ bind TkConsole <Control-d> {
+ if {[%W compare insert < limit]} break
+ %W delete insert
+ }
+ bind TkConsole <Control-k> {
+ if {[%W compare insert < limit]} break
+ if {[%W compare insert == {insert lineend}]} {
+ %W delete insert
+ } else {
+ %W delete insert {insert lineend}
+ }
+ }
+ bind TkConsole <<TkCon_Clear>> {
+ ## Clear console buffer, without losing current command line input
+ set ::tkcon::PRIV(tmp) [::tkcon::CmdGet %W]
+ clear
+ ::tkcon::Prompt {} $::tkcon::PRIV(tmp)
+ }
+ bind TkConsole <<TkCon_Previous>> {
+ if {[%W compare {insert linestart} != {limit linestart}]} {
+ tkTextSetCursor %W [tkTextUpDownLine %W -1]
+ } else {
+ ::tkcon::Event -1
+ }
+ }
+ bind TkConsole <<TkCon_Next>> {
+ if {[%W compare {insert linestart} != {end-1c linestart}]} {
+ tkTextSetCursor %W [tkTextUpDownLine %W 1]
+ } else {
+ ::tkcon::Event 1
+ }
+ }
+ bind TkConsole <<TkCon_NextImmediate>> { ::tkcon::Event 1 }
+ bind TkConsole <<TkCon_PreviousImmediate>> { ::tkcon::Event -1 }
+ bind TkConsole <<TkCon_PreviousSearch>> {
+ ::tkcon::Event -1 [::tkcon::CmdGet %W]
+ }
+ bind TkConsole <<TkCon_NextSearch>> {
+ ::tkcon::Event 1 [::tkcon::CmdGet %W]
+ }
+ bind TkConsole <<TkCon_Transpose>> {
+ ## Transpose current and previous chars
+ if {[%W compare insert > "limit+1c"]} { tkTextTranspose %W }
+ }
+ bind TkConsole <<TkCon_ClearLine>> {
+ ## Clear command line (Unix shell staple)
+ %W delete limit end
+ }
+ bind TkConsole <<TkCon_SaveCommand>> {
+ ## Save command buffer (swaps with current command)
+ set ::tkcon::PRIV(tmp) $::tkcon::PRIV(cmdsave)
+ set ::tkcon::PRIV(cmdsave) [::tkcon::CmdGet %W]
+ if {[string match {} $::tkcon::PRIV(cmdsave)]} {
+ set ::tkcon::PRIV(cmdsave) $::tkcon::PRIV(tmp)
+ } else {
+ %W delete limit end-1c
+ }
+ ::tkcon::Insert %W $::tkcon::PRIV(tmp)
+ %W see end
+ }
+ catch {bind TkConsole <Key-Page_Up> { tkTextScrollPages %W -1 }}
+ catch {bind TkConsole <Key-Prior> { tkTextScrollPages %W -1 }}
+ catch {bind TkConsole <Key-Page_Down> { tkTextScrollPages %W 1 }}
+ catch {bind TkConsole <Key-Next> { tkTextScrollPages %W 1 }}
+ bind TkConsole <$PRIV(meta)-d> {
+ if {[%W compare insert >= limit]} {
+ %W delete insert {insert wordend}
+ }
+ }
+ bind TkConsole <$PRIV(meta)-BackSpace> {
+ if {[%W compare {insert -1c wordstart} >= limit]} {
+ %W delete {insert -1c wordstart} insert
+ }
+ }
+ bind TkConsole <$PRIV(meta)-Delete> {
+ if {[%W compare insert >= limit]} {
+ %W delete insert {insert wordend}
+ }
+ }
+ bind TkConsole <ButtonRelease-2> {
+ if {
+ (!$tkPriv(mouseMoved) || $tk_strictMotif) &&
+ ![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)]
+ } {
+ if {[%W compare @%x,%y < limit]} {
+ %W insert end $::tkcon::PRIV(tmp)
+ } else {
+ %W insert @%x,%y $::tkcon::PRIV(tmp)
+ }
+ if {[string match *\n* $::tkcon::PRIV(tmp)]} {::tkcon::Eval %W}
+ }
+ }
+
+ ##
+ ## End TkConsole bindings
+ ##
+
+ ##
+ ## Bindings for doing special things based on certain keys
+ ##
+ bind TkConsolePost <Key-parenright> {
+ if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \
+ [string compare \\ [%W get insert-2c]]} {
+ ::tkcon::MatchPair %W \( \) limit
+ }
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+ bind TkConsolePost <Key-bracketright> {
+ if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \
+ [string compare \\ [%W get insert-2c]]} {
+ ::tkcon::MatchPair %W \[ \] limit
+ }
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+ bind TkConsolePost <Key-braceright> {
+ if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \
+ [string compare \\ [%W get insert-2c]]} {
+ ::tkcon::MatchPair %W \{ \} limit
+ }
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+ bind TkConsolePost <Key-quotedbl> {
+ if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \
+ [string compare \\ [%W get insert-2c]]} {
+ ::tkcon::MatchQuote %W limit
+ }
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+
+ bind TkConsolePost <KeyPress> {
+ if {$::tkcon::OPT(lightcmd) && [string compare {} %A]} {
+ ::tkcon::TagProc %W
+ }
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+
+ bind TkConsolePost <Button-1> {
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+ bind TkConsolePost <B1-Motion> {
+ set ::tkcon::PRIV(StatusCursor) [%W index insert]
+ }
+
+}
+
+##
+# ::tkcon::PopupMenu - what to do when the popup menu is requested
+##
+proc ::tkcon::PopupMenu {X Y} {
+ variable PRIV
+
+ set w $PRIV(console)
+ if {[string compare $w [winfo containing $X $Y]]} {
+ tk_popup $PRIV(popup) $X $Y
+ return
+ }
+ set x [expr {$X-[winfo rootx $w]}]
+ set y [expr {$Y-[winfo rooty $w]}]
+ if {[llength [set tags [$w tag names @$x,$y]]]} {
+ if {[lsearch -exact $tags "proc"] >= 0} {
+ lappend type "proc"
+ foreach {first last} [$w tag prevrange proc @$x,$y] {
+ set word [$w get $first $last]; break
+ }
+ }
+ if {[lsearch -exact $tags "var"] >= 0} {
+ lappend type "var"
+ foreach {first last} [$w tag prevrange var @$x,$y] {
+ set word [$w get $first $last]; break
+ }
+ }
+ }
+ if {![info exists type]} {
+ set exp "(^|\[^\\\\\]\[ \t\n\r\])"
+ set exp2 "\[\[\\\\\\?\\*\]"
+ set i [$w search -backwards -regexp $exp @$x,$y "@$x,$y linestart"]
+ if {[string compare {} $i]} {
+ if {![string match *.0 $i]} {append i +2c}
+ if {[string compare {} \
+ [set j [$w search -regexp $exp $i "$i lineend"]]]} {
+ append j +1c
+ } else {
+ set j "$i lineend"
+ }
+ regsub -all $exp2 [$w get $i $j] {\\\0} word
+ set word [string trim $word {\"$[]{}',?#*}]
+ if {[llength [EvalAttached [list info commands $word]]]} {
+ lappend type "proc"
+ }
+ if {[llength [EvalAttached [list info vars $word]]]} {
+ lappend type "var"
+ }
+ if {[EvalAttached [list file isfile $word]]} {
+ lappend type "file"
+ }
+ }
+ }
+ if {![info exists type] || ![info exists word]} {
+ tk_popup $PRIV(popup) $X $Y
+ return
+ }
+ $PRIV(context) delete 0 end
+ $PRIV(context) add command -label "$word" -state disabled
+ $PRIV(context) add separator
+ set app [Attach]
+ if {[lsearch $type proc] != -1} {
+ $PRIV(context) add command -label "View Procedure" \
+ -command [list edit -attach $app -type proc -- $word]
+ }
+ if {[lsearch $type var] != -1} {
+ $PRIV(context) add command -label "View Variable" \
+ -command [list edit -attach $app -type var -- $word]
+ }
+ if {[lsearch $type file] != -1} {
+ $PRIV(context) add command -label "View File" \
+ -command [list edit -attach $app -type file -- $word]
+ }
+ tk_popup $PRIV(context) $X $Y
+}
+
+## ::tkcon::TagProc - tags a procedure in the console if it's recognized
+## This procedure is not perfect. However, making it perfect wastes
+## too much CPU time...
+##
+proc ::tkcon::TagProc w {
+ set exp "\[^\\\\\]\[\[ \t\n\r\;{}\"\$\]"
+ set i [$w search -backwards -regexp $exp insert-1c limit-1c]
+ if {[string compare {} $i]} {append i +2c} else {set i limit}
+ regsub -all "\[\[\\\\\\?\\*\]" [$w get $i "insert-1c wordend"] {\\\0} c
+ if {[llength [EvalAttached [list info commands $c]]]} {
+ $w tag add proc $i "insert-1c wordend"
+ } else {
+ $w tag remove proc $i "insert-1c wordend"
+ }
+ if {[llength [EvalAttached [list info vars $c]]]} {
+ $w tag add var $i "insert-1c wordend"
+ } else {
+ $w tag remove var $i "insert-1c wordend"
+ }
+}
+
+## ::tkcon::MatchPair - blinks a matching pair of characters
+## c2 is assumed to be at the text index 'insert'.
+## This proc is really loopy and took me an hour to figure out given
+## all possible combinations with escaping except for escaped \'s.
+## It doesn't take into account possible commenting... Oh well. If
+## anyone has something better, I'd like to see/use it. This is really
+## only efficient for small contexts.
+# ARGS: w - console text widget
+# c1 - first char of pair
+# c2 - second char of pair
+# Calls: ::tkcon::Blink
+##
+proc ::tkcon::MatchPair {w c1 c2 {lim 1.0}} {
+ if {[string compare {} [set ix [$w search -back $c1 insert $lim]]]} {
+ while {
+ [string match {\\} [$w get $ix-1c]] &&
+ [string compare {} [set ix [$w search -back $c1 $ix-1c $lim]]]
+ } {}
+ set i1 insert-1c
+ while {[string compare {} $ix]} {
+ set i0 $ix
+ set j 0
+ while {[string compare {} [set i0 [$w search $c2 $i0 $i1]]]} {
+ append i0 +1c
+ if {[string match {\\} [$w get $i0-2c]]} continue
+ incr j
+ }
+ if {!$j} break
+ set i1 $ix
+ while {$j && [string compare {} \
+ [set ix [$w search -back $c1 $ix $lim]]]} {
+ if {[string match {\\} [$w get $ix-1c]]} continue
+ incr j -1
+ }
+ }
+ if {[string match {} $ix]} { set ix [$w index $lim] }
+ } else { set ix [$w index $lim] }
+ if {$::tkcon::OPT(blinkrange)} {
+ Blink $w $ix [$w index insert]
+ } else {
+ Blink $w $ix $ix+1c [$w index insert-1c] [$w index insert]
+ }
+}
+
+## ::tkcon::MatchQuote - blinks between matching quotes.
+## Blinks just the quote if it's unmatched, otherwise blinks quoted string
+## The quote to match is assumed to be at the text index 'insert'.
+# ARGS: w - console text widget
+# Calls: ::tkcon::Blink
+##
+proc ::tkcon::MatchQuote {w {lim 1.0}} {
+ set i insert-1c
+ set j 0
+ while {[string compare [set i [$w search -back \" $i $lim]] {}]} {
+ if {[string match {\\} [$w get $i-1c]]} continue
+ if {!$j} {set i0 $i}
+ incr j
+ }
+ if {$j&1} {
+ if {$::tkcon::OPT(blinkrange)} {
+ Blink $w $i0 [$w index insert]
+ } else {
+ Blink $w $i0 $i0+1c [$w index insert-1c] [$w index insert]
+ }
+ } else {
+ Blink $w [$w index insert-1c] [$w index insert]
+ }
+}
+
+## ::tkcon::Blink - blinks between n index pairs for a specified duration.
+# ARGS: w - console text widget
+# i1 - start index to blink region
+# i2 - end index of blink region
+# dur - duration in usecs to blink for
+# Outputs: blinks selected characters in $w
+##
+proc ::tkcon::Blink {w args} {
+ eval [list $w tag add blink] $args
+ after $::tkcon::OPT(blinktime) [list $w] tag remove blink $args
+ return
+}
+
+
+## ::tkcon::Insert
+## Insert a string into a text console at the point of the insertion cursor.
+## If there is a selection in the text, and it covers the point of the
+## insertion cursor, then delete the selection before inserting.
+# ARGS: w - text window in which to insert the string
+# s - string to insert (usually just a single char)
+# Outputs: $s to text widget
+##
+proc ::tkcon::Insert {w s} {
+ if {[string match {} $s] || [string match disabled [$w cget -state]]} {
+ return
+ }
+ if {[$w comp insert < limit]} {
+ $w mark set insert end
+ }
+ if {[llength [$w tag ranges sel]] && \
+ [$w comp sel.first <= insert] && [$w comp sel.last >= insert]} {
+ $w delete sel.first sel.last
+ }
+ $w insert insert $s
+ $w see insert
+}
+
+## ::tkcon::Expand -
+# ARGS: w - text widget in which to expand str
+# type - type of expansion (path / proc / variable)
+# Calls: ::tkcon::Expand(Pathname|Procname|Variable)
+# Outputs: The string to match is expanded to the longest possible match.
+# If ::tkcon::OPT(showmultiple) is non-zero and the user longest
+# match equaled the string to expand, then all possible matches
+# are output to stdout. Triggers bell if no matches are found.
+# Returns: number of matches found
+##
+proc ::tkcon::Expand {w {type ""}} {
+ set exp "\[^\\\\\]\[\[ \t\n\r\\\{\"$\]"
+ set tmp [$w search -backwards -regexp $exp insert-1c limit-1c]
+ if {[string compare {} $tmp]} {append tmp +2c} else {set tmp limit}
+ if {[$w compare $tmp >= insert]} return
+ set str [$w get $tmp insert]
+ switch -glob $type {
+ pa* { set res [ExpandPathname $str] }
+ pr* { set res [ExpandProcname $str] }
+ v* { set res [ExpandVariable $str] }
+ default {
+ set res {}
+ foreach t $::tkcon::OPT(expandorder) {
+ if {![catch {Expand$t $str} res] && \
+ [string compare {} $res]} break
+ }
+ }
+ }
+ set len [llength $res]
+ if {$len} {
+ $w delete $tmp insert
+ $w insert $tmp [lindex $res 0]
+ if {$len > 1} {
+ if {$::tkcon::OPT(showmultiple) && \
+ ![string compare [lindex $res 0] $str]} {
+ puts stdout [lsort [lreplace $res 0 0]]
+ }
+ }
+ } else { bell }
+ return [incr len -1]
+}
+
+## ::tkcon::ExpandPathname - expand a file pathname based on $str
+## This is based on UNIX file name conventions
+# ARGS: str - partial file pathname to expand
+# Calls: ::tkcon::ExpandBestMatch
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+##
+proc ::tkcon::ExpandPathname str {
+ set pwd [EvalAttached pwd]
+ # Cause a string like {C:/Program\ Files/} to become "C:/Program Files/"
+ regsub -all {\\([][ ])} $str {\1} str
+ if {[catch {EvalAttached [list cd [file dirname $str]]} err]} {
+ return -code error $err
+ }
+ set dir [file tail $str]
+ ## Check to see if it was known to be a directory and keep the trailing
+ ## slash if so (file tail cuts it off)
+ if {[string match */ $str]} { append dir / }
+ # Create a safely glob-able name
+ regsub -all {([][])} $dir {\\\1} safedir
+ if {[catch {lsort [EvalAttached [list glob $safedir*]]} m]} {
+ set match {}
+ } else {
+ if {[llength $m] > 1} {
+ global tcl_platform
+ if {[string match windows $tcl_platform(platform)]} {
+ ## Windows is screwy because it's case insensitive
+ set tmp [ExpandBestMatch [string tolower $m] \
+ [string tolower $dir]]
+ ## Don't change case if we haven't changed the word
+ if {[string length $dir]==[string length $tmp]} {
+ set tmp $dir
+ }
+ } else {
+ set tmp [ExpandBestMatch $m $dir]
+ }
+ if {[string match */* $str]} {
+ set tmp [string trimright [file dirname $str] /]/$tmp
+ }
+ regsub -all {([^\\])([][ ])} $tmp {\1\\\2} tmp
+ set match [linsert $m 0 $tmp]
+ } else {
+ ## This may look goofy, but it handles spaces in path names
+ eval append match $m
+ if {[file isdirectory $match]} {append match /}
+ if {[string match */* $str]} {
+ set match [string trimright [file dirname $str] /]/$match
+ }
+ regsub -all {([^\\])([][ ])} $match {\1\\\2} match
+ ## Why is this one needed and the ones below aren't!!
+ set match [list $match]
+ }
+ }
+ EvalAttached [list cd $pwd]
+ return $match
+}
+
+## ::tkcon::ExpandProcname - expand a tcl proc name based on $str
+# ARGS: str - partial proc name to expand
+# Calls: ::tkcon::ExpandBestMatch
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+##
+proc ::tkcon::ExpandProcname str {
+ set match [EvalAttached [list info commands $str*]]
+ if {[llength $match] == 0} {
+ set ns [EvalAttached \
+ "namespace children \[namespace current\] [list $str*]"]
+ if {[llength $ns]==1} {
+ set match [EvalAttached [list info commands ${ns}::*]]
+ } else {
+ set match $ns
+ }
+ }
+ if {[llength $match] > 1} {
+ regsub -all {([^\\]) } [ExpandBestMatch $match $str] {\1\\ } str
+ set match [linsert $match 0 $str]
+ } else {
+ regsub -all {([^\\]) } $match {\1\\ } match
+ }
+ return $match
+}
+
+## ::tkcon::ExpandVariable - expand a tcl variable name based on $str
+# ARGS: str - partial tcl var name to expand
+# Calls: ::tkcon::ExpandBestMatch
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+##
+proc ::tkcon::ExpandVariable str {
+ if {[regexp {([^\(]*)\((.*)} $str junk ary str]} {
+ ## Looks like they're trying to expand an array.
+ set match [EvalAttached [list array names $ary $str*]]
+ if {[llength $match] > 1} {
+ set vars $ary\([ExpandBestMatch $match $str]
+ foreach var $match {lappend vars $ary\($var\)}
+ return $vars
+ } else {set match $ary\($match\)}
+ ## Space transformation avoided for array names.
+ } else {
+ set match [EvalAttached [list info vars $str*]]
+ if {[llength $match] > 1} {
+ regsub -all {([^\\]) } [ExpandBestMatch $match $str] {\1\\ } str
+ set match [linsert $match 0 $str]
+ } else {
+ regsub -all {([^\\]) } $match {\1\\ } match
+ }
+ }
+ return $match
+}
+
+## ::tkcon::ExpandBestMatch2 - finds the best unique match in a list of names
+## Improves upon the speed of the below proc only when $l is small
+## or $e is {}. $e is extra for compatibility with proc below.
+# ARGS: l - list to find best unique match in
+# Returns: longest unique match in the list
+##
+proc ::tkcon::ExpandBestMatch2 {l {e {}}} {
+ set s [lindex $l 0]
+ if {[llength $l]>1} {
+ set i [expr {[string length $s]-1}]
+ foreach l $l {
+ while {$i>=0 && [string first $s $l]} {
+ set s [string range $s 0 [incr i -1]]
+ }
+ }
+ }
+ return $s
+}
+
+## ::tkcon::ExpandBestMatch - finds the best unique match in a list of names
+## The extra $e in this argument allows us to limit the innermost loop a
+## little further. This improves speed as $l becomes large or $e becomes long.
+# ARGS: l - list to find best unique match in
+# e - currently best known unique match
+# Returns: longest unique match in the list
+##
+proc ::tkcon::ExpandBestMatch {l {e {}}} {
+ set ec [lindex $l 0]
+ if {[llength $l]>1} {
+ set e [string length $e]; incr e -1
+ set ei [string length $ec]; incr ei -1
+ foreach l $l {
+ while {$ei>=$e && [string first $ec $l]} {
+ set ec [string range $ec 0 [incr ei -1]]
+ }
+ }
+ }
+ return $ec
+}
+
+# Here is a group of functions that is only used when Tkcon is
+# executed in a safe interpreter. It provides safe versions of
+# missing functions. For example:
+#
+# - "tk appname" returns "tkcon.tcl" but cannot be set
+# - "toplevel" is equivalent to 'frame', only it is automatically
+# packed.
+# - The 'source', 'load', 'open', 'file' and 'exit' functions are
+# mapped to corresponding functions in the parent interpreter.
+#
+# Further on, Tk cannot be really loaded. Still the safe 'load'
+# provedes a speciall case. The Tk can be divided into 4 groups,
+# that each has a safe handling procedure.
+#
+# - "::tkcon::SafeItem" handles commands like 'button', 'canvas' ......
+# Each of these functions has the window name as first argument.
+# - "::tkcon::SafeManage" handles commands like 'pack', 'place', 'grid',
+# 'winfo', which can have multiple window names as arguments.
+# - "::tkcon::SafeWindow" handles all windows, such as '.'. For every
+# window created, a new alias is formed which also is handled by
+# this function.
+# - Other (e.g. bind, bindtag, image), which need their own function.
+#
+## These functions courtesy Jan Nijtmans (nijtmans@nici.kun.nl)
+##
+if {[string compare [info command tk] tk]} {
+ proc tk {option args} {
+ if {![string match app* $option]} {
+ error "wrong option \"$option\": should be appname"
+ }
+ return "tkcon.tcl"
+ }
+}
+
+if {[string compare [info command toplevel] toplevel]} {
+ proc toplevel {name args} {
+ eval frame $name $args
+ pack $name
+ }
+}
+
+proc ::tkcon::SafeSource {i f} {
+ set fd [open $f r]
+ set r [read $fd]
+ close $fd
+ if {[catch {interp eval $i $r} msg]} {
+ error $msg
+ }
+}
+
+proc ::tkcon::SafeOpen {i f {m r}} {
+ set fd [open $f $m]
+ interp transfer {} $fd $i
+ return $fd
+}
+
+proc ::tkcon::SafeLoad {i f p} {
+ global tk_version tk_patchLevel tk_library auto_path
+ if {[string compare $p Tk]} {
+ load $f $p $i
+ } else {
+ foreach command {button canvas checkbutton entry frame label
+ listbox message radiobutton scale scrollbar spinbox text toplevel} {
+ $i alias $command ::tkcon::SafeItem $i $command
+ }
+ $i alias image ::tkcon::SafeImage $i
+ foreach command {pack place grid destroy winfo} {
+ $i alias $command ::tkcon::SafeManage $i $command
+ }
+ if {[llength [info command event]]} {
+ $i alias event ::tkcon::SafeManage $i $command
+ }
+ frame .${i}_dot -width 300 -height 300 -relief raised
+ pack .${i}_dot -side left
+ $i alias tk tk
+ $i alias bind ::tkcon::SafeBind $i
+ $i alias bindtags ::tkcon::SafeBindtags $i
+ $i alias . ::tkcon::SafeWindow $i {}
+ foreach var {tk_version tk_patchLevel tk_library auto_path} {
+ $i eval set $var [list [set $var]]
+ }
+ $i eval {
+ package provide Tk $tk_version
+ if {[lsearch -exact $auto_path $tk_library] < 0} {
+ lappend auto_path $tk_library
+ }
+ }
+ return ""
+ }
+}
+
+proc ::tkcon::SafeSubst {i a} {
+ set arg1 ""
+ foreach {arg value} $a {
+ if {![string compare $arg -textvariable] ||
+ ![string compare $arg -variable]} {
+ set newvalue "[list $i] $value"
+ global $newvalue
+ if {[interp eval $i info exists $value]} {
+ set $newvalue [interp eval $i set $value]
+ } else {
+ catch {unset $newvalue}
+ }
+ $i eval trace variable $value rwu \{[list tkcon set $newvalue $i]\}
+ set value $newvalue
+ } elseif {![string compare $arg -command]} {
+ set value [list $i eval $value]
+ }
+ lappend arg1 $arg $value
+ }
+ return $arg1
+}
+
+proc ::tkcon::SafeItem {i command w args} {
+ set args [::tkcon::SafeSubst $i $args]
+ set code [catch "$command [list .${i}_dot$w] $args" msg]
+ $i alias $w ::tkcon::SafeWindow $i $w
+ regsub -all .${i}_dot $msg {} msg
+ return -code $code $msg
+}
+
+proc ::tkcon::SafeManage {i command args} {
+ set args1 ""
+ foreach arg $args {
+ if {[string match . $arg]} {
+ set arg .${i}_dot
+ } elseif {[string match .* $arg]} {
+ set arg ".${i}_dot$arg"
+ }
+ lappend args1 $arg
+ }
+ set code [catch "$command $args1" msg]
+ regsub -all .${i}_dot $msg {} msg
+ return -code $code $msg
+}
+
+#
+# FIX: this function doesn't work yet if the binding starts with '+'.
+#
+proc ::tkcon::SafeBind {i w args} {
+ if {[string match . $w]} {
+ set w .${i}_dot
+ } elseif {[string match .* $w]} {
+ set w ".${i}_dot$w"
+ }
+ if {[llength $args] > 1} {
+ set args [list [lindex $args 0] \
+ "[list $i] eval [list [lindex $args 1]]"]
+ }
+ set code [catch "bind $w $args" msg]
+ if {[llength $args] <2 && $code == 0} {
+ set msg [lindex $msg 3]
+ }
+ return -code $code $msg
+}
+
+proc ::tkcon::SafeImage {i option args} {
+ set code [catch "image $option $args" msg]
+ if {[string match cr* $option]} {
+ $i alias $msg $msg
+ }
+ return -code $code $msg
+}
+
+proc ::tkcon::SafeBindtags {i w {tags {}}} {
+ if {[string match . $w]} {
+ set w .${i}_dot
+ } elseif {[string match .* $w]} {
+ set w ".${i}_dot$w"
+ }
+ set newtags {}
+ foreach tag $tags {
+ if {[string match . $tag]} {
+ lappend newtags .${i}_dot
+ } elseif {[string match .* $tag]} {
+ lappend newtags ".${i}_dot$tag"
+ } else {
+ lappend newtags $tag
+ }
+ }
+ if {[string match $tags {}]} {
+ set code [catch {bindtags $w} msg]
+ regsub -all \\.${i}_dot $msg {} msg
+ } else {
+ set code [catch {bindtags $w $newtags} msg]
+ }
+ return -code $code $msg
+}
+
+proc ::tkcon::SafeWindow {i w option args} {
+ if {[string match conf* $option] && [llength $args] > 1} {
+ set args [::tkcon::SafeSubst $i $args]
+ } elseif {[string match itemco* $option] && [llength $args] > 2} {
+ set args "[list [lindex $args 0]] [::tkcon::SafeSubst $i [lrange $args 1 end]]"
+ } elseif {[string match cr* $option]} {
+ if {[llength $args]%2} {
+ set args "[list [lindex $args 0]] [::tkcon::SafeSubst $i [lrange $args 1 end]]"
+ } else {
+ set args [::tkcon::SafeSubst $i $args]
+ }
+ } elseif {[string match bi* $option] && [llength $args] > 2} {
+ set args [list [lindex $args 0] [lindex $args 1] "[list $i] eval [list [lindex $args 2]]"]
+ }
+ set code [catch ".${i}_dot$w $option $args" msg]
+ if {$code} {
+ regsub -all .${i}_dot $msg {} msg
+ } elseif {[string match conf* $option] || [string match itemco* $option]} {
+ if {[llength $args] == 1} {
+ switch -- $args {
+ -textvariable - -variable {
+ set msg "[lrange $msg 0 3] [list [lrange [lindex $msg 4] 1 end]]"
+ }
+ -command - updatecommand {
+ set msg "[lrange $msg 0 3] [list [lindex [lindex $msg 4] 2]]"
+ }
+ }
+ } elseif {[llength $args] == 0} {
+ set args1 ""
+ foreach el $msg {
+ switch -- [lindex $el 0] {
+ -textvariable - -variable {
+ set el "[lrange $el 0 3] [list [lrange [lindex $el 4] 1 end]]"
+ }
+ -command - updatecommand {
+ set el "[lrange $el 0 3] [list [lindex [lindex $el 4] 2]]"
+ }
+ }
+ lappend args1 $el
+ }
+ set msg $args1
+ }
+ } elseif {[string match cg* $option] || [string match itemcg* $option]} {
+ switch -- $args {
+ -textvariable - -variable {
+ set msg [lrange $msg 1 end]
+ }
+ -command - updatecommand {
+ set msg [lindex $msg 2]
+ }
+ }
+ } elseif {[string match bi* $option]} {
+ if {[llength $args] == 2 && $code == 0} {
+ set msg [lindex $msg 2]
+ }
+ }
+ return -code $code $msg
+}
+
+proc ::tkcon::RetrieveFilter {host} {
+ variable PRIV
+ set result {}
+ if {[info exists PRIV(proxy)]} {
+ if {![regexp "^(localhost|127\.0\.0\.1)" $host]} {
+ set result [lrange [split [lindex $PRIV(proxy) 0] :] 0 1]
+ }
+ }
+ return $result
+}
+
+proc ::tkcon::RetrieveAuthentication {} {
+ package require Tk
+ if {[catch {package require base64}]} {
+ if {[catch {package require Trf}]} {
+ error "base64 support not available"
+ } else {
+ set local64 "base64 -mode enc"
+ }
+ } else {
+ set local64 "base64::encode"
+ }
+
+ set dlg [toplevel .auth]
+ wm title $dlg "Authenticating Proxy Configuration"
+ set f1 [frame ${dlg}.f1]
+ set f2 [frame ${dlg}.f2]
+ button $f2.b -text "OK" -command "destroy $dlg"
+ pack $f2.b -side right
+ label $f1.l2 -text "Username"
+ label $f1.l3 -text "Password"
+ entry $f1.e2 -textvariable "[namespace current]::conf_userid"
+ entry $f1.e3 -textvariable "[namespace current]::conf_passwd" -show *
+ grid $f1.l2 -column 0 -row 0 -sticky e
+ grid $f1.l3 -column 0 -row 1 -sticky e
+ grid $f1.e2 -column 1 -row 0 -sticky news
+ grid $f1.e3 -column 1 -row 1 -sticky news
+ grid columnconfigure $f1 1 -weight 1
+ pack $f2 -side bottom -fill x
+ pack $f1 -side top -anchor n -fill both -expand 1
+ tkwait window $dlg
+ set result {}
+ if {[info exists [namespace current]::conf_userid]} {
+ set data [subst $[namespace current]::conf_userid]
+ append data : [subst $[namespace current]::conf_passwd]
+ set data [$local64 $data]
+ set result [list "Proxy-Authorization" "Basic $data"]
+ }
+ unset [namespace current]::conf_passwd
+ return $result
+}
+
+proc ::tkcon::Retrieve {} {
+ # A little bit'o'magic to grab the latest tkcon from CVS and
+ # save it locally. It doesn't support proxies though...
+ variable PRIV
+
+ set defExt ""
+ if {[string match "windows" $::tcl_platform(platform)]} {
+ set defExt ".tcl"
+ }
+ set file [tk_getSaveFile -title "Save Latest tkcon to ..." \
+ -defaultextension $defExt \
+ -initialdir [file dirname $PRIV(SCRIPT)] \
+ -initialfile [file tail $PRIV(SCRIPT)] \
+ -parent $PRIV(root) \
+ -filetypes {{"Tcl Files" {.tcl .tk}} {"All Files" {*.*}}}]
+ if {[string compare $file ""]} {
+ package require http 2
+ set token [::http::geturl $PRIV(HEADURL) -timeout 30000]
+ ::http::wait $token
+ set code [catch {
+ if {[::http::status $token] == "ok"} {
+ set fid [open $file w]
+ # We don't want newline mode to change
+ fconfigure $fid -translation binary
+ set data [::http::data $token]
+ puts -nonewline $fid $data
+ close $fid
+ regexp {Id: tkcon.tcl,v (\d+\.\d+)} $data -> rcsVersion
+ regexp {version\s+(\d+\.\d[^\n]*)} $data -> tkconVersion
+ }
+ } err]
+ ::http::cleanup $token
+ if {$code} {
+ return -code error $err
+ } elseif {[tk_messageBox -type yesno -icon info -parent $PRIV(root) \
+ -title "Retrieved tkcon v$tkconVersion, RCS $rcsVersion" \
+ -message "Successfully retrieved tkcon v$tkconVersion,\
+ RCS $rcsVersion. Shall I resource (not restart) this\
+ version now?"] == "yes"} {
+ set PRIV(SCRIPT) $file
+ set PRIV(version) $tkconVersion.$rcsVersion
+ ::tkcon::Resource
+ }
+ }
+}
+
+## ::tkcon::Resource - re'source's this script into current console
+## Meant primarily for my development of this program. It follows
+## links until the ultimate source is found.
+##
+set ::tkcon::PRIV(SCRIPT) [info script]
+if {!$::tkcon::PRIV(WWW) && [string compare $::tkcon::PRIV(SCRIPT) {}]} {
+ # we use a catch here because some wrap apps choke on 'file type'
+ # because TclpLstat wasn't wrappable until 8.4.
+ catch {
+ while {[string match link [file type $::tkcon::PRIV(SCRIPT)]]} {
+ set link [file readlink $::tkcon::PRIV(SCRIPT)]
+ if {[string match relative [file pathtype $link]]} {
+ set ::tkcon::PRIV(SCRIPT) \
+ [file join [file dirname $::tkcon::PRIV(SCRIPT)] $link]
+ } else {
+ set ::tkcon::PRIV(SCRIPT) $link
+ }
+ }
+ catch {unset link}
+ if {[string match relative [file pathtype $::tkcon::PRIV(SCRIPT)]]} {
+ set ::tkcon::PRIV(SCRIPT) [file join [pwd] $::tkcon::PRIV(SCRIPT)]
+ }
+ }
+}
+
+proc ::tkcon::Resource {} {
+ uplevel \#0 {
+ if {[catch {source -rsrc tkcon}]} { source $::tkcon::PRIV(SCRIPT) }
+ }
+ Bindings
+ InitSlave $::tkcon::OPT(exec)
+}
+
+## Initialize only if we haven't yet
+##
+if {![info exists ::tkcon::PRIV(root)] || \
+ ![winfo exists $::tkcon::PRIV(root)]} {
+ ::tkcon::Init
+}
diff --git a/lib/tcl/wrapper.tcl b/lib/tcl/wrapper.tcl
new file mode 100644
index 0000000..20486e0
--- /dev/null
+++ b/lib/tcl/wrapper.tcl
@@ -0,0 +1,3286 @@
+#-------------------------------------------------------------------------
+# Start of xcircuit GUI configuration file.
+# This file is sourced by "xcircuit.tcl" (".wishrc")
+#-------------------------------------------------------------------------
+
+# This script sets up all the xcircuit windows and callback functions.
+# The callback routines are in the shared object file xcwrap.so
+#
+
+#-------------------------------
+# Main xcircuit drawing window
+#-------------------------------
+
+proc xcircuit::new_window { name } {
+
+ global XCIRCUIT_VERSION XCIRCUIT_REVISION XCOps XCWinOps tcl_platform
+
+ toplevel $name
+ wm title $name XCircuit
+ wm group $name .
+ wm protocol $name WM_DELETE_WINDOW \
+ "xcircuit::closewindow ${name}.mainframe.mainarea.drawing"
+
+ # All the internal frames
+
+ frame ${name}.menubar
+ frame ${name}.infobar -borderwidth 1 -bg #a07650
+ frame ${name}.mainframe -borderwidth 1 -bg #a07650
+
+ grid propagate ${name} false
+ grid ${name}.menubar -sticky news -row 0 -column 0
+ grid ${name}.mainframe -sticky news -row 1 -columnspan 2
+ grid ${name}.infobar -sticky news -row 2 -columnspan 2
+
+ grid rowconfigure ${name} 0 -weight 0
+ grid rowconfigure ${name} 1 -weight 1
+ grid rowconfigure ${name} 2 -weight 0
+
+ grid columnconfigure ${name} 0 -weight 0
+ grid columnconfigure ${name} 1 -weight 1
+
+ frame ${name}.mainframe.mainarea
+ frame ${name}.mainframe.toolbar -bg #a07650 -borderwidth 1
+
+ pack ${name}.mainframe.toolbar -side right -fill y
+ pack ${name}.mainframe.mainarea -expand true -fill both
+
+ set drawing ${name}.mainframe.mainarea.drawing
+ simple $drawing -bg white -commandproc "focus $drawing ; set XCOps(focus) $name"
+
+ simple ${name}.mainframe.mainarea.sbleft -width 13 -bg #a07650
+ simple ${name}.mainframe.mainarea.sbbottom -height 13 -bg #a07650
+ simple ${name}.mainframe.mainarea.corner -width 13 -height 13 -bg brown4
+
+ # The drawing area and its scrollbars
+
+ grid ${name}.mainframe.mainarea.sbleft -row 0 -column 0 -sticky ns
+ grid ${name}.mainframe.mainarea.sbbottom -row 1 -column 1 -sticky ew
+ grid $drawing -row 0 -column 1 -sticky news
+ grid ${name}.mainframe.mainarea.corner -row 1 -column 0 -sticky news
+
+ grid rowconfigure ${name}.mainframe.mainarea 0 -weight 1
+ grid columnconfigure ${name}.mainframe.mainarea 1 -weight 1
+
+ # The top menu and message bar
+
+ menubutton ${name}.menubar.filebutton -text File \
+ -menu ${name}.menubar.filebutton.filemenu
+ menubutton ${name}.menubar.editbutton -text Edit \
+ -menu ${name}.menubar.editbutton.editmenu
+ menubutton ${name}.menubar.textbutton -text Text \
+ -menu ${name}.menubar.textbutton.textmenu
+ menubutton ${name}.menubar.optionsbutton -text Options \
+ -menu ${name}.menubar.optionsbutton.optionsmenu
+ menubutton ${name}.menubar.windowbutton -text Window \
+ -menu ${name}.menubar.windowbutton.windowmenu
+ menubutton ${name}.menubar.netlistbutton -text Netlist \
+ -menu ${name}.menubar.netlistbutton.netlistmenu
+
+ grid ${name}.menubar.filebutton ${name}.menubar.editbutton \
+ ${name}.menubar.textbutton ${name}.menubar.optionsbutton \
+ ${name}.menubar.windowbutton ${name}.menubar.netlistbutton \
+ -ipadx 10 -sticky news
+
+ # The top message bar
+
+ label ${name}.message -text \
+ "Welcome to Xcircuit v${XCIRCUIT_VERSION} rev ${XCIRCUIT_REVISION}" \
+ -background beige -justify left -anchor w
+
+ grid ${name}.message -row 0 -column 1 -sticky news -ipadx 10
+
+ button ${name}.infobar.symb -text "Symbol" -bg gray30 -fg white
+ button ${name}.infobar.schem -text "Schematic" -bg red -fg white
+ button ${name}.infobar.mode -text "Wire Mode" -bg skyblue2 -fg gray20
+ label ${name}.infobar.message1 -text "Editing: Page 1" \
+ -background beige
+ label ${name}.infobar.message2 -text "Grid 1/6 in : Snap 1/12 in" \
+ -background beige -justify left -anchor w
+ pack ${name}.infobar.symb ${name}.infobar.schem ${name}.infobar.message1 \
+ ${name}.infobar.mode -side left -ipadx 6 -fill y
+ pack ${name}.infobar.message2 -ipadx 6 -expand true -fill both
+
+ #-------------------------------------------------
+ # Mouse hint window (if mousehints are enabled)
+ #-------------------------------------------------
+
+ if {$XCOps(mousehints) == 0} {
+ bind ${name}.infobar.mode <Button-1> {xcircuit::enable_mousehints}
+ } elseif {$XCOps(mousehints) == 1} {
+ xcircuit::mousehint_create ${name}
+ }
+
+ #-------------------------------------------------
+ # Create the menus, toolbar and associated tools
+ #-------------------------------------------------
+
+ xcircuit::makemenus $name
+ xcircuit::createtoolbar $name
+ xcircuit::arrangetoolbar $name
+ xcircuit::allcolorbuttons $name
+ xcircuit::allfontbuttons $name
+
+ #-----------------------------------------------------------------
+ # Add key and button bindings for XCircuit commands (standard actions)
+ # These can be overridden by binding to specific keys and/or buttons.
+ #-----------------------------------------------------------------
+
+ bind $drawing <ButtonPress> {standardaction %b down %s}
+ bind $drawing <ButtonRelease> {standardaction %b up %s}
+ bind $drawing <KeyPress> {standardaction %k down %s}
+ bind $drawing <KeyRelease> {standardaction %k up %s}
+
+ # Here are some extra key functions that come with the TCL wrapper
+
+ bind $drawing <Key-Next> {catch {page [expr {[page] + 1}]}}
+ bind $drawing <Key-Prior> {catch {page [expr {[page] - 1}]}}
+ bind $drawing <Control-Key-p> {xcircuit::prompteditparams}
+
+ xcircuit::keybind <Key-bracketleft> {if {[select get] == {}} \
+ {select here; element lower; deselect} else {element lower}; \
+ refresh} $drawing
+ xcircuit::keybind <Key-bracketright> {if {[select get] == {}} \
+ {select here; element raise; deselect} else {element raise}; \
+ refresh} $drawing
+
+ # Bind numbers 1-9 and 0 so that they call the Tcl "page" command,
+ # and so can take advantage of the tag callback to "pageupdate".
+
+ xcircuit::keybind <Key-1> {page 1} $drawing
+ xcircuit::keybind <Key-2> {page 2} $drawing
+ xcircuit::keybind <Key-3> {page 3} $drawing
+ xcircuit::keybind <Key-4> {page 4} $drawing
+ xcircuit::keybind <Key-5> {page 5} $drawing
+ xcircuit::keybind <Key-6> {page 6} $drawing
+ xcircuit::keybind <Key-7> {page 7} $drawing
+ xcircuit::keybind <Key-8> {page 8} $drawing
+ xcircuit::keybind <Key-9> {page 9} $drawing
+ xcircuit::keybind <Key-0> {page 10} $drawing
+
+ # These are supposed to disable the scroll wheel on the scrollbars. . .
+
+ bind ${name}.mainframe.mainarea.sbleft <Button-4> {}
+ bind ${name}.mainframe.mainarea.sbleft <Button-5> {}
+ bind ${name}.mainframe.mainarea.sbbottom <Button-4> {}
+ bind ${name}.mainframe.mainarea.sbbottom <Button-5> {}
+
+ if {$tcl_platform(platform) == "windows"} {
+ bind $name <FocusIn> \
+ "catch {config focus ${drawing} ; focus ${drawing}; \
+ set XCOps(focus) ${name} ; xcircuit::updatedialog}"
+ } else {
+ bind $drawing <Enter> {focus %W}
+ bind $name <FocusIn> "catch {config focus $drawing ; \
+ set XCOps(focus) ${name} ; xcircuit::updatedialog}"
+ }
+
+ # Window-specific variable defaults (variables associated with toggle
+ # and radio buttons, etc.). Note that we really should set these
+ # defaults for the first window only, and subsequent windows should
+ # inherit values from the first window.
+
+ set XCWinOps(${name},button1) None
+ set XCWinOps(${name},colorval) inherit
+ set XCWinOps(${name},jhoriz) left
+ set XCWinOps(${name},jvert) bottom
+ set XCWinOps(${name},linestyle) solid
+ set XCWinOps(${name},fillamount) 0
+ set XCWinOps(${name},opaque) false
+ set XCWinOps(${name},polyedittype) manhattan
+ set XCWinOps(${name},pathedittype) tangents
+ set XCWinOps(${name},showgrid) true
+ set XCWinOps(${name},showsnap) true
+ set XCWinOps(${name},showaxes) true
+ set XCWinOps(${name},showbbox) false
+ set XCWinOps(${name},fontfamily) Helvetica
+ set XCWinOps(${name},fontstyle) normal
+ set XCWinOps(${name},fontencoding) Standard
+ set XCWinOps(${name},fontlining) normal
+ set XCWinOps(${name},fontscript) normal
+ set XCWinOps(${name},gridstyle) "internal units"
+ set XCWinOps(${name},flipinvariant) true
+ set XCWinOps(${name},pinvisible) false
+ set XCWinOps(${name},showclipmasks) show
+ set XCWinOps(${name},latexmode) false
+ set XCWinOps(${name},colorscheme) normal
+ set XCWinOps(${name},editinplace) true
+ set XCWinOps(${name},pinpositions) invisible
+ set XCWinOps(${name},pinattach) false
+ set XCWinOps(${name},namespaces) false
+ set XCWinOps(${name},centerobject) true
+ set XCWinOps(${name},manhattandraw) false
+ set XCWinOps(${name},polyclosed) closed
+ set XCWinOps(${name},scaleinvariant) invariant
+ set XCWinOps(${name},endcaps) round
+ set XCWinOps(${name},bboxtype) false
+ set XCWinOps(${name},clipmask) false
+ set XCWinOps(${name},substringparam) false
+ set XCWinOps(${name},numericparam) false
+ set XCWinOps(${name},expressparam) false
+ set XCWinOps(${name},xposparam) false
+ set XCWinOps(${name},yposparam) false
+ set XCWinOps(${name},styleparam) false
+ set XCWinOps(${name},justparam) false
+ set XCWinOps(${name},startparam) false
+ set XCWinOps(${name},endparam) false
+ set XCWinOps(${name},radiusparam) false
+ set XCWinOps(${name},minorparam) false
+ set XCWinOps(${name},rotationparam) false
+ set XCWinOps(${name},scaleparam) false
+ set XCWinOps(${name},linewidthparam) false
+ set XCWinOps(${name},colorparam) false
+ set XCWinOps(${name},sel_lab) true
+ set XCWinOps(${name},sel_inst) true
+ set XCWinOps(${name},sel_poly) true
+ set XCWinOps(${name},sel_arc) true
+ set XCWinOps(${name},sel_spline) true
+ set XCWinOps(${name},sel_graphic) true
+ set XCWinOps(${name},sel_path) true
+ set XCWinOps(${name},labeltype) Text
+ set XCWinOps(${name},labelimage) img_t
+ set XCWinOps(${name},rotateamount) 15
+
+ #-----------------------------------------------------------------
+ # The "catch" statement here allows "i" and "I" to have other bindings for
+ # normal mode (e.g., "I" for "make info label") when nothing is selected.
+ #-----------------------------------------------------------------
+
+ xcircuit::keybind i {if {[catch {xcircuit::autoincr}]} \
+ {standardaction %k down %s}} $drawing
+ xcircuit::keybind I {if {[catch {xcircuit::autoincr -1}]} \
+ {standardaction %k down %s}} $drawing
+
+ #-----------------------------------------------------------------
+ # Function bindings for the mouse scroll wheel.
+ #-----------------------------------------------------------------
+
+ xcircuit::keybind <Button-4> { pan up 0.05 ; refresh} $drawing
+ xcircuit::keybind <Button-5> { pan down 0.05 ; refresh} $drawing
+ xcircuit::keybind <Shift-Button-4> { pan left 0.05 ; refresh} $drawing
+ xcircuit::keybind <Shift-Button-5> { pan right 0.05 ; refresh} $drawing
+
+ #-----------------------------------------------------------------
+ # Evaluate registered callback procedures
+ #-----------------------------------------------------------------
+
+ catch {eval $XCOps(callback)}
+ catch {eval $XCWinOps(${name}, callback)}
+}
+
+#----------------------------------------------------------------------
+# Delete a window.
+#----------------------------------------------------------------------
+
+proc xcircuit::closewindow {name} {
+ set winlist [config windownames]
+ if {[llength $winlist] > 1} {
+ if {[lsearch $winlist $name] != -1} {
+ config delete $name
+ set newwin [lindex [config windownames] 0]
+ destroy [winfo top $name]
+ config focus $newwin
+ }
+ } else {
+ quit
+ }
+}
+
+#----------------------------------------------------------------------
+# Create a new window, and set it to the same page as the current one.
+#----------------------------------------------------------------------
+
+proc xcircuit::forkwindow {} {
+ set suffix [llength [config windownames]]
+ set newname .xcircuit${suffix}
+ xcircuit::new_window $newname
+ config init $newname
+}
+
+#----------------------------------------------------------------------
+# Find the geometry position that centers a window on the cursor
+# position
+#----------------------------------------------------------------------
+
+proc xcircuit::centerwin {wname} {
+ set xmax [expr {[winfo screenwidth $wname] - 10}]
+ set ymax [expr {[winfo screenheight $wname] - 35}] ;# allow for titlebar height
+ set x [winfo pointerx $wname]
+ set y [winfo pointery $wname]
+ tkwait visibility $wname
+ set w [winfo width $wname]
+ set h [winfo height $wname]
+ set x [expr $x - $w / 2]
+ set y [expr $y - $h / 2]
+ if {$x < 10} {set x 10}
+ if {$y < 10} {set y 10}
+ if {[expr {$x + $w}] > $xmax} {set x [expr {$xmax - $w}]}
+ if {[expr {$y + $h}] > $ymax} {set y [expr {$ymax - $h}]}
+ if {$x > 0} {set x "+$x"}
+ if {$y > 0} {set y "+$y"}
+ wm geometry $wname $x$y
+}
+
+#----------------------------------------------------------------------
+# Message handling. Assumes that windows are named
+# 1) "pagename" where the page name is printed
+# 2) "coordinates" where the coordinates are printed
+# 3) "status" the general-purpose status and message line.
+#----------------------------------------------------------------------
+
+proc xcircuit::print {wname string} {
+ global XCOps
+ set window $XCOps(focus)
+
+ switch -glob ${wname} {
+ page* {
+ ${window}.infobar.message1 configure -text ${string}
+ }
+ coord* {
+ ${window}.message configure -text ${string}
+ }
+ mes* -
+ stat* {
+ ${window}.infobar.message2 configure -text ${string}
+ }
+ }
+}
+
+proc xcircuit::getinitstate {wname} {
+ if [winfo exists $wname] {
+ set wstate [wm state $wname]
+ } else {
+ set wstate "none"
+ }
+ return $wstate
+}
+
+#----------------------------------------------------------------------
+# Support procedures for tag callbacks
+#----------------------------------------------------------------------
+
+proc xcircuit::popupdialog {} {
+ set wstate [xcircuit::getinitstate .dialog]
+ xcircuit::removelists .dialog
+ wm deiconify .dialog
+ if {"$wstate" != "normal"} {centerwin .dialog}
+ raise .dialog
+ focus .dialog.textent.txt
+}
+
+proc xcircuit::popupfilelist {} {
+ set wstate [xcircuit::getinitstate .filelist]
+ xcircuit::removelists .filelist
+ wm deiconify .filelist
+ centerwin .filelist
+ raise .filelist
+ focus .filelist.textent.txt
+}
+
+#----------------------------------------------------------------------
+# A refined "page size" that keeps a lid on the numerical precision
+# out of Tcl. . .
+#----------------------------------------------------------------------
+
+proc xcircuit::getpagesize {} {
+ set slist [xcircuit::page size]
+ set coordstyle [lindex $slist 3]
+ if {$coordstyle == "cm"} {
+ # Round centimeter coords to the nearest 0.1
+ set xcm [lindex $slist 0]
+ set xcm [expr {round($xcm * 10.0) / 10.0}]
+ set slist [lreplace $slist 0 0 $xcm]
+ set ycm [lindex $slist 2]
+ set ycm [expr {round($ycm * 10.0) / 10.0}]
+ set slist [lreplace $slist 2 2 $ycm]
+ } elseif {$coordstyle == "in"} {
+ # Round inch coords to the nearest 1/8
+ set xin [lindex $slist 0]
+ set xin [expr {round($xin * 8.0) / 8.0}]
+ set slist [lreplace $slist 0 0 $xin]
+ set yin [lindex $slist 2]
+ set yin [expr {round($yin * 8.0) / 8.0}]
+ set slist [lreplace $slist 2 2 $yin]
+ }
+ return $slist
+}
+
+#----------------------------------------------------------------------
+# This procedure configures the sheet size according to the page
+# dimensions (if they match, within reason)
+#----------------------------------------------------------------------
+
+proc xcircuit::setsheetsize {} {
+ global XCOps
+
+ set slist [xcircuit::getpagesize]
+ set coordstyle [lindex $slist 3]
+ if {$coordstyle == "cm"} {
+ set xcm [lindex $slist 0]
+ set ycm [lindex $slist 2]
+
+ if {$xcm == 21.0 && $ycm == 29.7} {
+ set XCOps(sheetsize) a4
+ .output.textent.txtf.sizb configure -text "A4"
+ } elseif {$xcm == 29.7 && $ycm == 42.0} {
+ set XCOps(sheetsize) a3
+ .output.textent.txtf.sizb configure -text "A3"
+ } elseif {$xcm == 14.8 && $ycm == 18.4} {
+ set XCOps(sheetsize) a5
+ .output.textent.txtf.sizb configure -text "A5"
+ } elseif {$xcm == 25.7 && $ycm == 36.4} {
+ set XCOps(sheetsize) b4
+ .output.textent.txtf.sizb configure -text "B4"
+ } elseif {$xcm == 18.2 && $ycm == 25.7} {
+ set XCOps(sheetsize) b5
+ .output.textent.txtf.sizb configure -text "B5"
+ } else {
+ set XCOps(sheetsize) special
+ .output.textent.txtf.sizb configure -text "Special"
+ }
+ } elseif {$coordstyle == "in"} {
+ set xin [lindex $slist 0]
+ set yin [lindex $slist 2]
+
+ if {$xin == 8.5 && $yin == 11.0} {
+ set XCOps(sheetsize) letter
+ .output.textent.txtf.sizb configure -text Letter
+ } elseif {$xin == 8.5 && $yin == 14.0} {
+ set XCOps(sheetsize) legal
+ .output.textent.txtf.sizb configure -text Legal
+ } elseif {$xin == 5.5 && $yin == 8.5} {
+ set XCOps(sheetsize) statement
+ .output.textent.txtf.sizb configure -text Statement
+ } elseif {$xin == 11.0 && $yin == 17.0} {
+ set XCOps(sheetsize) tabloid
+ .output.textent.txtf.sizb configure -text Tabloid
+ } elseif {$xin == 17.0 && $yin == 11.0} {
+ set XCOps(sheetsize) ledger
+ .output.textent.txtf.sizb configure -text Ledger
+ } elseif {$xin == 8.5 && $yin == 13.0} {
+ set XCOps(sheetsize) folio
+ .output.textent.txtf.sizb configure -text Folio
+ } elseif {$xin == 10.0 && $yin == 14.0} {
+ set XCOps(sheetsize) tenfourteen
+ .output.textent.txtf.sizb configure -text 10x14
+ } elseif {$xin == 7.5 && $yin == 10.0} {
+ set XCOps(sheetsize) executive
+ .output.textent.txtf.sizb configure -text Executive
+ } elseif {$xin == 17.0 && $yin == 22.0} {
+ set XCOps(sheetsize) ansic
+ .output.textent.txtf.sizb configure -text "ANSI C"
+ } elseif {$xin == 22.0 && $yin == 34.0} {
+ set XCOps(sheetsize) ansid
+ .output.textent.txtf.sizb configure -text "ANSI D"
+ } elseif {$xin == 34.0 && $yin == 44.0} {
+ set XCOps(sheetsize) ansie
+ .output.textent.txtf.sizb configure -text "ANSI E"
+ } else {
+ set XCOps(sheetsize) special
+ .output.textent.txtf.sizb configure -text "Special"
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+# This procedure configures the output properties window according to
+# the page mode (full or encapsulated)
+#----------------------------------------------------------------------
+
+proc xcircuit::setpstype {mode} {
+ global XCOps
+ switch -- $mode {
+ {eps} { .output.textent.butp configure -text "Embedded (EPS)"
+ grid remove .output.textent.but7
+ grid remove .output.textent.butf
+ grid remove .output.textent.txtf
+ }
+ {full} {.output.textent.butp configure -text "Full Page"
+ grid .output.textent.but7 -row 6 -column 3 -pady 5 -ipadx 10
+ grid .output.textent.butf -row 5 -column 2 -padx 10
+ grid .output.textent.txtf -row 6 -column 2 -sticky ew -padx 10
+ }
+ }
+ set XCOps(pstype) $mode
+ xcircuit::page encapsulation $mode
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::dolinks {} {
+ global XCOps
+ set ilinks [xcircuit::page links independent]
+ if {$ilinks > 1} {
+ set XCOps(imultiple) 1
+ } else {
+ set XCOps(imultiple) 0
+ }
+ if {$ilinks == 1} { set plural ""} else { set plural "s"}
+ .output.title.imulti configure -text "$ilinks schematic$plural"
+
+ if {$XCOps(dmultiple) == 1} {
+ set dlinks [xcircuit::page links dependent]
+ } else {
+ set dlinks 0
+ }
+ if {$dlinks == 1} { set plural ""} else { set plural "s"}
+ .output.title.dmulti configure -text "$dlinks subcircuit$plural"
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::setlinksmenu {} {
+ set m .output.textent.butl.linksmenu
+ $m delete 0 end
+ $m add radio -label "None" -variable XCOps(links) -command \
+ {.output.textent.butl configure -text None ; \
+ xcircuit::page filename {}}
+ if {![catch {set plist [xcircuit::page list]}]} {
+ set fnames {}
+ foreach p $plist {
+ set pfile [xcircuit::page $p filename]
+ if {"$pfile" != ""} {
+ lappend fnames $pfile
+ }
+ }
+ foreach f [lsort -uniq $fnames] {
+ $m add radio -label $f -variable XCOps(links) \
+ -command ".output.textent.butl configure -text $f ; \
+ xcircuit::page filename $f"
+ }
+ }
+ .output.textent.butl configure -text "(change)"
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::pageupdate { {subcommand "none"} } {
+ global XCOps
+ if {[info level] <= 1} {
+ switch -- $subcommand {
+ save {
+ .output.bbar.okay configure -text "Done"
+ .output.bbar.okay configure -command {wm withdraw .output}
+ }
+ make {
+ xcircuit::newpagebutton [xcircuit::page label]
+ }
+ default {
+ .output.title.field configure -text \
+ "PostScript output properties (Page [xcircuit::page])"
+ set fname [xcircuit::page filename]
+ .output.textent.but1 configure -text Apply
+ .output.textent.but2 configure -text Apply
+ .output.textent.but3 configure -text Apply
+ .output.textent.but4 configure -text Apply
+ .output.textent.but5 configure -text Apply
+ .output.textent.but7 configure -text Apply
+ .output.textent.txt1 delete 0 end
+ .output.textent.txt1 insert 0 $fname
+ .output.textent.txt2 delete 0 end
+ .output.textent.txt2 insert 0 [xcircuit::page label]
+ .output.textent.txt3 delete 0 end
+ set stext [format "%g" [xcircuit::page scale]]
+ .output.textent.txt3 insert 0 $stext
+ .output.textent.txt4 delete 0 end
+ set wtext [format "%g" [xcircuit::page width]]
+ .output.textent.txt4 insert 0 $wtext
+ .output.textent.txt4 insert end " "
+ .output.textent.txt4 insert end [xcircuit::coordstyle get]
+ .output.textent.txt5 delete 0 end
+ set htext [format "%g" [xcircuit::page height]]
+ .output.textent.txt5 insert 0 $htext
+ .output.textent.txt5 insert end " "
+ .output.textent.txt5 insert end [xcircuit::coordstyle get]
+ .output.textent.txtf.txtp delete 0 end
+ .output.textent.txtf.txtp insert 0 [xcircuit::getpagesize]
+ xcircuit::setpstype [xcircuit::page encapsulation]
+ set XCOps(orient) [xcircuit::page orientation]
+ if {$XCOps(orient) == 0} {
+ .output.textent.buto configure -text Portrait
+ } else {
+ .output.textent.buto configure -text Landscape
+ }
+ xcircuit::dolinks
+ xcircuit::setlinksmenu
+ xcircuit::setsheetsize
+
+ set XCOps(autofit) [xcircuit::page fit]
+ if {[string match *.* $fname] == 0} {append fname .ps}
+ if {[glob -nocomplain ${fname}] == {}} {
+ .output.bbar.okay configure -text "Write File"
+ } else {
+ .output.bbar.okay configure -text "Overwrite File"
+ }
+ .output.bbar.okay configure -command \
+ {.output.textent.but1 invoke; \
+ .output.textent.but2 invoke; \
+ if {$XCOps(autofit)} {xcircuit::page fit true}; \
+ if {$XCOps(dmultiple) == 1} {xcircuit::page save} else { \
+ xcircuit::page saveonly }; wm withdraw .output}
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+# Update the GUI based on the schematic class of the current page
+# This is called internally from the xcircuit code and the function
+# must be defined, even if it is a null proc.
+#----------------------------------------------------------------------
+
+proc xcircuit::setsymschem {} {
+ global XCOps
+ set window $XCOps(focus)
+
+ if {[info level] <= 1} {
+ set schemtype [xcircuit::schematic type]
+ set symschem [xcircuit::schematic get]
+ set m ${window}.menubar.netlistbutton.netlistmenu
+ switch -- $schemtype {
+ primary -
+ secondary -
+ schematic {
+ ${window}.infobar.schem configure -background red -foreground white
+ if {$symschem == {}} {
+ ${window}.infobar.symb configure -background gray70 \
+ -foreground gray40
+ $m entryconfigure 5 -label "Make Matching Symbol" \
+ -command {xcircuit::promptmakesymbol [page label]}
+ $m entryconfigure 6 -label "Associate With Symbol" \
+ -command {xcircuit::symbol associate}
+ } else {
+ ${window}.infobar.symb configure -background white -foreground black
+ $m entryconfigure 5 -label "Go To Symbol" \
+ -command {xcircuit::symbol go}
+ $m entryconfigure 6 -label "Disassociate Symbol" \
+ -command {xcircuit::symbol disassociate}
+ }
+ }
+ symbol -
+ fundamental -
+ trivial {
+ ${window}.infobar.symb configure -foreground white
+ if {$symschem == {}} {
+ ${window}.infobar.schem configure -background gray70 -foreground \
+ gray40
+ $m entryconfigure 5 -label "Make Matching Schematic" \
+ -command {xcircuit::schematic make}
+ $m entryconfigure 6 -label "Associate With Schematic" \
+ -command {xcircuit::schematic associate}
+ } else {
+ ${window}.infobar.schem configure -background white -foreground black
+ $m entryconfigure 5 -label "Go To Schematic" \
+ -command {xcircuit::schematic go}
+ $m entryconfigure 6 -label "Disassociate Schematic" \
+ -command {xcircuit::schematic disassociate}
+ }
+ }
+ }
+ switch -- $schemtype {
+ trivial {
+ ${window}.infobar.symb configure -background red
+ }
+ fundamental {
+ ${window}.infobar.symb configure -background green4 ;# bboxcolor
+ }
+ symbol {
+ ${window}.infobar.symb configure -background blue2
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+# Set the coordinate style to inches from cm and vice versa.
+# This routine avoids switching from fractional to decimal inches
+# and vice versa if we are already in one of the two inches modes.
+#
+# with no argument, or argument "get", returns the "short" name
+# ("cm" or "in") of the style.
+#----------------------------------------------------------------------
+
+proc xcircuit::coordstyle { { mode get } } {
+ global XCOps XCWinOps
+ set curstyle [xcircuit::config coordstyle]
+ switch -- $mode {
+ inches {
+ switch -- $curstyle {
+ centimeters {
+ xcircuit::config coordstyle "decimal inches"
+ xcircuit::pageupdate
+ }
+ }
+ }
+ centimeters -
+ cm {
+ switch -- $curstyle {
+ centimeters {
+ }
+ default {
+ xcircuit::config coordstyle "centimeters"
+ xcircuit::pageupdate
+ }
+ }
+ }
+ get {
+ switch -- $curstyle {
+ centimeters {
+ return "cm"
+ }
+ default {
+ return "in"
+ }
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::raiseconsole {} {
+ global XCOps
+ set window $XCOps(focus)
+
+ xcircuit::consoleup
+ xcircuit::consoleontop
+ set cidx [${window}.menubar.filebutton.filemenu index *Console]
+ ${window}.menubar.filebutton.filemenu entryconfigure \
+ $cidx -label "No Console" -command {xcircuit::lowerconsole}
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::lowerconsole {} {
+ global XCOps
+ set window $XCOps(focus)
+
+ xcircuit::consoledown
+ set cidx [${window}.menubar.filebutton.filemenu index *Console]
+ ${window}.menubar.filebutton.filemenu entryconfigure \
+ $cidx -label "Tcl Console" -command {xcircuit::raiseconsole}
+}
+
+#----------------------------------------------------------------------
+# Command tags---these let the command-line entry functions update the
+# Tk windows, so that the Tk window structure doesn't need to be hard-
+# coded into the source.
+#----------------------------------------------------------------------
+
+xcircuit::tag page {xcircuit::pageupdate %1 ; xcircuit::updateparams}
+xcircuit::tag promptsavepage {xcircuit::pageupdate ;
+ set wstate [xcircuit::getinitstate .output] ; wm deiconify .output ;
+ if {"$wstate" != "normal"} {xcircuit::centerwin .output} ; raise .output}
+xcircuit::tag loadfont {xcircuit::newfontbutton %r}
+xcircuit::tag color { if {"%1" == "set"} {
+ set XCWinOps($XCOps(focus),colorval) %2; set iname img_co;
+ if {"%2" != "inherit"} {append iname l%2} ;
+ $XCOps(focus).mainframe.toolbar.bco configure -image $iname} }
+xcircuit::tag border {if {%# == 2} {
+ switch -- %1 {
+ dashed { set XCWinOps($XCOps(focus),linestyle) dashed}
+ dotted { set XCWinOps($XCOps(focus),linestyle) dotted}
+ unbordered { set XCWinOps($XCOps(focus),linestyle) unbordered}
+ solid { set XCWinOps($XCOps(focus),linestyle) solid}
+ square { set XCWinOps($XCOps(focus),endcaps) square}
+ round { set XCWinOps($XCOps(focus),endcaps) round}
+ closed { set XCWinOps($XCOps(focus),polyclosed) closed}
+ unclosed { set XCWinOps($XCOps(focus),polyclosed) unclosed}
+ }} elseif {%# == 3} {
+ switch -- %1 {
+ bbox { set XCWinOps($XCOps(focus),bboxtype) %2}
+ clipmask { set XCWinOps($XCOps(focus),clipmask) %2}
+ }}}
+xcircuit::tag fill { foreach i %N { switch -- "$i" {
+ opaque { set XCWinOps($XCOps(focus),opaque) true }
+ transparent { set XCWinOps($XCOps(focus),opaque) false } 0 - unfilled
+ {set XCWinOps($XCOps(focus),fillamount) 0;
+ $XCOps(focus).mainframe.toolbar.bfi configure -image img_fi}
+ solid {set XCWinOps($XCOps(focus),fillamount) 100;
+ $XCOps(focus).mainframe.toolbar.bfi configure -image img_stip100}
+ default {set XCWinOps($XCOps(focus),fillamount) $i;
+ $XCOps(focus).mainframe.toolbar.bfi configure -image img_stip$i} } } }
+
+xcircuit::tag select {if {%N > 1} {xcircuit::updateparams; xcircuit::updatedialog}}
+xcircuit::tag unselect {xcircuit::updateparams; xcircuit::updatedialog}
+xcircuit::tag schematic {xcircuit::setsymschem}
+xcircuit::tag symbol {xcircuit::setsymschem}
+
+xcircuit::tag parameter { if {"%1" == "make"} {set cond true} else {set cond false}
+ switch %1 {
+ set -
+ forget -
+ delete {xcircuit::updateparams}
+ make -
+ replace {switch -- "%2" {
+ "x position" {set XCWinOps($XCOps(focus),xposparam) $cond}
+ "y position" {set XCWinOps($XCOps(focus),yposparam) $cond}
+ style {set XCWinOps($XCOps(focus),styleparam) $cond}
+ "start angle" {set XCWinOps($XCOps(focus),startparam) $cond}
+ "end angle" {set XCWinOps($XCOps(focus),endparam) $cond}
+ justification {set XCWinOps($XCOps(focus),justparam) $cond}
+ radius {set XCWinOps($XCOps(focus),radiusparam) $cond}
+ "minor axis" {set XCWinOps($XCOps(focus),minorparam) $cond}
+ rotation {set XCWinOps($XCOps(focus),rotationparam) $cond}
+ scale {set XCWinOps($XCOps(focus),scaleparam) $cond}
+ linewidth {set XCWinOps($XCOps(focus),linewidthparam) $cond}
+ color {set XCWinOps($XCOps(focus),colorparam) $cond}
+ default {xcircuit::updateparams}
+ }}
+ default {if {%# == 4} {xcircuit::updateparams}}
+ }}
+
+xcircuit::tag config {if {%# == 3} {
+ switch -- %1 {
+ colorscheme {set XCWinOps($XCOps(focus),colorscheme) [config colorscheme];
+ refresh}
+ bbox {set XCWinOps($XCOps(focus),showbbox) [config bbox]}
+ editinplace {set XCWinOps($XCOps(focus),editinplace) [config editinplace]}
+ pinpositions {set XCWinOps($XCOps(focus),pinpositions) [config pinpositions]}
+ pinattach {set XCWinOps($XCOps(focus),pinattach) [config pinattach]}
+ technologies {set XCWinOps($XCOps(focus),namespaces) [config technologies]}
+ hold {set XCOps(hold) [config hold]}
+ grid {catch {set XCWinOps($XCOps(focus),showgrid) [config grid]}}
+ snap {catch {set XCWinOps($XCOps(focus),showsnap) [config snap]}}
+ axes {set XCWinOps($XCOps(focus),showaxes) [config axes]}
+ centering {set XCWinOps($XCOps(focus),centerobject) [config centering]}
+ manhattan {set XCWinOps($XCOps(focus),manhattandraw) [config manhattan]}
+ coordstyle {set XCWinOps($XCOps(focus),gridstyle) [config coordstyle]}
+ boxedit {set XCWinOps($XCOps(focus),polyedittype) [config boxedit]}
+ pathedit {set XCWinOps($XCOps(focus),pathedittype) [config pathedit]}
+ technologies {set XCWinOps($XCOps(focus),showtech) [config technologies]}
+ }} elseif {(%# == 4) && ("%1" == "filter")} {
+ set XCWinOps($XCOps(focus),sel_%2) [config filter %2]
+ }}
+
+xcircuit::tag label {if {%# == 3} {
+ switch -- %1 {
+ encoding {
+ set XCWinOps($XCOps(focus),fontencoding) %2
+ xcircuit::newencodingbutton %2
+ }
+ family {if {"%2" != "-all"} {set XCWinOps($XCOps(focus),fontfamily) %2}}
+ style {set XCWinOps($XCOps(focus),fontstyle) %2}
+ justify {
+ switch -- %2 {
+ top -
+ bottom -
+ middle {set XCWinOps($XCOps(focus),jvert) %2}
+ default {set XCWinOps($XCOps(focus),jhoriz) %2}
+ }
+ }
+ flipinvariant {set XCWinOps($XCOps(focus),flipinvariant) %2}
+ visible {set XCWinOps($XCOps(focus),pinvisible) %2}
+ latex {set XCWinOps($XCOps(focus),latexmode) %2}
+ }} elseif {(%# == 4) && ("%1" == "justify")} {
+ switch -- %2 {
+ top -
+ bottom -
+ middle {set XCWinOps($XCOps(focus),jvert) %2 ;
+ set XCWinOps($XCOps(focus),jhoriz) %3}
+ default {set XCWinOps($XCOps(focus),jhoriz) %2 ;
+ set XCWinOps($XCOps(focus),jvert) %3}
+ }
+ }}
+
+#------------------------------
+# Create the file-list window
+#------------------------------
+
+# First, set the variables associated with toggle and radio buttons
+set XCOps(filter) 1
+
+toplevel .filelist -bg beige
+wm title .filelist "File List Window"
+wm group .filelist .
+wm protocol .filelist WM_DELETE_WINDOW {wm withdraw .filelist}
+wm withdraw .filelist
+
+frame .filelist.listwin
+frame .filelist.textent -bg beige
+frame .filelist.bbar -bg beige
+
+pack .filelist.listwin -side top -padx 20 -pady 7 -expand true -fill both
+pack .filelist.textent -side top -padx 20 -pady 7 -fill x
+pack .filelist.bbar -side bottom -padx 20 -pady 7 -fill x
+
+simple .filelist.listwin.win -bg white
+simple .filelist.listwin.sb -width 13 -bg beige
+
+grid .filelist.listwin.win -row 0 -column 0 -sticky news -padx 1 -pady 1
+grid .filelist.listwin.sb -row 0 -column 1 -sticky ns -padx 1 -pady 1
+
+grid columnconfigure .filelist.listwin 0 -weight 1 -minsize 100
+grid rowconfigure .filelist.listwin 0 -weight 1 -minsize 100
+
+frame .filelist.textent.title -bg beige
+pack .filelist.textent.title -side top -fill x
+
+label .filelist.textent.title.field -text "Select file to load:" -bg beige
+label .filelist.textent.title.chklabel -text "Filter" -bg beige
+checkbutton .filelist.textent.title.filter -bg beige -variable XCOps(filter) \
+ -command {event generate .filelist.listwin.win <ButtonPress> -button 3 ; \
+ event generate .filelist.listwin.win <ButtonRelease> -button 3}
+
+entry .filelist.textent.txt -bg white -relief sunken -width 50
+
+pack .filelist.textent.title.filter -side right
+pack .filelist.textent.title.chklabel -side right
+pack .filelist.textent.title.field -side left
+pack .filelist.textent.txt -side bottom -fill x -expand true
+
+button .filelist.bbar.okay -text Okay -bg beige
+button .filelist.bbar.cancel -text Cancel -bg beige -command {wm withdraw .filelist}
+
+pack .filelist.bbar.okay -side left -ipadx 10
+pack .filelist.bbar.cancel -side right -ipadx 10
+
+# Allow <return> to update or accept entry
+bind .filelist.textent.txt <Return> \
+ {event generate .filelist.listwin.win <ButtonPress> -button 2 ; \
+ event generate .filelist.listwin.win <ButtonRelease> -button 2}
+
+#--------------------------------------
+# Create the output generating window
+#--------------------------------------
+
+# First, set the variables associated with toggle and radio buttons
+set XCOps(autofit) 0
+set XCOps(imultiple) 0
+set XCOps(dmultiple) 0 ;# don't save subcircuits with different filenames
+if {[catch {set XCOps(technology)}]} {set XCOps(technology) "(user)"}
+if {[catch {set XCOps(library)}]} {set XCOps(library) "User Library"}
+
+toplevel .output -bg beige
+wm title .output "PostScript Output Properties"
+wm group .output .
+wm protocol .output WM_DELETE_WINDOW {wm withdraw .output}
+wm withdraw .output
+
+frame .output.title -bg beige
+frame .output.textent -bg beige
+frame .output.bbar -bg beige
+
+pack .output.title -side top -padx 20 -pady 7 -fill x
+pack .output.textent -side top -padx 20 -pady 7 -fill x
+pack .output.bbar -side bottom -padx 20 -pady 7 -fill x
+
+label .output.title.field -text "PostScript output properties (Page 1):" -bg tan
+checkbutton .output.title.imulti -text "1 schematic" -bg beige \
+ -variable XCOps(imultiple) \
+ -command {xcircuit::dolinks ; \
+ if {$XCOps(imultiple) == 1} {.output.textent.txt1 \
+ delete 0 end; .output.textent.but1 configure -text Apply; xcircuit::page \
+ filename {}; focus .output.textent.txt1 ; xcircuit::dolinks }}
+checkbutton .output.title.dmulti -text "0 subcircuits" -bg beige \
+ -variable XCOps(dmultiple) \
+ -command {xcircuit::dolinks ; .output.textent.but1 configure -text Apply; \
+ if {$XCOps(dmultiple) == 1} {xcircuit::page filename {}; \
+ .output.textent.txt1 delete 0 end; focus .output.textent.txt1 }; \
+ xcircuit::dolinks }
+
+pack .output.title.dmulti -side right -padx 5
+pack .output.title.imulti -side right -padx 5
+
+pack .output.title.field -side left
+
+label .output.textent.lab1 -text "Filename:" -bg beige
+label .output.textent.lab2 -text "Page label:" -bg beige
+label .output.textent.lab3 -text "Scale:" -bg beige
+label .output.textent.lab4 -text "Width:" -bg beige
+label .output.textent.lab5 -text "Height:" -bg beige
+label .output.textent.lab6 -text "Orientation:" -bg beige
+label .output.textent.lab7 -text "Mode:" -bg beige
+label .output.textent.lab8 -text "Link to:" -bg beige
+
+entry .output.textent.txt1 -bg white -relief sunken -width 20
+entry .output.textent.txt2 -bg white -relief sunken -width 20
+entry .output.textent.txt3 -bg white -relief sunken -width 20
+entry .output.textent.txt4 -bg white -relief sunken -width 20
+entry .output.textent.txt5 -bg white -relief sunken -width 20
+
+menubutton .output.textent.buto -text Portrait -bg beige \
+ -menu .output.textent.buto.orientmenu
+menubutton .output.textent.butp -text "Embedded (EPS)" -bg beige \
+ -menu .output.textent.butp.psmenu
+menubutton .output.textent.butl -text "(change)" -bg beige \
+ -menu .output.textent.butl.linksmenu
+
+checkbutton .output.textent.butf -text "Auto-fit" -bg beige \
+ -variable XCOps(autofit) -onvalue true -offvalue false \
+ -command {xcircuit::page fit $XCOps(autofit)}
+frame .output.textent.txtf -bg beige
+menubutton .output.textent.txtf.sizb -text "Sizes" -bg beige \
+ -menu .output.textent.txtf.sizb.sizemenu
+entry .output.textent.txtf.txtp -bg white -relief sunken -width 14
+
+pack .output.textent.txtf.txtp -side left -fill y
+pack .output.textent.txtf.sizb -side left
+
+button .output.textent.but1 -text Apply -bg beige \
+ -command {xcircuit::page filename [.output.textent.txt1 get]
+ if {[llength [xcircuit::page label]] > 1} {
+ xcircuit::page label [file root [.output.textent.txt1 get]]};\
+ .output.textent.but1 configure -text Okay}
+button .output.textent.but2 -text Apply -bg beige \
+ -command {xcircuit::page label [.output.textent.txt2 get];\
+ .output.textent.but2 configure -text Okay}
+button .output.textent.but3 -text Apply -bg beige \
+ -command {xcircuit::page scale [.output.textent.txt3 get];\
+ .output.textent.but3 configure -text Okay}
+button .output.textent.but4 -text Apply -bg beige \
+ -command {xcircuit::page width [.output.textent.txt4 get];\
+ .output.textent.but4 configure -text Okay}
+button .output.textent.but5 -text Apply -bg beige \
+ -command {xcircuit::page height [.output.textent.txt5 get];\
+ .output.textent.but5 configure -text Okay}
+button .output.textent.but7 -text Apply -bg beige \
+ -command {xcircuit::page size [.output.textent.txtf.txtp get];\
+ .output.textent.but7 configure -text Okay}
+
+bind .output.textent.txt1 <Return> {.output.textent.but1 invoke}
+bind .output.textent.txt2 <Return> {.output.textent.but2 invoke}
+bind .output.textent.txt3 <Return> {.output.textent.but3 invoke}
+bind .output.textent.txt4 <Return> {.output.textent.but4 invoke}
+bind .output.textent.txt5 <Return> {.output.textent.but5 invoke}
+
+grid .output.textent.lab1 -row 0 -column 0 -sticky w
+grid .output.textent.lab2 -row 1 -column 0 -sticky w
+grid .output.textent.lab3 -row 2 -column 0 -sticky w
+grid .output.textent.lab4 -row 3 -column 0 -sticky w
+grid .output.textent.lab5 -row 4 -column 0 -sticky w
+grid .output.textent.lab6 -row 5 -column 0 -sticky w
+grid .output.textent.lab7 -row 6 -column 0 -sticky w
+grid .output.textent.lab8 -row 7 -column 0 -sticky w
+
+grid .output.textent.txt1 -row 0 -column 1 -columnspan 2 -sticky ew -padx 10
+grid .output.textent.txt2 -row 1 -column 1 -columnspan 2 -sticky ew -padx 10
+grid .output.textent.txt3 -row 2 -column 1 -columnspan 2 -sticky ew -padx 10
+grid .output.textent.txt4 -row 3 -column 1 -columnspan 2 -sticky ew -padx 10
+grid .output.textent.txt5 -row 4 -column 1 -columnspan 2 -sticky ew -padx 10
+grid .output.textent.buto -row 5 -column 1 -sticky w -padx 10
+grid .output.textent.butp -row 6 -column 1 -sticky w -padx 10
+grid .output.textent.butl -row 7 -column 1 -sticky w -padx 10
+
+grid .output.textent.but1 -row 0 -column 3 -pady 5 -ipadx 10
+grid .output.textent.but2 -row 1 -column 3 -pady 5 -ipadx 10
+grid .output.textent.but3 -row 2 -column 3 -pady 5 -ipadx 10
+grid .output.textent.but4 -row 3 -column 3 -pady 5 -ipadx 10
+grid .output.textent.but5 -row 4 -column 3 -pady 5 -ipadx 10
+
+grid columnconfigure .output.textent 2 -weight 1
+
+button .output.bbar.okay -text Okay -bg beige -command {xcircuit::page save; \
+ wm withdraw .output}
+button .output.bbar.cancel -text Cancel -bg beige -command {wm withdraw .output}
+
+# Setup simple choice menus for page type and orientation
+# First, set the variables associated with the radio buttons. . .
+set XCOps(orient) 0
+set XCOps(pstype) eps
+
+set m [menu .output.textent.buto.orientmenu -tearoff 0]
+$m add radio -label "Portrait" -variable XCOps(orient) -value 0 -command \
+ {.output.textent.buto configure -text Portrait ; \
+ xcircuit::page orientation 0}
+$m add radio -label "Landscape" -variable XCOps(orient) -value 90 -command \
+ {.output.textent.buto configure -text Landscape ; \
+ xcircuit::page orientation 90}
+
+set m [menu .output.textent.butp.psmenu -tearoff 0]
+$m add radio -label "Embedded (EPS)" -variable XCOps(pstype) -value eps -command \
+ {xcircuit::setpstype eps}
+$m add radio -label "Full Page" -variable XCOps(pstype) -value full -command \
+ {xcircuit::setpstype full}
+
+menu .output.textent.butl.linksmenu -tearoff 0
+xcircuit::setlinksmenu
+
+pack .output.bbar.okay -side left -ipadx 10
+pack .output.bbar.cancel -side right -ipadx 10
+
+set m [menu .output.textent.txtf.sizb.sizemenu -tearoff 0]
+$m add radio -label "Letter (ANSI A)" -variable XCOps(sheetsize) \
+ -value letter -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "8.5 x 11.0 in"}
+$m add radio -label "Legal" -variable XCOps(sheetsize) -value legal -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "8.5 x 14.0 in"}
+$m add radio -label "Statement" -variable XCOps(sheetsize) -value statement \
+ -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "5.5 x 8.5 in"}
+$m add radio -label "Tabloid (ANSI B)" -variable XCOps(sheetsize) \
+ -value tabloid -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "11.0 x 17.0 in"}
+$m add radio -label "Ledger" -variable XCOps(sheetsize) -value ledger -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "17.0 x 11.0 in"}
+$m add radio -label "Folio" -variable XCOps(sheetsize) -value folio -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "8.5 x 13.0 in"}
+$m add radio -label "Quarto" -variable XCOps(sheetsize) -value quarto -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "8.472 x 10.833 in"}
+$m add radio -label "10x14" -variable XCOps(sheetsize) -value tenfourteen -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "10.0 x 14.0 in"}
+$m add radio -label "Executive" -variable XCOps(sheetsize) -value executive -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "7.5 x 10.0 in"}
+$m add radio -label "ANSI C" -variable XCOps(sheetsize) -value ansic -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "17.0 x 22.0 in"}
+$m add radio -label "ANSI D" -variable XCOps(sheetsize) -value ansid -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "22.0 x 34.0 in"}
+$m add radio -label "ANSI E" -variable XCOps(sheetsize) -value ansie -command \
+ { xcircuit::coordstyle inches; xcircuit::page size "34.0 x 44.0 in"}
+$m add radio -label "A3" -variable XCOps(sheetsize) -value a3 -command \
+ { xcircuit::coordstyle centimeters; xcircuit::page size "29.7 x 42.0 cm"}
+$m add radio -label "A4" -variable XCOps(sheetsize) -value a4 -command \
+ { xcircuit::coordstyle centimeters; xcircuit::page size "21.0 x 29.7 cm"}
+$m add radio -label "A5" -variable XCOps(sheetsize) -value a5 -command \
+ { xcircuit::coordstyle centimeters; xcircuit::page size "14.82 x 18.43 cm"}
+$m add radio -label "B4" -variable XCOps(sheetsize) -value b4 -command \
+ { xcircuit::coordstyle centimeters; xcircuit::page size "25.7 x 36.4 cm"}
+$m add radio -label "B5" -variable XCOps(sheetsize) -value b5 -command \
+ { xcircuit::coordstyle centimeters; xcircuit::page size "18.2 x 25.7 cm"}
+$m add radio -label "Special" -variable XCOps(sheetsize) -value special}
+
+#-----------------------------------------------------------------
+# Clear the selection listbox. Create it if it does not exist.
+#-----------------------------------------------------------------
+
+proc xcircuit::make_parameter_listbox {} {
+ if {[catch {wm state .parameter}]} {
+ toplevel .parameter -bg beige
+ wm group .parameter .
+ wm withdraw .parameter
+
+ label .parameter.title -text "Parameters" -bg beige
+ label .parameter.keytitle -text "Key" -bg beige
+ label .parameter.valtitle -text "Value" -bg beige
+
+ listbox .parameter.keylist -bg white
+ listbox .parameter.vallist -bg white
+ listbox .parameter.parvals -bg white
+
+ button .parameter.dismiss -text "Dismiss" -bg beige \
+ -command {wm withdraw .parameter}
+
+ menubutton .parameter.delete -text "Delete..." -bg beige \
+ -menu .parameter.delete.deleteparam
+ menu .parameter.delete.deleteparam -tearoff 0
+
+ menubutton .parameter.create -text "New..." -bg beige \
+ -menu .parameter.create.newparam
+ menu .parameter.create.newparam -tearoff 0
+ .parameter.create.newparam add command -label "Substring" -command \
+ "xcircuit::promptmakeparam substring"
+ .parameter.create.newparam add command -label "Numeric" -command \
+ "xcircuit::promptmakeparam numeric"
+ .parameter.create.newparam add command -label "Expression" -command \
+ "xcircuit::promptmakeparam expression"
+
+ labelframe .parameter.valedit -text "Edit value" -bg beige
+ entry .parameter.valedit.entry -textvariable new_paramval -bg white
+ button .parameter.valedit.apply -text "Apply" -bg beige
+
+ pack .parameter.valedit.entry -side left -fill x -expand true -padx 2
+ pack .parameter.valedit.apply -side top
+
+ grid .parameter.title -row 0 -column 0 -columnspan 2 -sticky news
+ grid .parameter.keytitle -row 1 -column 0 -sticky news
+ grid .parameter.keylist -row 2 -column 0 -sticky news
+ grid .parameter.valtitle -row 1 -column 1 -sticky news
+ grid .parameter.vallist -row 2 -column 1 -sticky news
+ grid .parameter.parvals -row 2 -column 1 -sticky news
+
+ grid .parameter.valedit -row 3 -column 0 -columnspan 2 -padx 2 \
+ -pady 2 -sticky ew
+
+ grid .parameter.create -row 4 -column 1 -sticky ns
+ grid .parameter.delete -row 4 -column 0 -sticky ns
+ grid .parameter.dismiss -row 5 -column 0 -columnspan 2 -sticky ns
+
+ grid rowconfigure .parameter 2 -weight 1
+ grid columnconfigure .parameter 0 -weight 1
+ grid columnconfigure .parameter 1 -weight 2
+
+ raise .parameter.vallist
+
+ bind .parameter <Escape> {wm withdraw .parameter}
+ bind .parameter.valedit.entry <Return> {.parameter.valedit.apply invoke}
+ }
+}
+
+# Update the dialog box, if it has been left visible
+# (Corrected 2/4/12: Don't delete contents except in these specific cases!)
+
+proc xcircuit::updatedialog {} {
+ global XCOps
+ if {[xcircuit::getinitstate .dialog] == "normal"} {
+ switch -- $XCOps(dialog) {
+ linewidth {
+ set btext [format "%g" [lindex [xcircuit::border get] 0]]
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $btext
+ }
+ textscale {
+ set cscale [xcircuit::label scale]
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $cscale
+ }
+ elementscale {
+ set selects [xcircuit::select]
+ if {$selects > 0} {
+ set cscale [xcircuit::element scale]
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $cscale
+ }
+ }
+ }
+ }
+}
+
+proc xcircuit::makedialogline {dframe textline} {
+ if {[catch {frame .dialog.${dframe} -bg beige}]} {
+ .dialog.${dframe}.title.field configure -text ${textline}
+ } else {
+ pack .dialog.${dframe} -side top -padx 20 -pady 7 -fill x
+
+ frame .dialog.${dframe}.title -bg beige
+ entry .dialog.${dframe}.txt -bg white -relief sunken -width 50
+
+ pack .dialog.${dframe}.title -side top -fill x
+ pack .dialog.${dframe}.txt -side bottom -fill x -expand true
+
+ label .dialog.${dframe}.title.field -text ${textline} -bg beige
+ pack .dialog.${dframe}.title.field -side left
+ }
+}
+
+proc xcircuit::removedialogline {dframe} {
+ global XCOps
+ pack forget .dialog.${dframe}
+ destroy .dialog.${dframe}
+ set XCOps(dialog) 0
+}
+
+#--------------------------------------
+# Create the simple popup prompt window
+#--------------------------------------
+
+toplevel .dialog -bg beige
+wm title .dialog "Dialog Box"
+wm group .dialog .
+wm protocol .dialog WM_DELETE_WINDOW {wm withdraw .dialog}
+wm withdraw .dialog
+set XCOps(dialog) 0
+
+xcircuit::makedialogline textent "Select file to load:"
+
+frame .dialog.bbar -bg beige
+pack .dialog.bbar -side bottom -padx 20 -pady 7 -fill x
+
+button .dialog.bbar.okay -text Okay -bg beige -command {.dialog.bbar.apply invoke ;\
+ wm withdraw .dialog}
+button .dialog.bbar.apply -text Apply -bg beige
+button .dialog.bbar.cancel -text Cancel -bg beige -command {wm withdraw .dialog}
+
+bind .dialog.textent.txt <Return> {.dialog.bbar.apply invoke}
+
+pack .dialog.bbar.okay -side left -ipadx 10
+pack .dialog.bbar.apply -side left -ipadx 10
+pack .dialog.bbar.cancel -side right -ipadx 10
+
+#--------------------------------------
+# Create the query prompt window
+#--------------------------------------
+
+toplevel .query -bg beige
+wm title .query "Query Dialog Box"
+wm group .query .
+wm protocol .query WM_DELETE_WINDOW {wm withdraw .query}
+wm withdraw .query
+
+frame .query.title -bg beige
+frame .query.bbar -bg beige
+
+pack .query.title -side top -padx 20 -pady 7 -fill x
+pack .query.bbar -side bottom -padx 20 -pady 7 -fill x
+
+label .query.title.field -text "Select:" -bg beige
+pack .query.title.field -side left
+
+button .query.bbar.okay -text Okay -bg beige
+button .query.bbar.cancel -text Cancel -bg beige -command {wm withdraw .query}
+
+pack .query.bbar.okay -side left -ipadx 10
+pack .query.bbar.cancel -side right -ipadx 10
+
+#--------------------------------------------------------
+# Generate all of the menu cascades
+# Most commands reference XCircuit internal routines
+#--------------------------------------------------------
+
+# Supporting procedures
+
+proc xcircuit::printstring {stringlist} {
+ set p ""
+ foreach i $stringlist {
+ switch -- [lindex $i 0] {
+ Text {append p [lindex $i 1]}
+ Half -
+ Quarter {append p " "}
+ }
+ }
+ return $p
+}
+
+proc xcircuit::printjust {justif} {
+ switch [expr {$justif & 3}] {
+ 0 {set p "left"}
+ 1 {set p "center"}
+ 3 {set p "right"}
+ }
+ switch [expr {$justif & 12}] {
+ 0 {append p " bottom"}
+ 4 {append p " middle"}
+ 12 {append p " top"}
+ }
+ return $p
+}
+
+proc xcircuit::labelmakeparam {} {
+ global XCOps
+ if {[xcircuit::select] > 0} { ;# this should be true. . .
+ set XCOps(dialog) paramname
+ xcircuit::removedialogline textent2 ;# default is the selected text
+ .dialog.bbar.apply configure -command \
+ [subst {xcircuit::parameter make substring \[.dialog.textent.txt get\];\
+ xcircuit::updateparams substring}]
+ .dialog.textent.title.field configure -text "Parameter name:"
+ }
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+proc xcircuit::promptmakeparam {{mode substring}} {
+ global XCOps
+
+ set XCOps(dialog) paramdefault
+ if {$mode == "label"} {set mode substring}
+ xcircuit::makedialogline textent2 "Default value:"
+ .dialog.bbar.apply configure -command \
+ [subst {xcircuit::parameter make $mode \
+ \[.dialog.textent.txt get\] \[.dialog.textent2.txt get\] -forward; \
+ xcircuit::removedialogline textent2; \
+ xcircuit::updateparams $mode}]
+ .dialog.textent.title.field configure -text \
+ "Parameter name:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+# This procedure generates a new index number for list selection
+# inside a parameter, using "regsub" and "subst" to replace the
+# old index with the new one. This procedure depends on the
+# existance of the listbox widget ".paramlist.plist".
+#----------------------------------------------------------------------
+
+proc xcircuit::renewparam {key y args} {
+ set newidx [.parameter.parvals nearest $y]
+ set current [join [xcircuit::parameter get $key ${args} -verbatim]]
+ regsub {(.*lindex +{.*} +)([0-9]+)(.*)} $current {\1$newidx\3} tmpkey
+ set newkey [subst -nocommands -nobackslashes "$tmpkey"]
+ xcircuit::parameter set $key $newkey $args
+}
+
+#----------------------------------------------------------------------
+# Prompt for a new value of a parameter. Do some sophisticated checking
+# for parameters that declare a list of possible options, and handle
+# that situation separately.
+#----------------------------------------------------------------------
+
+proc xcircuit::changeparamvalue {key current args} {
+
+ .parameter.valedit.entry delete 0 end
+ if {[xcircuit::parameter type $key -forward] == "expression"} {
+
+ # Use regexp processing to find if there is some part of the expression
+ # that chooses a single fixed value from a list. If so, generate a
+ # listbox to present the choices in the list.
+
+ set loccurnt [join [xcircuit::parameter get $key ${args} -verbatim]]
+ if {[regexp {.*lindex +{(.*)} +[0-9]+.*} $loccurnt qall sellist] > 0} {
+ .parameter.parvals delete 0 end
+ raise .parameter.parvals
+
+ foreach item $sellist {
+ .parameter.parvals insert end $item
+ }
+
+ #Abort the parameter value selection
+ bind .parameter.parvals <ButtonRelease-3> {raise .parameter.vallist}
+
+ bind .parameter.parvals <ButtonRelease-1> [subst {xcircuit::renewparam \
+ $key %y $args ;\
+ .parameter.keylist configure -state normal ;\
+ xcircuit::updateparams ;\
+ raise .parameter.vallist}]
+
+ .parameter.valedit.entry delete 0 end
+ .parameter.valedit.entry insert 0 $loccurnt
+
+ } else {
+ # If the parameter is an expression but not a choice-list type, then
+ # we had better print the verbatim entry, or people will just get
+ # confused when the value becomes "invalid result:..."
+ .parameter.valedit.entry insert 0 $loccurnt
+ }
+ } else {
+ .parameter.valedit.entry insert 0 $current
+ }
+ focus .parameter.valedit.entry
+ .parameter.valedit.apply configure \
+ -command [subst {xcircuit::parameter set \
+ $key \[.parameter.valedit.entry get\] \
+ ${args}; xcircuit::updateparams}]
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::updateparams { {mode {substring numeric expression}} } {
+
+ if {[catch {wm state .parameter}]} {return}
+
+ # Avoid infinite recursion if a parameter invokes updateparams
+ # (e.g., any "page" command in a parameter will do this!)
+
+ if {$mode != "force"} {
+ if {[info level] > 1} {return}
+ } else {
+ set mode {substring numeric expression}
+ }
+
+ while {[.parameter.keylist size] > 0} {.parameter.keylist delete 0}
+ while {[.parameter.vallist size] > 0} {.parameter.vallist delete 0}
+
+ .parameter.delete.deleteparam delete 0 last
+
+ if {$mode == "none"} {
+ set dlist [xcircuit::parameter get -forward]
+ } else {
+ set dlist {}
+ foreach i $mode {
+ set dlist [concat $dlist [parameter get $i -forward]]
+ }
+ }
+
+ # Ensure that the parvals list is not present
+ if {[select] == 0} { lower .parameter.parvals }
+
+ # All selections will be lost, so make sure that the value field is clear
+ .parameter.valedit.entry delete 0 end
+ .parameter.valedit.apply configure -command {}
+
+ bind .parameter.vallist <ButtonRelease-1> {
+ set kidx [.parameter.keylist nearest %y]; \
+ xcircuit::changeparamvalue \
+ [.parameter.keylist get $kidx] [.parameter.vallist get $kidx] \
+ -forward}
+
+ ;#The insertion of parameters should only be applicable in "text" mode
+ bind .parameter.keylist <ButtonRelease-1> {
+ set kidx [.parameter.keylist nearest %y]; \
+ if {[string last "text" [xcircuit::eventmode]] >= 0} {
+ label insert parameter [.parameter.keylist get $kidx]
+ }
+ }
+
+ if {[catch {set oname [xcircuit::object name]}]} {
+ .parameter.title configure -text "Parameters"
+ } else {
+ .parameter.title configure -text "Parameters of $oname"
+ }
+ foreach i $dlist {
+ set p_name [lindex $i 0]
+ set p_val [lindex $i 1]
+ .parameter.delete.deleteparam add command -label $p_name -command \
+ "xcircuit::parameter delete $p_name -forward"
+ .parameter.keylist insert end $p_name
+ switch -- [xcircuit::parameter type $p_name -forward] {
+ "substring" {
+ .parameter.vallist insert end [xcircuit::printstring $p_val]
+ }
+ "justification" {
+ .parameter.vallist insert end [xcircuit::printjust $p_val]
+ }
+ default {
+ .parameter.vallist insert end $p_val
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::prompteditparams {} {
+ set wstate [xcircuit::getinitstate .parameter]
+ xcircuit::make_parameter_listbox
+ xcircuit::updateparams force
+ if {"$wstate" != "normal"} {
+ wm deiconify .parameter
+ xcircuit::centerwin .parameter
+ }
+ raise .parameter
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptmakesymbol {{name ""}} {
+ global XCOps
+
+ set XCOps(dialog) makeobject
+ .dialog.bbar.apply configure -command \
+ {if {[string first "Page " [page label]] >= 0} { \
+ page label [.dialog.textent.txt get]}; \
+ xcircuit::symbol make [.dialog.textent.txt get] $XCOps(library)}
+ xcircuit::removedialogline textent2
+ .dialog.textent.title.field configure -text "Name for new object:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $name
+ xcircuit::popupdialog
+ xcircuit::addliblist .dialog "Place in: "
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::prompttargettech {{name ""}} {
+ global XCOps
+
+ set XCOps(dialog) targettech
+ .dialog.bbar.apply configure -command { \
+ set selects [xcircuit::select]; \
+ if {$selects > 0} { \
+ if {[catch {set techname [.dialog.textent2.txt get]}]} {\
+ set techname $XCOps(technology)}; \
+ technology objects $techname [.dialog.textent.txt get]}\
+ }
+ xcircuit::removedialogline textent2
+ .dialog.textent.title.field configure -text "Objects to move:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $name
+ xcircuit::popupdialog
+ xcircuit::addtechlist .dialog "Target technology: "
+
+ # Add an additional selection to the tech menu for adding a new
+ # technology namespace. This is relevant only to "prompttargettech".
+
+ .dialog.techself.techselect.menu add \
+ command -label "Add New Tech" -command \
+ "xcircuit::makedialogline textent2 {New tech name:}"
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptelementsize {} {
+ global XCOps
+ if {![catch {set cscale [xcircuit::element scale]}]} {
+ set XCOps(dialog) elementscale
+ .dialog.bbar.apply configure -command \
+ {xcircuit::element scale [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Element scale:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 $cscale
+ xcircuit::popupdialog
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptborderwidth {} {
+ global XCOps
+ .dialog.textent.txt delete 0 end
+ set XCOps(dialog) linewidth
+ set elist [xcircuit::select get]
+ if {[llength $elist] == 0} {
+ .dialog.bbar.apply configure -command \
+ [subst {config focus [config focus] ;\
+ xcircuit::border set \[.dialog.textent.txt get\]}]
+ .dialog.textent.title.field configure -text "Default linewidth scale:"
+ set btext [format "%g" [xcircuit::border get]]
+ .dialog.textent.txt insert 0 $btext
+ } else {
+ .dialog.bbar.apply configure -command \
+ [subst {config focus [config focus] ;\
+ xcircuit::border set \[.dialog.textent.txt get \]}]
+ .dialog.textent.title.field configure -text "Element linewidth:"
+ set btext [format "%g" [lindex [xcircuit::border get] 0]]
+ .dialog.textent.txt insert 0 $btext
+ }
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptlinewidth {} {
+ global XCOps
+ set XCOps(dialog) linescale
+ .dialog.bbar.apply configure -command \
+ [subst {config focus [config focus] ;\
+ xcircuit::config linewidth \[.dialog.textent.txt get \]}]
+ .dialog.textent.title.field configure -text "Page linewidth scaling:"
+ .dialog.textent.txt delete 0 end
+ set ltext [format "%g" [xcircuit::config linewidth]]
+ .dialog.textent.txt insert 0 $ltext
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptdrawingscale {} {
+ global XCOps
+ set XCOps(dialog) drawingscale
+ .dialog.bbar.apply configure -command \
+ {xcircuit::config drawingscale [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Drawing scale:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 [xcircuit::config drawingscale]
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptgridspace {} {
+ .dialog.bbar.apply configure -command \
+ {xcircuit::config grid spacing [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Grid spacing:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 [xcircuit::config grid space]
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptsnapspace {} {
+ global XCOps
+ set XCOps(dialog) snapspace
+ .dialog.bbar.apply configure -command \
+ {xcircuit::config snap spacing [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Snap spacing:"
+ .dialog.textent.txt delete 0 end
+ .dialog.textent.txt insert 0 [xcircuit::config snap space]
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptmakeobject {} {
+ global XCOps
+ if {[xcircuit::select] > 0} {
+ set XCOps(dialog) makeobject
+ .dialog.bbar.apply configure -command \
+ {if {[select get] != {}} {\
+ if {[.dialog.textent.txt get] == ""} {\
+ .dialog.textent.title.field configure -text "Please enter a name" }\
+ elseif {[catch {xcircuit::object handle [.dialog.textent.txt get]}]} {\
+ xcircuit::object make [.dialog.textent.txt get] $XCOps(library)}\
+ else {.dialog.textent.title.field configure -text \
+ "Name already used. Choose another name" ; .dialog.textent.txt \
+ delete 0 end}}}
+ .dialog.textent.title.field configure -text "Name for new object"
+ .dialog.textent.txt delete 0 end
+ if {$XCOps(technology) != "(user)"} {
+ .dialog.textent.txt insert 0 "${XCOps(technology)}::"
+ }
+ xcircuit::popupdialog
+ xcircuit::addtechlist .dialog "Technology: " {(user)} prefix
+ xcircuit::addliblist .dialog "Place in: "
+
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptreplaceobject {} {
+ global XCOps
+ if {[xcircuit::select] > 0} {
+ set XCOps(dialog) replaceobject
+ .dialog.bbar.apply configure -command \
+ {xcircuit::element selected object [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Name of replacement object"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptloadlibrary {} {
+ global XCOps
+
+ .filelist.bbar.okay configure -command \
+ {xcircuit::library [.filelist.libself.libselect cget -text] load \
+ [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "lps"
+ .filelist.textent.title.field configure -text "Select technology file to load:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+ xcircuit::addliblist .filelist "Load to which library page: "
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptsavetech {} {
+ global XCOps
+
+ set XCOps(dialog) techname
+ .dialog.bbar.apply configure -command \
+ {xcircuit::technology save [.dialog.techself.techselect cget -text] \
+ [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Filename to save technology as:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+ xcircuit::addtechlist .dialog "Save which technology: " {(user)} true
+ set fname ""
+ catch {set fname [technology filename $XCOps(technology)]}
+ if {$fname == "(no associated file)"} {
+ set fname $XCOps(technology).lps
+ }
+ .dialog.textent.txt insert 0 $fname
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptaddlibrary {} {
+ global XCOps
+ set XCOps(dialog) libname
+ .dialog.bbar.apply configure -command \
+ {xcircuit::library make [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Name of new library page:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptloadfile {} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::page load [.filelist.textent.txt get] -replace \
+ [.filelist.techself.techselect cget -text] \
+ -target $XCOps(library); wm withdraw .filelist}
+ .filelist.listwin.win configure -data "ps eps"
+ .filelist.textent.title.field configure -text "Select file to load:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+ xcircuit::addtechlist .filelist "Replace from: " {(user) all none}
+ xcircuit::addliblist .filelist "Target library: "
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptimportspice {} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::page import spice \
+ [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "spice spc ckt sp"
+ .filelist.textent.title.field configure -text "Select SPICE file to import:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptimportfile {} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::page import xcircuit \
+ [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "ps eps"
+ .filelist.textent.title.field configure -text "Select file to import:"
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptimportbackground {} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::page import background \
+ [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "ps eps"
+ .filelist.textent.title.field configure -text "Select file to use as background:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+# Convert a graphic image using ImageMagick "convert" (if available)
+#----------------------------------------------------------------------
+
+proc xcircuit::convertgraphic {filename} {
+ set fileext [file extension $filename]
+ set fileroot [file rootname $filename]
+ set temp true
+ switch -- $fileext {
+ .gif -
+ .jpg -
+ .png -
+ .pnm {
+ exec convert $filename ${fileroot}.ppm
+ }
+ .ppm {
+ set temp false
+ }
+ .ps -
+ .pdf {
+ exec convert -density 300x300 $filename ${fileroot}.ppm
+ }
+ }
+ xcircuit::graphic make ${fileroot}.ppm {0 0} 1;
+ if {$temp == true} {
+ file delete ${fileroot}.ppm
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptimportgraphic {} {
+ if {![catch {exec convert -version}]} {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::convertgraphic [.filelist.textent.txt get];
+ refresh; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "pnm ppm gif jpg png"
+ } else {
+ .filelist.bbar.okay configure -command \
+ {xcircuit::graphic make [.filelist.textent.txt get] {0 0} 1;
+ refresh; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "pnm ppm"
+ }
+ .filelist.textent.title.field configure -text "Select graphic image file:"
+ .filelist.textent.txt delete 0 end
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptexecscript {} {
+ .filelist.bbar.okay configure -command \
+ {source [.filelist.textent.txt get]; wm withdraw .filelist}
+ .filelist.listwin.win configure -data "tcl xcircuitrc"
+ .filelist.textent.title.field configure -text "Select script to execute:"
+ xcircuit::popupfilelist
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::prompttextsize {} {
+ global XCOps
+ set XCOps(dialog) textscale
+ .dialog.bbar.apply configure -command \
+ {xcircuit::label scale [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Text scale:"
+ .dialog.textent.txt delete 0 end
+ set stext [format "%g" [xcircuit::label scale]]
+ .dialog.textent.txt insert 0 $stext
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+# add a library list widget to a dialog box
+#----------------------------------------------------------------------
+
+proc xcircuit::addliblist {w {prompt "Target: "}} {
+ global XCOps
+
+ frame ${w}.libself
+ label ${w}.libself.title -text $prompt -bg beige
+
+ set liblist [library directory list]
+
+ menubutton ${w}.libself.libselect -menu ${w}.libself.libselect.menu -relief groove
+ menu ${w}.libself.libselect.menu -tearoff 0
+ foreach j $liblist {
+ ${w}.libself.libselect.menu add \
+ radio -label "$j" -variable XCOps(library) -value \
+ "$j" -command "${w}.libself.libselect configure -text {$j}"
+ }
+ ${w}.libself.libselect configure -text $XCOps(library)
+
+ pack ${w}.libself.title -side left
+ pack ${w}.libself.libselect -side left
+ pack ${w}.libself -side top -anchor w -padx 20
+}
+
+#----------------------------------------------------------------------
+# Add a technology list widget to a dialog box
+#
+# If "update" is "true", then a selection of a technology in the list
+# will update the text entry window contents with the corresponding
+# filename. If "update" is "prefix", then a selection of a technology
+# in the list will update the text entry window contents with the
+# technology namespace prefix corresponding to the selected technology.
+# If "update" is "false", then selecting the technology will set the
+# global variable XCOps(technology) but will not alter the window
+# contents.
+#----------------------------------------------------------------------
+
+proc xcircuit::addtechlist {w {prompt "Technology: "} {endlist {}} {update {false}}} {
+ global XCOps
+
+ frame ${w}.techself
+ label ${w}.techself.title -text $prompt -bg beige
+
+ set techlist [technology list]
+ foreach j $endlist { lappend techlist $j }
+
+ menubutton ${w}.techself.techselect -menu ${w}.techself.techselect.menu -relief groove
+ menu ${w}.techself.techselect.menu -tearoff 0
+ foreach j $techlist {
+ if {$update == true} {
+ set fname ""
+ catch {set fname [technology filename "$j"]}
+
+ ${w}.techself.techselect.menu add \
+ radio -label "$j" -variable XCOps(technology) -value \
+ "$j" -command "${w}.techself.techselect configure -text {$j} ; \
+ ${w}.textent.txt delete 0 end ; ${w}.textent.txt insert 0 {$fname}"
+ } elseif {$update == "prefix"} {
+ if {$j != {} && $j != "(user)"} {
+ set tpfix "${j}::"
+ } else {
+ set tpfix {}
+ }
+ ${w}.techself.techselect.menu add \
+ radio -label "$j" -variable XCOps(technology) -value \
+ "$j" -command [subst {${w}.techself.techselect configure -text {$j} ; \
+ set pfixend \[string last :: \[${w}.textent.txt get\]\] ; \
+ if {\$pfixend < 0} {set pfixend 0} else {incr pfixend 2} ; \
+ ${w}.textent.txt delete 0 \$pfixend ; \
+ ${w}.textent.txt insert 0 {$tpfix}}]
+ } else {
+ ${w}.techself.techselect.menu add \
+ radio -label "$j" -variable XCOps(technology) -value \
+ "$j" -command "${w}.techself.techselect configure -text {$j}"
+ }
+ }
+ ${w}.techself.techselect configure -text $XCOps(technology)
+
+ pack ${w}.techself.title -side left
+ pack ${w}.techself.techselect -side left
+ pack ${w}.techself -side right -anchor w -padx 20
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::removelists {w} {
+ global XCOps
+
+ catch {
+ pack forget ${w}.libself
+ destroy ${w}.libself
+ }
+ catch {
+ pack forget ${w}.techself
+ destroy ${w}.techself
+ }
+}
+
+#----------------------------------------------------------------------
+# newcolorbutton is called internally to xcircuit---don't mess with it!
+#----------------------------------------------------------------------
+
+proc xcircuit::newcolorbutton {r g b idx} {
+ global XCWinOps XCIRCUIT_LIB_DIR
+
+ set colorrgb [format "#%04X%04X%04X" $r $g $b]
+ image create bitmap img_col$idx -foreground $colorrgb -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/solid.xbm
+
+ foreach window [config windownames] {
+ set frame [winfo top $window]
+ ${frame}.menubar.optionsbutton.optionsmenu.elementsmenu.colormenu \
+ add radio -image img_col$idx -activebackground $colorrgb \
+ -variable XCWinOps(${frame},colorval) -value $idx -command \
+ "xcircuit::color set $idx"
+ }
+}
+
+#----------------------------------------------------------------------
+# Regenerate the list of color buttons for a new window
+#----------------------------------------------------------------------
+
+proc xcircuit::allcolorbuttons {window} {
+ global XCWinOps
+
+ set colorlist [color get -all]
+ set frame [winfo top $window]
+ set idx 0
+ foreach colorrgb $colorlist {
+ ${frame}.menubar.optionsbutton.optionsmenu.elementsmenu.colormenu \
+ add radio -image img_col$idx -activebackground $colorrgb \
+ -variable XCWinOps(${frame},colorval) -value $idx -command \
+ "xcircuit::color set $idx"
+ incr idx
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::picknewcolor {} {
+ if {[catch {set colorrgb [tk_chooseColor]}]} {
+ set colorrgb [tkColorDialog]
+ }
+ xcircuit::color add $colorrgb
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::newencodingbutton {encodingname} {
+ global XCWinOps
+
+ foreach window [config windownames] {
+ set frame [winfo top $window]
+ if {[catch {${frame}.menubar.textbutton.textmenu.encodingmenu \
+ index $encodingname} result]} {
+ ${frame}.menubar.textbutton.textmenu.encodingmenu add radio -label \
+ $encodingname -command "xcircuit::label encoding $encodingname" \
+ -variable XCWinOps(${frame},fontencoding) -value $encodingname
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::newfontbutton {familyname} {
+ global XCWinOps
+
+ foreach window [config windownames] {
+ set frame [winfo top $window]
+ if {[catch {${frame}.menubar.textbutton.textmenu.fontmenu \
+ index $familyname} result]} {
+ ${frame}.menubar.textbutton.textmenu.fontmenu add radio -label \
+ $familyname -command "xcircuit::label family $familyname" \
+ -variable XCWinOps(${frame},fontfamily) -value $familyname
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+# Regenerate the list of known font families for a new window
+#----------------------------------------------------------------------
+
+proc xcircuit::allfontbuttons {window} {
+ global XCWinOps
+
+ set familylist [label family -all]
+ set frame [winfo top $window]
+ while {$familylist != {}} {
+ set familyname [lindex $familylist 0]
+ ${frame}.menubar.textbutton.textmenu.fontmenu add radio -label \
+ $familyname -command "xcircuit::label family $familyname" \
+ -variable XCWinOps(${frame},fontfamily) -value $familyname
+ # Remove all such entries (this works like "lsort -unique" but doesn't
+ # scramble the list entries).
+ set familylist [lsearch -all -inline -not $familylist $familyname]
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::newlibrarybutton {libname} {
+ if {[catch {.librarymenu index $libname} result]} {
+ set libidx [.librarymenu index end]
+ if {$libidx <= 1} {set libidx [expr $libidx + 1]}
+ .librarymenu insert $libidx command -label $libname -command \
+ "xcircuit::library \"$libname\" goto"
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::newpagebutton {pagename {pageno 0}} {
+ if {[catch {.pagemenu index $pagename} result]} {
+ set target $pagename
+ if {$pageno > 0} { set target $pageno }
+ .pagemenu add command -label $pagename -command \
+ "xcircuit::page \"$target\" goto"
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::renamelib {libno libname} {
+ set target [expr $libno + 1]
+ .librarymenu entryconfigure $target -label $libname -command \
+ "xcircuit::library \"$libname\" goto"
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::renamepage {pageno pagename} {
+ set target [expr $pageno + 1]
+ .pagemenu entryconfigure $target -label $pagename -command \
+ "xcircuit::page \"$pagename\" goto"
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptnewfont {} {
+ global XCOps
+ set XCOps(dialog) fontname
+ .dialog.bbar.apply configure -command \
+ {xcircuit::loadfont [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Font name:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptkern {} {
+ global XCOps
+ set XCOps(dialog) kernamount
+ .dialog.bbar.apply configure -command \
+ {xcircuit::label insert kern [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Kern amount:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::promptmargin {} {
+ global XCOps
+ set XCOps(dialog) marginamount
+ .dialog.bbar.apply configure -command \
+ {xcircuit::label insert margin [.dialog.textent.txt get]}
+ .dialog.textent.title.field configure -text "Margin amount:"
+ .dialog.textent.txt delete 0 end
+ xcircuit::popupdialog
+}
+
+#----------------------------------------------------------------------
+
+set XCOps(tools) [list pn w b a s t mv cp e d2 cw ccw fx fy r pu2 po2 mk pz \
+ uj co bd fi pm pa li yp pl z4 z5 i]
+
+for {set i 0} {$i < [llength $XCOps(tools)]} {incr i 1} {
+ set bname [lindex $XCOps(tools) $i]
+ image create photo img_${bname} -file ${XCIRCUIT_LIB_DIR}/pixmaps/${bname}.gif
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::modebutton {widget} {
+ global XCOps XCWinOps
+ set window $XCOps(focus)
+
+ for {set i 0} {$i < [llength $XCOps(tools)]} {incr i 1} {
+ set bname [lindex $XCOps(tools) $i]
+ ${window}.mainframe.toolbar.b${bname} configure -relief raised \
+ -highlightbackground gray90 -background gray90
+ }
+ $widget configure -relief solid -highlightbackground green3 -background green3
+ if {$XCWinOps(${window},button1) == "Rotate"} {
+ ${window}.infobar.mode configure -text "$XCWinOps(${window},button1) \
+ $XCWinOps(${window},rotateamount) Mode"
+ } else {
+ ${window}.infobar.mode configure -text "$XCWinOps(${window},button1) Mode"
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::button1action {button cursor action {value {}}} {
+ global XCOps XCWinOps
+
+ set window $XCOps(focus).mainframe.mainarea.drawing
+ catch {bindkey $window Button1 $XCWinOps($XCOps(focus),button1) forget}
+
+ if {$value == {}} {
+ bindkey $window Button1 $action
+ } else {
+ bindkey $window Button1 $action $value
+ }
+ set XCWinOps($XCOps(focus),button1) $action
+ xcircuit::modebutton $button
+ catch {cursor $cursor}
+ catch {xcircuit::automousehint $window}
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::createtoolbar {window} {
+ global XCOps XCWinOps XCIRCUIT_LIB_DIR
+
+ set tooltips [list "pan window" "draw wire" "draw box" \
+ "draw arc" "draw spline" "enter text" \
+ "move element" "copy element" "edit element" "delete element" \
+ "rotate 15 degrees clockwise" "rotate 15 degrees counterclockwise" \
+ "flip horizontal" "flip vertical" "rescale" "push (edit object)" \
+ "pop (return from object edit)" "make an object from selection" \
+ "join elements into polygon or path" "separate path into elements" \
+ "set color" "set border and line properties" "set fill properties" \
+ "parameterize properties" "parameter selection" \
+ "go to next library" "go to library directory" \
+ "go to page directory" "zoom in" "zoom out" "pop up help window"]
+ set toolactions [list \
+ {xcircuit::button1action %W hand Pan 6} \
+ {xcircuit::button1action %W cross Wire} \
+ {xcircuit::button1action %W cross Box} \
+ {xcircuit::button1action %W circle Arc} \
+ {if {[select]} {spline make} else { \
+ xcircuit::button1action %W arrow Spline}} \
+ {xcircuit::button1action %W text $XCWinOps($XCOps(focus),labeltype) ; \
+ $XCOps(focus).mainframe.toolbar.bt configure -image \
+ $XCWinOps($XCOps(focus),labelimage)} \
+ {if {[select]} {move selected} else { \
+ xcircuit::button1action %W arrow Move}} \
+ {if {[select]} {copy selected} else { \
+ xcircuit::button1action %W copy Copy}} \
+ {if {[select] == 1} {edit selected} else { \
+ xcircuit::button1action %W edit Edit}} \
+ {if {[select]} {delete selected} else { \
+ xcircuit::button1action %W scissors Delete}} \
+ {if {[select]} {rotate $XCWinOps($XCOps(focus),rotateamount)} else {\
+ xcircuit::button1action %W rotate Rotate \
+ $XCWinOps($XCOps(focus),rotateamount)}} \
+ {if {[select]} {rotate -$XCWinOps($XCOps(focus),rotateamount)} else {\
+ xcircuit::button1action %W rotate Rotate \
+ -$XCWinOps($XCOps(focus),rotateamount)}} \
+ {if {[select]} {flip horizontal} else { \
+ xcircuit::button1action %W rotate "Flip X"}} \
+ {if {[select]} {flip vertical} else { \
+ xcircuit::button1action %W rotate "Flip Y"}} \
+ {if {[select]} {xcircuit::promptelementsize} else { \
+ xcircuit::button1action %W arrow Rescale}} \
+ {if {[select] == 1} {push selected} else { \
+ xcircuit::button1action %W question Push}} \
+ {pop} \
+ {if {[select]} {xcircuit::promptmakeobject} else { \
+ xcircuit::button1action %W question "Select Save"}} \
+ {if {[select]} {path join selected} else { \
+ xcircuit::button1action %W arrow Join}} \
+ {if {[select] == 1} {path unjoin selected} else { \
+ xcircuit::button1action %W arrow Unjoin}} \
+ {tk_popup $XCOps(focus).colormenu [expr {[winfo rootx \
+ $XCOps(focus).mainframe.toolbar.bco] \
+ - [winfo width $XCOps(focus).colormenu]}] \
+ [expr {[winfo rooty $XCOps(focus).mainframe.toolbar.bco] \
+ - [winfo height $XCOps(focus).colormenu] / 2}] } \
+ {tk_popup $XCOps(focus).bordermenu [expr {[winfo rootx \
+ $XCOps(focus).mainframe.toolbar.bbd] \
+ - [winfo width $XCOps(focus).bordermenu]}] \
+ [expr {[winfo rooty $XCOps(focus).mainframe.toolbar.bbd] \
+ - [winfo height $XCOps(focus).bordermenu] / 2}] } \
+ {tk_popup $XCOps(focus).fillmenu [expr {[winfo rootx \
+ $XCOps(focus).mainframe.toolbar.bfi] \
+ - [winfo width $XCOps(focus).fillmenu]}] \
+ [expr {[winfo rooty $XCOps(focus).mainframe.toolbar.bfi] \
+ - [winfo height $XCOps(focus).fillmenu] / 2}] } \
+ {tk_popup $XCOps(focus).parammenu [expr {[winfo rootx \
+ $XCOps(focus).mainframe.toolbar.bpm] \
+ - [winfo width $XCOps(focus).parammenu]}] \
+ [expr {[winfo rooty $XCOps(focus).mainframe.toolbar.bpm] \
+ - [winfo height $XCOps(focus).parammenu] / 2}] } \
+ {xcircuit::prompteditparams} \
+ {library next} \
+ {library directory} {page directory} \
+ {zoom 1.5; refresh} {zoom [expr {1 / 1.5}]; refresh} \
+ {xcircuit::helpwindow} ]
+
+ for {set i 0} {$i < [llength $XCOps(tools)]} {incr i 1} {
+ set bname [lindex $XCOps(tools) $i]
+ set btip [lindex $tooltips $i]
+ regsub -all -- %W [lindex $toolactions $i] \
+ ${window}.mainframe.toolbar.b${bname} bcmd
+ button ${window}.mainframe.toolbar.b${bname} -image img_${bname} -command \
+ "$bcmd"
+ bind ${window}.mainframe.toolbar.b${bname} <Enter> \
+ [subst {${window}.infobar.message2 configure -text "$btip"}]
+ bind ${window}.mainframe.toolbar.b${bname} <Leave> \
+ [subst {${window}.infobar.message2 configure -text ""}]
+ }
+
+ # pack the first button so we can query its height for arrangement.
+ # this assumes that the height of each button is the same!
+ set bname [lindex $XCOps(tools) 0]
+ place ${window}.mainframe.toolbar.b${bname} -x 0 -y 0
+ update idletasks
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::arrangetoolbar {window} {
+ global XCOps
+
+ set numtools [llength $XCOps(tools)]
+ for {set i 0} {$i < $numtools} {incr i 1} {
+ set bname [lindex $XCOps(tools) $i]
+ place forget ${window}.mainframe.toolbar.b${bname}
+ }
+ set bname [lindex $XCOps(tools) 0]
+ set bheight [winfo height ${window}.mainframe.toolbar.b${bname}]
+ set bwidth [winfo width ${window}.mainframe.toolbar.b${bname}]
+ set wheight [winfo height ${window}.mainframe]
+ set nrows [expr {$wheight / $bheight}]
+ ${window}.mainframe.toolbar configure -width [expr {$bwidth}]
+ set j 0
+ set k 0
+ for {set i 0} {$i < [llength $XCOps(tools)]} {incr i; incr j} {
+ if {$j == $nrows} {
+ set j 0
+ incr k
+ ${window}.mainframe.toolbar configure -width [expr {($k + 1) * $bwidth}]
+ }
+ set bname [lindex $XCOps(tools) $i]
+ place ${window}.mainframe.toolbar.b${bname} \
+ -x [expr {$k * $bwidth}] \
+ -y [expr {$j * $bheight}]
+ }
+}
+
+#----------------------------------------------------------------------
+
+proc xcircuit::toolbar {value} {
+ global XCOps
+ set window $XCOps(focus)
+
+ switch -- $value {
+ true -
+ enable {
+ pack forget ${window}.mainframe.mainarea
+ pack ${window}.mainframe.toolbar -side right -fill y -padx 2
+ pack ${window}.mainframe.mainarea -expand true -fill both
+ set midx [${window}.menubar.optionsbutton.optionsmenu \
+ index "Enable Toolbar"]
+ ${window}.menubar.optionsbutton.optionsmenu entryconfigure $midx \
+ -command {xcircuit::toolbar disable} -label \
+ "Disable Toolbar"
+ }
+ false -
+ disable {
+ pack forget ${window}.mainframe.toolbar
+ set midx [${window}.menubar.optionsbutton.optionsmenu \
+ index "Disable Toolbar"]
+ ${window}.menubar.optionsbutton.optionsmenu entryconfigure $midx \
+ -command {xcircuit::toolbar enable} -label \
+ "Enable Toolbar"
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+# These variables are associated with toggle and radio buttons
+# but must be the same for all windows.
+#----------------------------------------------------------------------
+
+set XCOps(sheetsize) letter
+set XCOps(spiceend) true
+set XCOps(forcenets) true
+set XCOps(hold) true
+
+set XCOps(focus) .xcircuit
+
+#----------------------------------------------------------------------
+# Create stipple images
+#----------------------------------------------------------------------
+
+image create bitmap img_stip0 -foreground white -background black -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/solid.xbm
+image create bitmap img_stip12 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip12.xbm
+image create bitmap img_stip25 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip25.xbm
+image create bitmap img_stip38 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip38.xbm
+image create bitmap img_stip50 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip50.xbm
+image create bitmap img_stip62 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip62.xbm
+image create bitmap img_stip75 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip75.xbm
+image create bitmap img_stip88 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/stip88.xbm
+image create bitmap img_stip100 -foreground black -background white -file \
+ ${XCIRCUIT_LIB_DIR}/pixmaps/solid.xbm
+
+#----------------------------------------------------------------------
+# alternate label type images (info, global, and pin labels)
+#----------------------------------------------------------------------
+
+image create photo img_ti -file ${XCIRCUIT_LIB_DIR}/pixmaps/ti.gif
+image create photo img_tg -file ${XCIRCUIT_LIB_DIR}/pixmaps/tg.gif
+image create photo img_tp -file ${XCIRCUIT_LIB_DIR}/pixmaps/tp.gif
+
+#----------------------------------------------------------------------
+
+proc xcircuit::makemenus {window} {
+ global XCOps
+
+ set m [menu ${window}.menubar.filebutton.filemenu -tearoff 0]
+ $m add command -label "New Window" -command {xcircuit::forkwindow}
+ $m add command -label "Close Window" -command \
+ "xcircuit::closewindow ${window}.mainframe.mainarea.drawing"
+ $m add separator
+ $m add command -label "Read XCircuit File" -command {xcircuit::promptloadfile}
+ if {![catch {set XCOps(module,files)}]} {
+ $m add command -label "Write All..." -command {xcircuit::promptwriteall}
+ }
+ $m add command -label "Format Page Output" -command {xcircuit::promptsavepage}
+ $m add separator
+ $m add command -label "Load Dependencies" -command \
+ {while {[page links load -replace $XCOps(technology) \
+ -target $XCOps(library)]} {}}
+ $m add cascade -label "Import" -menu $m.importmenu
+ $m add cascade -label "Export" -menu $m.exportmenu
+
+ $m add command -label "Execute Script" -command {xcircuit::promptexecscript}
+ if {[file tail [info nameofexecutable]] != "xcircexec"} {
+ $m add command -label "Tcl Console" -command {xcircuit::raiseconsole}
+ }
+ $m add separator
+ if {![catch {set XCOps(module,library)}]} {
+ $m add command -label "Library Manager" -command {xcircuit::raisemanager}
+ }
+ $m add command -label "New Library Page" -command {xcircuit::promptaddlibrary}
+ $m add command -label "Load Technology (.lps)" -command {xcircuit::promptloadlibrary}
+ $m add command -label "Save Technology (.lps)" -command {xcircuit::promptsavetech}
+
+ $m add separator
+ $m add command -label "Clear Page" -command {xcircuit::page reset}
+ $m add separator
+ $m add command -label "Quit" -command {quit}
+
+ # Sub-menu for Import functions
+
+ set m2 [menu $m.importmenu -tearoff 0]
+ $m2 add command -label "Import XCircuit File" -command {xcircuit::promptimportfile}
+ $m2 add command -label "Import background PS" -command \
+ {xcircuit::promptimportbackground}
+ $m2 add command -label "Import graphic image" -command \
+ {xcircuit::promptimportgraphic}
+ if {![catch {set XCOps(module,edif)}]} {
+ $m2 add command -label "Read EDIF file" -command {xcircuit::promptreadedif}
+ }
+ if {![catch {set XCOps(module,matgen)}]} {
+ $m2 add command -label "Import Matlab PS" -command {xcircuit::promptimportmatlab}
+ }
+ if {![catch {set XCIRCUIT_ASG}]} {
+ $m2 add command -label "Import SPICE Deck" -command \
+ {xcircuit::promptimportspice}
+ }
+ if {![catch {set XCOps(module,text)}]} {
+ $m2 add command -label "Import text" -command {xcircuit::promptimporttext}
+ }
+
+ # Sub-menu for Export functions
+
+ set m2 [menu $m.exportmenu -tearoff 0]
+ $m2 add command -label "Export SVG" -command {svg -fullscale}
+
+ set m [menu ${window}.menubar.editbutton.editmenu -tearoff 0]
+ $m add command -label "Undo" -command {undo}
+ $m add command -label "Redo" -command {redo}
+ $m add separator
+ $m add command -label "Delete" -command \
+ "${window}.mainframe.toolbar.bd2 invoke"
+ $m add command -label "Copy" -command \
+ "${window}.mainframe.toolbar.bcp invoke"
+ $m add command -label "Move" -command \
+ "${window}.mainframe.toolbar.bmv invoke"
+ $m add command -label "Edit" -command \
+ "${window}.mainframe.toolbar.be invoke"
+ $m add cascade -label "Rotate/Flip" -menu $m.rotmenu
+ $m add command -label "Deselect" -command {deselect selected}
+ $m add cascade -label "Select Filter" -menu $m.selmenu
+ $m add command -label "Push Selected" -command \
+ "${window}.mainframe.toolbar.pu2 invoke"
+ $m add command -label "Pop Hierarchy" -command {pop}
+ $m add separator
+ $m add command -label "Change Technology" -command \
+ {xcircuit::prompttargettech [element selected object]}
+ $m add separator
+ $m add command -label "Make User Object" -command \
+ "${window}.mainframe.toolbar.bmk invoke"
+ $m add command -label "Make Arc" -command \
+ "${window}.mainframe.toolbar.ba invoke"
+ $m add command -label "Make Box" -command \
+ "${window}.mainframe.toolbar.bb invoke"
+ $m add command -label "Make Spline" -command \
+ "${window}.mainframe.toolbar.bs invoke"
+ $m add command -label "Make Wire" -command \
+ "${window}.mainframe.toolbar.bw invoke"
+ $m add command -label "Replace" -command {xcircuit::promptreplaceobject}
+ $m add command -label "Join" -command \
+ "${window}.mainframe.toolbar.bpz invoke"
+ $m add command -label "Unjoin" -command \
+ "${window}.mainframe.toolbar.buj invoke"
+ $m add command -label "Raise/Lower" -command {element exchange}
+
+ set m2 [menu $m.rotmenu -tearoff 0]
+ $m2 add command -label "Flip Horizontal" -command \
+ "${window}.mainframe.toolbar.bfx invoke"
+ $m2 add command -label "Flip Vertical" -command \
+ "${window}.mainframe.toolbar.bfy invoke"
+ $m2 add command -label "Rescale" -command \
+ "${window}.mainframe.toolbar.r invoke"
+ $m2 add separator
+ $m2 add command -label "Rotate CW 90" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 90; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add command -label "Rotate CW 45" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 45; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add command -label "Rotate CW 30" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 30; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add command -label "Rotate CW 15" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 15; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add command -label "Rotate CW 5" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 5; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add command -label "Rotate CW 1" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 1; \
+ $XCOps(focus).mainframe.toolbar.bcw invoke}
+ $m2 add separator
+ $m2 add command -label "Rotate CCW 90" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 90; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+ $m2 add command -label "Rotate CCW 45" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 45; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+ $m2 add command -label "Rotate CCW 30" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 30; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+ $m2 add command -label "Rotate CCW 15" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 15; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+ $m2 add command -label "Rotate CCW 5" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 5; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+ $m2 add command -label "Rotate CCW 1" -command \
+ {set XCWinOps($XCOps(focus),rotateamount) 1; \
+ $XCOps(focus).mainframe.toolbar.bccw invoke}
+
+ set m2 [menu $m.selmenu -tearoff 0]
+ $m2 add command -label "Disable selection" -command {element select hide}
+ $m2 add command -label "Remove all disabled" -command {element select allow}
+ $m2 add separator
+ $m2 add check -label "Labels" -variable XCWinOps(${window},sel_lab) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter label $XCWinOps($XCOps(focus),sel_lab)}
+ $m2 add check -label "Objects" -variable XCWinOps(${window},sel_inst) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter instance $XCWinOps($XCOps(focus),sel_inst)}
+ $m2 add check -label "Polygons" -variable XCWinOps(${window},sel_poly) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter polygon $XCWinOps($XCOps(focus),sel_poly)}
+ $m2 add check -label "Arcs" -variable XCWinOps(${window},sel_arc) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter arc $XCWinOps($XCOps(focus),sel_arc)}
+ $m2 add check -label "Splines" -variable XCWinOps(${window},sel_spline) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter spline $XCWinOps($XCOps(focus),sel_spline)}
+ $m2 add check -label "Paths" -variable XCWinOps(${window},sel_path) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter path $XCWinOps($XCOps(focus),sel_path)}
+ $m2 add check -label "Graphic Images" -variable XCWinOps(${window},sel_graphic) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config filter graphic $XCWinOps($XCOps(focus),sel_graphic)}
+
+ set m [menu ${window}.menubar.textbutton.textmenu -tearoff 0]
+ $m add command -label "Text Size" -command {xcircuit::prompttextsize}
+ $m add cascade -label "Font" -menu $m.fontmenu
+ $m add cascade -label "Style" -menu $m.stylemenu
+ $m add cascade -label "Encoding" -menu $m.encodingmenu
+ $m add cascade -label "Insert" -menu $m.insertmenu
+ $m add cascade -label "Justification" -menu $m.justifymenu
+ $m add command -label "Parameterize" \
+ -command {xcircuit::labelmakeparam}
+ $m add command -label "Unparameterize" \
+ -command {xcircuit::parameter replace substring}
+ $m add separator
+ $m add check -label "LaTeX mode" -variable XCWinOps(${window},latexmode) \
+ -onvalue true -offvalue false -command {xcircuit::label latex \
+ $XCWinOps($XCOps(focus),latexmode)}
+ if {![catch {set XCOps(module,text)}]} {
+ $m add separator
+ $m add command -label "Modify Text..." -command {xcircuit::textmod}
+ }
+ $m add separator
+ $m add command -label "Make Text" -command \
+ {set XCWinOps($XCOps(focus),labeltype) "Text"; set \
+ XCWinOps($XCOps(focus),labelimage) img_t; \
+ $XCOps(focus).mainframe.toolbar.bt invoke}
+
+ set m2 [menu $m.fontmenu -tearoff 0]
+ $m2 add command -label "Add New Font" -command {xcircuit::promptnewfont}
+ $m2 add separator
+
+ set m2 [menu $m.stylemenu -tearoff 0]
+ $m2 add radio -label "Normal" -variable XCWinOps(${window},fontstyle) \
+ -value normal -command "xcircuit::label style normal"
+ $m2 add radio -label "Bold" -variable XCWinOps(${window},fontstyle) \
+ -value bold -command "xcircuit::label style bold"
+ $m2 add radio -label "Italic" -variable XCWinOps(${window},fontstyle) \
+ -value italic -command "xcircuit::label style italic"
+ $m2 add radio -label "BoldItalic" -variable XCWinOps(${window},fontstyle) \
+ -value bolditalic -command "xcircuit::label style bolditalic"
+ $m2 add separator
+ $m2 add radio -label "Subscript" -variable XCWinOps(${window},fontscript) \
+ -value subscript -command "xcircuit::label insert subscript"
+ $m2 add radio -label "Superscript" -variable XCWinOps(${window},fontscript) \
+ -value superscript -command "xcircuit::label insert superscript"
+ $m2 add radio -label "Normalscript" -variable XCWinOps(${window},fontscript) \
+ -value normal -command "xcircuit::label insert normalscript"
+ $m2 add separator
+ $m2 add radio -label "Underline" -variable XCWinOps(${window},fontlining) \
+ -value underline -command "xcircuit::label insert underline"
+ $m2 add radio -label "Overline" -variable XCWinOps(${window},fontlining) \
+ -value overline -command "xcircuit::label insert overline"
+ $m2 add radio -label "No Line" -variable XCWinOps(${window},fontlining) \
+ -value normal -command "xcircuit::label insert noline"
+
+ set m2 [menu $m.encodingmenu -tearoff 0]
+ $m2 add radio -label "Standard" -variable XCWinOps(${window},fontencoding) \
+ -value Standard -command "xcircuit::label encoding Standard"
+ $m2 add radio -label "ISOLatin1" -variable XCWinOps(${window},fontencoding) \
+ -value ISOLatin1 -command "xcircuit::label encoding ISOLatin1"
+
+ set m2 [menu $m.insertmenu -tearoff 0]
+ $m2 add command -label "Tab stop" -command "xcircuit::label insert stop"
+ $m2 add command -label "Tab forward" -command "xcircuit::label insert forward"
+ $m2 add command -label "Tab backward" -command "xcircuit::label insert backward"
+ $m2 add command -label "Margin stop" -command {if {[lindex [xcircuit::label \
+ substring] 1] <= 1} {xcircuit::promptmargin} else \
+ {xcircuit::label insert margin}}
+ $m2 add command -label "Carriage Return" -command "xcircuit::label insert return"
+ $m2 add command -label "1/2 space" -command "xcircuit::label insert halfspace"
+ $m2 add command -label "1/4 space" -command "xcircuit::label insert quarterspace"
+ $m2 add command -label "Kern" -command "xcircuit::promptkern"
+ $m2 add command -label "Character" -command "xcircuit::label insert special"
+ $m2 add command -label "Parameter" -command "xcircuit::prompteditparams"
+
+ set m2 [menu $m.justifymenu -tearoff 0]
+ $m2 add radio -label "Left Justified" -variable XCWinOps(${window},jhoriz) \
+ -value left -command "xcircuit::label justify left"
+ $m2 add radio -label "Center Justified" -variable XCWinOps(${window},jhoriz) \
+ -value center -command "xcircuit::label justify center"
+ $m2 add radio -label "Right Justified" -variable XCWinOps(${window},jhoriz) \
+ -value right -command "xcircuit::label justify right"
+ $m2 add separator
+ $m2 add radio -label "Top Justified" -variable XCWinOps(${window},jvert) \
+ -value top -command "xcircuit::label justify top"
+ $m2 add radio -label "Middle Justified" -variable XCWinOps(${window},jvert) \
+ -value middle -command "xcircuit::label justify middle"
+ $m2 add radio -label "Bottom Justified" -variable XCWinOps(${window},jvert) \
+ -value bottom -command "xcircuit::label justify bottom"
+ $m2 add separator
+ $m2 add check -label "Flip Invariant" \
+ -variable XCWinOps(${window},flipinvariant) \
+ -onvalue true -offvalue false -command {xcircuit::label flipinvariant \
+ $XCWinOps($XCOps(focus),flipinvariant)}
+
+ set m [menu ${window}.menubar.optionsbutton.optionsmenu -tearoff 0]
+ $m add check -label "Alt Colors" -variable XCWinOps(${window},colorscheme) \
+ -onvalue inverse -offvalue normal -command {xcircuit::config \
+ colorscheme $XCWinOps($XCOps(focus),colorscheme)}
+ $m add check -label "Show Bounding Box" -variable XCWinOps(${window},showbbox) \
+ -onvalue visible -offvalue invisible -command \
+ {xcircuit::config bbox $XCWinOps($XCOps(focus),showbbox)}
+ $m add check -label "Edit In Place" -variable XCWinOps(${window},editinplace) \
+ -onvalue true -offvalue false -command {xcircuit::config editinplace \
+ $XCWinOps($XCOps(focus),editinplace)}
+ $m add check -label "Show Pin Positions" \
+ -variable XCWinOps(${window},pinpositions) \
+ -onvalue visible -offvalue invisible -command \
+ {xcircuit::config pinpositions $XCWinOps($XCOps(focus),pinpositions)}
+ $m add check -label "Wires Stay Attached to Pins" \
+ -variable XCWinOps(${window},pinattach) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config pinattach $XCWinOps($XCOps(focus),pinattach)}
+ $m add check -label "Show Clipmask Outlines" \
+ -variable XCWinOps(${window},showclipmasks) \
+ -onvalue show -offvalue hide -command \
+ {xcircuit::config clipmasks $XCWinOps($XCOps(focus),showclipmasks)}
+ $m add check -label "Show Technology Namespaces" \
+ -variable XCWinOps(${window},namespaces) \
+ -onvalue true -offvalue false -command \
+ {xcircuit::config technologies $XCWinOps($XCOps(focus),namespaces)}
+
+ $m add command -label "Disable Toolbar" -command {xcircuit::toolbar disable}
+ $m add check -label "Allow HOLD Mode" -variable XCOps(hold) -onvalue true \
+ -offvalue false -command {xcircuit::config hold $XCOps(hold)}
+ $m add cascade -label "Grid" -menu $m.gridmenu
+ $m add cascade -label "Snap-to" -menu $m.snapmenu
+ $m add cascade -label "Linewidth" -menu $m.linemenu
+ $m add cascade -label "Elements" -menu $m.elementsmenu
+ $m add separator
+ $m add command -label "Help!" -command {xcircuit::helpwindow}
+
+ set m2 [menu $m.gridmenu -tearoff 0]
+ $m2 add check -label "Grid" -variable XCWinOps(${window},showgrid) \
+ -onvalue true -offvalue false \
+ -command {xcircuit::config grid $XCWinOps($XCOps(focus),showgrid); refresh}
+ $m2 add check -label "Axes" -variable XCWinOps(${window},showaxes) \
+ -onvalue true -offvalue false \
+ -command {xcircuit::config axes $XCWinOps($XCOps(focus),showaxes); refresh}
+ $m2 add command -label "Grid Spacing" -command {xcircuit::promptgridspace}
+ $m2 add cascade -label "Grid type/display" -menu $m2.gridsubmenu
+
+ set m3 [menu $m2.gridsubmenu -tearoff 0]
+ $m3 add radio -label "Decimal Inches" -variable XCWinOps(${window},gridstyle) \
+ -value "decimal inches" \
+ -command {xcircuit::config coordstyle "decimal inches"}
+ $m3 add radio -label "Fractional Inches" -variable XCWinOps(${window},gridstyle) \
+ -value "fractional inches" \
+ -command {xcircuit::config coordstyle "fractional inches"}
+ $m3 add radio -label "Centimeters" -variable XCWinOps(${window},gridstyle) \
+ -value "centimeters" -command {xcircuit::config coordstyle "centimeters"}
+ $m3 add radio -label "Internal Units" -variable XCWinOps(${window},gridstyle) \
+ -value "internal units" -command \
+ {xcircuit::config coordstyle "internal units"}
+ $m3 add separator
+ $m3 add command -label "Drawing Scale" -command {xcircuit::promptdrawingscale}
+
+ set m2 [menu $m.snapmenu -tearoff 0]
+ $m2 add check -label "Snap-to" -variable XCWinOps(${window},showsnap) \
+ -onvalue true \
+ -offvalue false -command {xcircuit::config snap \
+ $XCWinOps($XCOps(focus),showsnap); refresh}
+ $m2 add command -label "Snap Spacing" -command {xcircuit::promptsnapspace}
+
+ set m2 [menu $m.linemenu -tearoff 0]
+ $m2 add command -label "Wire Linewidth" -command {xcircuit::promptborderwidth}
+ $m2 add command -label "Global Linewidth" -command {xcircuit::promptlinewidth}
+
+ set m2 [menu $m.elementsmenu -tearoff 0]
+ $m2 add cascade -label "Border" -menu $m2.bordermenu
+ $m2 add cascade -label "Fill" -menu $m2.fillmenu
+ $m2 add cascade -label "Color" -menu $m2.colormenu
+ $m2 add separator
+ $m2 add cascade -label "Parameters" -menu $m2.parammenu
+ $m2 add command -label "Scale" -command {xcircuit::promptelementsize}
+ $m2 add check -label "Center Object" -variable XCWinOps(${window},centerobject) \
+ -onvalue true -offvalue false -command {xcircuit::config centering \
+ $XCWinOps($XCOps(focus),centerobject)}
+ $m2 add check -label "Instance Scale-invariant Linewidth" \
+ -variable XCWinOps(${window},scaleinvariant) \
+ -onvalue invariant -offvalue variant -command {xcircuit::instance linewidth \
+ $XCWinOps($XCOps(focus),scaleinvariant)}
+ $m2 add check -label "Manhattan Draw" \
+ -variable XCWinOps(${window},manhattandraw) \
+ -onvalue true -offvalue false -command {xcircuit::config manhattan \
+ $XCWinOps($XCOps(focus),manhattandraw)}
+ $m2 add check -label "Link Curve Tangents" \
+ -variable XCWinOps(${window},pathedittype) \
+ -onvalue tangents -offvalue normal -command {xcircuit::config pathedit \
+ $XCWinOps($XCOps(focus),pathedittype)}
+ $m2 add cascade -label "Polygon Edit" -menu $m2.polyeditmenu
+
+ set m3 [menu $m2.bordermenu -tearoff 0]
+ $m3 add command -label "Linewidth" -command {xcircuit::promptborderwidth}
+ $m3 add separator
+ $m3 add radio -label "Solid" -variable XCWinOps(${window},linestyle) \
+ -value solid -command {xcircuit::border solid}
+ $m3 add radio -label "Dashed" -variable XCWinOps(${window},linestyle) \
+ -value dashed -command {xcircuit::border dashed}
+ $m3 add radio -label "Dotted" -variable XCWinOps(${window},linestyle) \
+ -value dotted -command {xcircuit::border dotted}
+ $m3 add radio -label "Unbordered" -variable XCWinOps(${window},linestyle) \
+ -value unbordered -command {xcircuit::border unbordered}
+ $m3 add separator
+ $m3 add check -label "Closed" -variable XCWinOps(${window},polyclosed) \
+ -onvalue closed -offvalue unclosed -command \
+ {xcircuit::border $XCWinOps($XCOps(focus),polyclosed)}
+ $m3 add check -label "Square Endcaps" -variable XCWinOps(${window},endcaps) \
+ -onvalue square -offvalue round -command {xcircuit::border \
+ $XCWinOps($XCOps(focus),endcaps)}
+ $m3 add check -label "Bounding Box" -variable XCWinOps(${window},bboxtype) \
+ -onvalue true -offvalue false -command {xcircuit::border bbox \
+ $XCWinOps($XCOps(focus),bboxtype)}
+ $m3 add check -label "Clipmask" -variable XCWinOps(${window},clipmask) \
+ -onvalue true -offvalue false -command {xcircuit::border clipmask \
+ $XCWinOps($XCOps(focus),clipmask)}
+ $m3 add check -label "Manhattan Draw" -variable XCWinOps(${window},manhattandraw) \
+ -onvalue true -offvalue false -command {xcircuit::config manhattan \
+ $XCWinOps($XCOps(focus),manhattandraw)}
+ $m3 add check -label "Manhattan Edit" \
+ -variable XCWinOps(${window},polyedittype) \
+ -onvalue manhattan -offvalue normal \
+ -command {xcircuit::config boxedit \
+ $XCWinOps($XCOps(focus),polyedittype)}
+
+ set m3 [menu $m2.fillmenu -tearoff 0]
+ $m3 add radio -image img_stip100 -variable XCWinOps(${window},fillamount) \
+ -value 100 -command {xcircuit::fill 100 opaque}
+ $m3 add radio -image img_stip88 -variable XCWinOps(${window},fillamount) \
+ -value 88 -command {xcircuit::fill 88 opaque}
+ $m3 add radio -image img_stip75 -variable XCWinOps(${window},fillamount) \
+ -value 75 -command {xcircuit::fill 75 opaque}
+ $m3 add radio -image img_stip62 -variable XCWinOps(${window},fillamount) \
+ -value 62 -command {xcircuit::fill 62 opaque}
+ $m3 add radio -image img_stip50 -variable XCWinOps(${window},fillamount) \
+ -value 50 -command {xcircuit::fill 50 opaque}
+ $m3 add radio -image img_stip38 -variable XCWinOps(${window},fillamount) \
+ -value 38 -command {xcircuit::fill 38 opaque}
+ $m3 add radio -image img_stip25 -variable XCWinOps(${window},fillamount) \
+ -value 25 -command {xcircuit::fill 25 opaque}
+ $m3 add radio -image img_stip12 -variable XCWinOps(${window},fillamount) \
+ -value 12 -command {xcircuit::fill 12 opaque}
+ $m3 add radio -image img_stip0 -variable XCWinOps(${window},fillamount) \
+ -value 0 -command {xcircuit::fill 0 transparent}
+ $m3 add separator
+ $m3 add radio -label "Opaque" -variable XCWinOps(${window},opaque) \
+ -value true -command {xcircuit::fill opaque}
+ $m3 add radio -label "Transparent" -variable XCWinOps(${window},opaque) \
+ -value false -command {xcircuit::fill transparent}
+
+ set m3 [menu $m2.colormenu -tearoff 0]
+ $m3 add command -label "Add New Color" -command {xcircuit::picknewcolor}
+ $m3 add separator
+ $m3 add radio -label "Inherit Color" -variable XCWinOps(${window},colorval) \
+ -value inherit -command {color set inherit}
+
+ set m3 [menu $m2.parammenu -tearoff 0]
+ $m3 add command -label "Manage Parameters" -command {xcircuit::prompteditparams}
+ $m3 add separator
+ $m3 add check -label "X Position" -variable XCWinOps(${window},xposparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),xposparam)} \
+ {xcircuit::parameter make "x position"} \
+ {xcircuit::parameter replace "x position"}}
+ $m3 add check -label "Y Position" -variable XCWinOps(${window},yposparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),yposparam)} \
+ {xcircuit::parameter make "y position"} \
+ {xcircuit::parameter replace "y position"}}
+ $m3 add check -label "Justification" -variable XCWinOps(${window},justparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),justparam)} \
+ {xcircuit::parameter make justification} \
+ {xcircuit::parameter replace justification}}
+ $m3 add check -label "Rotation" -variable XCWinOps(${window},rotationparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),rotationparam)} \
+ {xcircuit::parameter make rotation} \
+ {xcircuit::parameter replace rotation}}
+ $m3 add check -label "Style" -variable XCWinOps(${window},styleparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),styleparam)} \
+ {xcircuit::parameter make style} \
+ {xcircuit::parameter replace style}}
+ $m3 add check -label "Scale" -variable XCWinOps(${window},scaleparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),scaleparam)} \
+ {xcircuit::parameter make scale} \
+ {xcircuit::parameter replace scale}}
+ $m3 add check -label "Linewidth" -variable XCWinOps(${window},linewidthparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),linewidthparam)} \
+ {xcircuit::parameter make linewidth} \
+ {xcircuit::parameter replace linewidth}}
+ $m3 add check -label "Color" -variable XCWinOps(${window},colorparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),colorparam)} \
+ {xcircuit::parameter make color} \
+ {xcircuit::parameter replace color}}
+ $m3 add check -label "Start Angle" -variable XCWinOps(${window},startparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),startparam)} \
+ {xcircuit::parameter make "start angle"} \
+ {xcircuit::parameter replace "start angle"}}
+ $m3 add check -label "End Angle" -variable XCWinOps(${window},endparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),endparam)} \
+ {xcircuit::parameter make "end angle"} \
+ {xcircuit::parameter replace "end angle"}}
+ $m3 add check -label "Radius" -variable XCWinOps(${window},radiusparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),radiusparam)} \
+ {xcircuit::parameter make radius} \
+ {xcircuit::parameter replace radius}}
+ $m3 add check -label "Minor Axis" -variable XCWinOps(${window},minorparam) \
+ -onvalue true -offvalue false -command \
+ {if {$XCWinOps($XCOps(focus),minorparam)} \
+ {xcircuit::parameter make "minor axis"} \
+ {xcircuit::parameter replace "minor axis"}}
+
+ set m3 [menu $m2.polyeditmenu -tearoff 0]
+ $m3 add radio -label "Manhattan Box Edit" \
+ -variable XCWinOps(${window},polyedittype) \
+ -value manhattan -command {xcircuit::config boxedit manhattan}
+ $m3 add radio -label "Rhomboid X" -variable XCWinOps(${window},polyedittype) \
+ -value rhomboidx -command {xcircuit::config boxedit rhomboidx}
+ $m3 add radio -label "Rhomboid Y" -variable XCWinOps(${window},polyedittype) \
+ -value rhomboidy -command {xcircuit::config boxedit rhomboidy}
+ $m3 add radio -label "Rhomboid A" -variable XCWinOps(${window},polyedittype) \
+ -value rhomboida -command {xcircuit::config boxedit rhomboida}
+ $m3 add radio -label "Normal" -variable XCWinOps(${window},polyedittype) \
+ -value normal -command {xcircuit::config boxedit normal}
+
+ set m [menu ${window}.menubar.windowbutton.windowmenu -tearoff 0]
+ $m add command -label "Zoom In" -command {zoom 1.5; refresh}
+ $m add command -label "Zoom Out" -command {zoom [expr {1 / 1.5}]; refresh}
+ $m add command -label "Pan" -command {$XCOps(focus).mainframe.toolbar.bp invoke}
+ $m add command -label "Full View" -command {zoom view; refresh}
+ $m add command -label "Refresh" -command {refresh}
+ $m add separator
+ $m add command -label "Library Directory" -command {xcircuit::library directory}
+ $m add cascade -label "Goto Library" -menu $m.librarymenu
+ $m add separator
+ $m add command -label "Page Directory" -command {xcircuit::page directory}
+ $m add cascade -label "Goto Page" -menu $m.pagemenu
+
+ set m [menu ${window}.menubar.netlistbutton.netlistmenu -tearoff 0]
+ $m add command -label "Make Pin" -command \
+ {set XCWinOps($XCOps(focus),labeltype) "Pin Label"; set \
+ XCWinOps($XCOps(focus),labelimage) img_tp; \
+ $XCOps(focus).mainframe.toolbar.bt invoke}
+ $m add command -label "Make Info Pin" -command \
+ {set XCWinOps($XCOps(focus),labeltype) "Info Label"; set \
+ XCWinOps($XCOps(focus),labelimage) img_ti; \
+ $XCOps(focus).mainframe.toolbar.bt invoke}
+ $m add command -label "Make Global Pin" -command \
+ {set XCWinOps($XCOps(focus),labeltype) "Pin Global"; set \
+ XCWinOps($XCOps(focus),labelimage) img_tg; \
+ $XCOps(focus).mainframe.toolbar.bt invoke}
+ $m add cascade -label "Convert Label To..." -menu $m.pinmenu
+ $m add check -label "Pin Visibility" -variable XCWinOps(${window},pinvisible) \
+ -onvalue true -offvalue false -command {xcircuit::label visible \
+ $XCWinOps($XCOps(focus),pinvisible)}
+ $m add command -label "Make Matching Symbol" -command \
+ {xcircuit::promptmakesymbol [page label]}
+ $m add command -label "Associate With Symbol" -command \
+ {xcircuit::symbol associate}
+ $m add command -label "Highlight Connectivity" -command \
+ {xcircuit::netlist highlight}
+ $m add command -label "Auto-number Components" -command \
+ {xcircuit::netlist autonumber}
+ $m add command -label "Un-number Components" -command \
+ {xcircuit::netlist autonumber -forget}
+ $m add separator
+ $m add check -label "SPICE .end statement" -variable XCOps(spiceend) \
+ -onvalue true -offvalue false
+ $m add check -label "Always regenerate netlists" -variable XCOps(forcenets) \
+ -onvalue true -offvalue false
+ $m add separator
+ $m add command -label "Write SPICE netlist" -command \
+ {if {$XCOps(forcenets)} {xcircuit::netlist update}; \
+ xcircuit::netlist write spice spc $XCOps(spiceend)}
+ $m add command -label "Write flattened SPICE" -command \
+ {if {$XCOps(forcenets)} {xcircuit::netlist update}; \
+ xcircuit::netlist write flatspice fspc}
+ $m add command -label "Write sim" -command \
+ {if {$XCOps(forcenets)} {xcircuit::netlist update}; \
+ xcircuit::netlist write flatsim sim}
+ $m add command -label "Write pcb" -command \
+ {if {$XCOps(forcenets)} {xcircuit::netlist update}; \
+ xcircuit::netlist write pcb pcbnet}
+
+ set m2 [menu $m.pinmenu -tearoff 0]
+ $m2 add command -label "Normal label" -command {xcircuit::label type normal}
+ $m2 add command -label "Local Pin" -command {xcircuit::label type pin}
+ $m2 add command -label "Global Pin" -command {xcircuit::label type global}
+ $m2 add command -label "Info label" -command {xcircuit::label type info}
+
+ #---------------------------------------------------------------------------
+ # Create the cloned menu links used by the toolbar
+ #---------------------------------------------------------------------------
+
+ ${window}.menubar.optionsbutton.optionsmenu.elementsmenu.parammenu \
+ clone ${window}.parammenu
+ ${window}.menubar.optionsbutton.optionsmenu.elementsmenu.colormenu \
+ clone ${window}.colormenu
+ ${window}.menubar.optionsbutton.optionsmenu.elementsmenu.bordermenu \
+ clone ${window}.bordermenu
+ ${window}.menubar.optionsbutton.optionsmenu.elementsmenu.fillmenu \
+ clone ${window}.fillmenu
+
+ .librarymenu clone ${window}.menubar.windowbutton.windowmenu.librarymenu
+ .pagemenu clone ${window}.menubar.windowbutton.windowmenu.pagemenu
+}
+
+#-----------------------------------------------------------------
+# Wrapper procedure to (re)bind a key to a Tcl procedure (Ed Casas 9/4/03)
+# With no arguments, prints a list of bindings to stdout. Key
+# bindings should use "keyaction" to check for text mode, so that
+# rebinding of keys does not prevent text entry. Button bindings
+# do not need this restriction.
+#-----------------------------------------------------------------
+
+proc xcircuit::keybind { {key {}} {proc {}} {window {}} } {
+ global XCOps
+
+ if { $window == {} } { set window $XCOps(focus).mainframe.mainarea.drawing }
+
+ switch -glob -- $key {
+ {} {
+ puts stdout "XCircuit standard key bindings:"
+ puts stdout "Key Binding"
+ puts stdout "-------------------------------------"
+ set kpairs [xcircuit::bindkey]
+ foreach i $kpairs {
+ set pkey [lindex $i 0]
+ set pval [lindex $i 1]
+ puts stdout "$pkey $pval"
+ }
+ puts stdout ""
+ }
+ <[Bb]utton-?> {
+ bind ${window} $key $proc
+ }
+ default {
+ bind ${window} $key "if \{!\[xcircuit::keyaction %k %s\]\} \{ $proc \}"
+ }
+ }
+}
+
+#-----------------------------------------------------------------
+# Enable mouse hints in the window
+#-----------------------------------------------------------------
+
+# James Vernon's mouse button hints
+
+if {[catch {source $XCIRCUIT_SRC_DIR/mousehint.tcl}]} {
+ set XCOps(mousehints) -1
+} else {
+ set XCOps(mousehints) 0
+}
+
+proc xcircuit::enable_mousehints {} {
+ global XCOps
+
+ if {$XCOps(mousehints) == 0} {
+ set XCOps(mousehints) 1
+ foreach window [config windownames] {
+ set frame [winfo top $window]
+ xcircuit::mousehint_create $frame
+ }
+ }
+}
+
+#-----------------------------------------------------------------
+# Final setup stuff before exiting back to interpreter
+#-----------------------------------------------------------------
+
+# This gets rid of the original "wish", in favor of our own window
+
+if {[string range [wm title .] 0 3] == "wish"} {
+ wm withdraw .
+}
+
+#----------------------------------------------------------------------
+# Library and Page menus (common to all windows)
+#----------------------------------------------------------------------
+
+menu .librarymenu -tearoff 0
+.librarymenu add command -label "New Library Page" -command \
+ {xcircuit::promptaddlibrary}
+.librarymenu add separator
+
+menu .pagemenu -tearoff 0
+.pagemenu add command -label "Add New Page" -command {xcircuit::page make}
+.pagemenu add separator
+
+#----------------------------------------------------------------------
+# Source other Tcl scripts, if they exist in the $XCIRCUIT_SRC_DIR path
+# and add the capabilities to the GUI.
+#----------------------------------------------------------------------
+
+# "Write All" feature
+
+catch {source $XCIRCUIT_SRC_DIR/files.tcl}
+
+# Library manager widget
+
+catch {source $XCIRCUIT_SRC_DIR/library.tcl}
+
+# Fancy "Make Matching Symbol" feature
+
+catch {source $XCIRCUIT_SRC_DIR/symbol.tcl}
+
+# Help window
+
+catch {source $XCIRCUIT_SRC_DIR/xchelp.tcl}
+
+# EDIF file parser
+
+catch {source $XCIRCUIT_SRC_DIR/edif.tcl}
+
+# System Clipboard paste into labels
+
+catch {source $XCIRCUIT_SRC_DIR/selection.tcl}
+
+# Regexp label substitutions and auto-increment feature
+
+catch {source $XCIRCUIT_SRC_DIR/text.tcl}
+
+# Wim Vereecken's Matlab PostScript import function
+
+catch {source $XCIRCUIT_SRC_DIR/matgen.tcl}
+
+#----------------------------------------------------------------------
+# Create the initial window.
+#----------------------------------------------------------------------
+
+xcircuit::new_window $XCOps(focus)
+
+#----------------------------------------------------------------------
+# Add buttons for the pre-allocated pages
+#----------------------------------------------------------------------
+
+xcircuit::newpagebutton "Page 1" 1
+xcircuit::newpagebutton "Page 2" 2
+xcircuit::newpagebutton "Page 3" 3
+xcircuit::newpagebutton "Page 4" 4
+xcircuit::newpagebutton "Page 5" 5
+xcircuit::newpagebutton "Page 6" 6
+xcircuit::newpagebutton "Page 7" 7
+xcircuit::newpagebutton "Page 8" 8
+xcircuit::newpagebutton "Page 9" 9
+xcircuit::newpagebutton "Page 10" 10
+
+#----------------------------------------------------------------------
+# Add buttons for the pre-allocated libraries
+#----------------------------------------------------------------------
+
+xcircuit::newlibrarybutton "User Library"
+
+#-----------------------------------------------------------------
+# New key bindings should pass through this function so that key
+# strokes are captured correctly for label editing.
+#----------------------------------------------------------------------
+
+proc xcircuit::keyaction {keycode {keystate 0}} {
+ switch -- [eventmode] {
+ text -
+ etext -
+ cattext {
+ standardaction $keycode down $keystate
+ return true
+ }
+ }
+ return false
+}
+
+#-----------------------------------------------------------------
+
+proc scrollboth { lists args } {
+ foreach l $lists {
+ eval {$l yview} $args
+ }
+}
+
+#-----------------------------------------------------------------
+# Procedure to generate the help window
+#-----------------------------------------------------------------
+
+proc xcircuit::makehelpwindow {} {
+ toplevel .help -bg beige
+ wm group .help .
+ wm withdraw .help
+
+ frame .help.title -bg beige
+ frame .help.listwin
+
+ pack .help.title -side top -fill x
+ pack .help.listwin -side top -fill both -expand true
+
+ label .help.title.field -text "XCircuit Help" -bg beige
+ button .help.title.dbut -text "Dismiss" -bg beige -command {wm withdraw .help}
+ pack .help.title.field -side left -padx 10
+ pack .help.title.dbut -side right -ipadx 10
+
+ listbox .help.listwin.func -yscrollcommand ".help.listwin.sb set" \
+ -setgrid 1 -height 20
+ listbox .help.listwin.keys -yscrollcommand ".help.listwin.sb set" \
+ -setgrid 1 -height 20
+ scrollbar .help.listwin.sb -orient vertical -command \
+ [list scrollboth [list .help.listwin.func .help.listwin.keys]]
+ message .help.listwin.win -width 200 -justify left -anchor n \
+ -relief groove -text "Click on a function for help text"
+
+ grid .help.listwin.func -row 0 -column 0 -sticky news -padx 1 -pady 1
+ grid .help.listwin.keys -row 0 -column 1 -sticky news -padx 1 -pady 1
+ grid .help.listwin.sb -row 0 -column 2 -sticky ns -padx 1 -pady 1
+ grid .help.listwin.win -row 0 -column 3 -sticky news -padx 1 -pady 1
+
+ grid columnconfigure .help.listwin 1 -weight 1 -minsize 100
+ grid rowconfigure .help.listwin 0 -weight 1 -minsize 100
+
+ bind .help.listwin.func <ButtonRelease-1> "xcircuit::printhelp"
+}
+
+#-----------------------------------------------------------------
+# Procedure to update and display the help window
+#-----------------------------------------------------------------
+
+proc xcircuit::helpwindow {} {
+
+ # Create the help window if it doesn't exist
+ if {[catch {wm state .help}]} {
+ xcircuit::makehelpwindow
+ }
+ set wstate [xcircuit::getinitstate .help]
+
+ .help.listwin.func delete 0 end
+ .help.listwin.keys delete 0 end
+
+ set k [lsort -dictionary [xcircuit::bindkey]]
+
+ .help.listwin.func insert end "Function"
+ .help.listwin.keys insert end "Keys"
+ .help.listwin.func insert end ""
+ .help.listwin.keys insert end ""
+
+ foreach i $k {
+ set pkeys [xcircuit::bindkey -func $i]
+ .help.listwin.func insert end "$i"
+ .help.listwin.keys insert end "$pkeys"
+ }
+
+ if {"$wstate" != "normal"} {
+ wm deiconify .help
+ xcircuit::centerwin .help
+ }
+ raise .help
+}
+
+#-----------------------------------------------------------------
+# Prevent "Tab" from removing focus from the window during text edits,
+# but allow it to take its normal meaning at other times.
+#-----------------------------------------------------------------
+
+bind all <Tab> {
+ switch -- [eventmode] {
+ text -
+ etext -
+ cattext {}
+ default {tk::TabToWindow [tk_focusNext %W]}
+ }
+}
+
+bind all <<PrevWindow>> {
+ switch -- [eventmode] {
+ text -
+ etext -
+ cattext {}
+ default {tk::TabToWindow [tk_focusPrev %W]}
+ }
+}
+
+#-----------------------------------------------------------------
+# Wait for the drawing area to become visible, and set the focus on it.
+# Invoke the "wire" button so we have a default button1 action.
+#-----------------------------------------------------------------
+
+tkwait visibility $XCOps(focus).mainframe.mainarea.drawing
+focus -force $XCOps(focus).mainframe.mainarea.drawing
+
+#-----------------------------------------------------------------
+# This pops down the interpreter window, if the "console.tcl" script was run.
+#-----------------------------------------------------------------
+
+catch xcircuit::consoledown
+
+#-----------------------------------------------------------------
+# End of GUI configuration file. Xcircuit continues to load the xcircuit
+# startup configuration files.
+#-----------------------------------------------------------------
diff --git a/lib/tcl/xchelp.tcl b/lib/tcl/xchelp.tcl
new file mode 100644
index 0000000..b3f33fe
--- /dev/null
+++ b/lib/tcl/xchelp.tcl
@@ -0,0 +1,450 @@
+#-----------------------------------------------------------------
+# Procedures to generate and display a help window in xcircuit
+#-----------------------------------------------------------------
+
+proc xcircuit::printhelp {} {
+ set csel [.help.listwin.func curselection]
+ if {$csel == ""} {return}
+ set key [.help.listwin.func get $csel]
+ switch -glob $key {
+ {Page} {.help.listwin.win configure -text \
+ "Switch to the indicated page."}
+ {Justify} {.help.listwin.win configure -text \
+ "Change justification of the currently selected or\
+ edited label."}
+ {Text Delete} {.help.listwin.win configure -text \
+ "When editing a label, delete one character."}
+ {Text Return} {.help.listwin.win configure -text \
+ "When editing a label, accept edits and return to normal drawing mode."}
+ {Text Left} {.help.listwin.win configure -text \
+ "When editing a label, move cursor left one character or procedure."}
+ {Text Right} {.help.listwin.win configure -text \
+ "When editing a label, move cursor right one character or procedure."}
+ {Text Up} {.help.listwin.win configure -text \
+ "When editing a multi-line label, move cursor up one line of text."}
+ {Text Down} {.help.listwin.win configure -text \
+ "When editing a multi-line label, move cursor down one line of text."}
+ {Text Split} {.help.listwin.win configure -text \
+ "When editing a label, split the label into two separate labels at\
+ the cursor position."}
+ {Text Home} {.help.listwin.win configure -text \
+ "When editing a label, move cursor to the beginning of the label."}
+ {Text End} {.help.listwin.win configure -text \
+ "When editing a label, move cursor to the end of the label."}
+ {Tab Forward} {.help.listwin.win configure -text \
+ "When editing a label, move forward to the next defined tab stop."}
+ {Tab Backward} {.help.listwin.win configure -text \
+ "When editing a label, move backward to the previously defined tab stop."}
+ {Tab Stop} {.help.listwin.win configure -text \
+ "When editing a label, declare a tab stop at the current horizontal cursor\
+ position. This may be used to align text in multiple lines to certain\
+ positions."}
+ {Superscript} {.help.listwin.win configure -text \
+ "When editing a label, make text superscripted (about 2/3 size, and\
+ raised about half a line)."}
+ {Subscript} {.help.listwin.win configure -text \
+ "When editing a label, make text subscripted (about 2/3 size, and\
+ lowered about 3/4 of a line)."}
+ {Normalscript} {.help.listwin.win configure -text \
+ "When editing a label, return from a subscript or superscript alignment\
+ to a normal text alignment."}
+ {Nextfont} {.help.listwin.win configure -text \
+ "When editing a label, change the font at the cursor position to the\
+ next font family in the list. This will cycle through all of the\
+ defined fonts if executed repeatedly."}
+ {Boldfont} {.help.listwin.win configure -text \
+ "When editing a label, change the current font family to a boldface\
+ type, if available."}
+ {Italicfont} {.help.listwin.win configure -text \
+ "When editing a label, change the current font family to an italic\
+ or slanted type, if available."}
+ {Normalfont} {.help.listwin.win configure -text \
+ "When editing a label, change the current font family to a regular\
+ type (non-italic, non-bold)."}
+ {Underline} {.help.listwin.win configure -text \
+ "When editing a label, begin underlining the text."}
+ {Overline} {.help.listwin.win configure -text \
+ "When editing a label, begin overlining the text."}
+ {ISO Encoding} {.help.listwin.win configure -text \
+ "When editing a label, change the font encoding from normal to ISO."}
+ {Linebreak} {.help.listwin.win configure -text \
+ "When editing a label, append a linebreak to the label. This generates\
+ multi-line text."}
+ {Halfspace} {.help.listwin.win configure -text \
+ "When editing a label, insert a half-space."}
+ {Quarterspace} {.help.listwin.win configure -text \
+ "When editing a label, insert a quarter-space."}
+ {Special} {.help.listwin.win configure -text \
+ "When editing a label, insert a special character. This is a command\
+ that brings up the font encoding array, allowing the user to select\
+ any character from the current font in the current encoding type."}
+ {Parameter} {.help.listwin.win configure -text \
+ "When editing a label, insert a parameter. The parameter must first\
+ exist in the current object. If only one parameter is defined, it\
+ will be inserted. If more than one parameter is defined, a selection\
+ box will appear, allowing the user to select which parameter to\
+ insert into the text."}
+ {Parameterize Point} {.help.listwin.win configure -text \
+ "When editing a polygon, parameterize the X and Y position of the\
+ currently edited point. The point may then be at a different\
+ position in different instances of the current object."}
+ {Break at Point} {.help.listwin.win configure -text \
+ "When editing a polygon, break the polygon into two pieces at\
+ the currently edited point."}
+ {Delete Point} {.help.listwin.win configure -text \
+ "When editing a polygon, remove the currently edited point, and\
+ move to the next point."}
+ {Insert Point} {.help.listwin.win configure -text \
+ "When editing a polygon, insert a point at the same position as\
+ the currently edited point."}
+ {Append Point} {.help.listwin.win configure -text \
+ "When editing a polygon, append a point at the same position as\
+ the currently edited point, and move the currently edited point\
+ to the new point."}
+ {Next Point} {.help.listwin.win configure -text \
+ "When editing a polygon, move to the next point."}
+ {Attach} {.help.listwin.win configure -text \
+ "When editing a polygon, select the nearest element that is not\
+ the polygon, and force the currently edited point to terminate\
+ on that element. The element to attach to may be a polygon, an\
+ arc, a spline, or a path. The edit point will continue to follow\
+ the cursor within the constraint that it must remain connected to\
+ the other element."}
+ {Virtual Copy} {.help.listwin.win configure -text \
+ "Create a virtual library instance of the currently selected\
+ object instance. This will duplicate the existing library entry\
+ but will have the scale and rotation of the selected instance,\
+ as well as any non-default parameters given to that instance."}
+ {Next Library} {.help.listwin.win configure -text \
+ "When on a library page, go to the next defined library. The\
+ User Library is always last, and then the function cycles back\
+ to the first defined library."}
+ {Library Directory} {.help.listwin.win configure -text \
+ "Go to the master list of libraries."}
+ {Library Copy} {.help.listwin.win configure -text \
+ "When on a library page, select the object under the cursor and\
+ any selected objects, and return to the originating page in\
+ copy mode."}
+ {Library Edit} {.help.listwin.win configure -text \
+ "When on a library page, edit the name of an object by editing\
+ the text label underneath the picture of the object."}
+ {Library Delete} {.help.listwin.win configure -text \
+ "When on a library page, remove the selected object from the\
+ library. An object can be removed only if there are no instances\
+ of that object on any page or in the hierarchy of another object.\
+ A removed object is destroyed and cannot be recovered."}
+ {Library Duplicate} {.help.listwin.win configure -text \
+ "When on a library page, create a duplicate object of the selected\
+ object, placing it in the User Library."}
+ {Library Hide} {.help.listwin.win configure -text \
+ "When on a library page, remove the selected object from view but\
+ do not destroy it. An object can be hidden from view only if\
+ it exists in the hierarchy of another object (such as the arrow
+ object inside the current source object)."}
+ {Library Virtual Copy} {.help.listwin.win configure -text \
+ "When on a library page, create a duplicate instance of the\
+ selected object. The duplicate instance may have different\
+ (instanced) parameters. Default parameters are defined by\
+ the master object. The name of the master object is printed\
+ in black, while the names of virtual instances are in gray.\
+ To define a virtual copy with different scale or rotation,\
+ use the (non-Library) Virtual Copy function."}
+ {Library Move} {.help.listwin.win configure -text \
+ "When on a library page, move the position of an object relative\
+ to other objects. If one object is selected, it will be moved\
+ to the position nearest the cursor. If two objects are selected,\
+ their positions will be swapped. If in the Page Directory, the\
+ relative positions of pages may be changed with the same function."}
+ {Library Pop} {.help.listwin.win configure -text \
+ "When on a library page, return to the originating page."}
+ {Page Directory} {.help.listwin.win configure -text \
+ "Go to the master list of pages."}
+ {Help} {.help.listwin.win configure -text \
+ "Display the window of help information and key bindings."}
+ {Redraw} {.help.listwin.win configure -text \
+ "Redraw everything in the window."}
+ {View} {.help.listwin.win configure -text \
+ "Scale and position the view of the current page so that elements\
+ on the page fill the window to the maximum extent possible (minus\
+ small margins on all sides)."}
+ {Zoom In} {.help.listwin.win configure -text \
+ "Increase the magnification of the view of the current page in\
+ the window. The location of the page at the center point of the\
+ window remains at the center."}
+ {Zoom Out} {.help.listwin.win configure -text \
+ "Decrease the magnification of the view of the current page in\
+ the window. The location of the page at the center point of the\
+ window remains at the center."}
+ {Pan} {.help.listwin.win configure -text \
+ "Change the view of the current page. There are various modes,\
+ including here, center, left, right, up, down, and follow. Pan\
+ center changes the view such that the point nearest\
+ the cursor becomes the center point of the window. Pan up, down,\
+ right, and left change the view by one-half page in the indicated\
+ direction."}
+ {Double Snap} {.help.listwin.win configure -text \
+ "Increase the spacing between snap points by a factor of two."}
+ {Halve Snap} {.help.listwin.win configure -text \
+ "Decrease the spacing between snap points by half."}
+ {Write} {.help.listwin.win configure -text \
+ "Display the Output Properties and File Write window. If output\
+ properties are changed but user does not want to write the file\
+ (such as when attaching multiple pages or schematics), use the\
+ Cancel button to accept all applied changes and pop down the\
+ window without writing."}
+ {Rotate} {.help.listwin.win configure -text \
+ "Rotate the selected elements, or element nearest the cursor, by\
+ the number of degrees in the argument. A positive number indicates\
+ a clockwise rotation, a negative number, a counterclockwise\
+ rotation."}
+ {Flip X} {.help.listwin.win configure -text \
+ "Flip the selected elements, or element nearest the cursor, in the\
+ horizontal (X) direction (that is, across the Y axis). The axis\
+ defining the flip is the vertical line passing through the cursor X\
+ position."}
+ {Flip Y} {.help.listwin.win configure -text \
+ "Flip the selected elements, or element nearest the cursor, in the\
+ vertical (Y) direction (that is, across the X axis). The axis\
+ defining the flip is the horizontal line passing through the cursor\
+ Y position."}
+ {Snap} {.help.listwin.win configure -text \
+ "Snap the selected elements, or element nearest the cursor, to the\
+ nearest point on the snap grid. Each point of a polygon is snapped.\
+ Spline control points and arc centers are snapped. Label and object\
+ instance reference positions are snapped."}
+ {Pop} {.help.listwin.win configure -text \
+ "Return from editing an object (return from the last push)."}
+ {Push} {.help.listwin.win configure -text \
+ "Edit the object represented by the selected object instance, or the\
+ object instance closest to the cursor. The current page is pushed\
+ onto a stack, and the object becomes the current page."}
+ {Delete} {.help.listwin.win configure -text \
+ "Delete the selected elements or element closest to the cursor."}
+ {Select} {.help.listwin.win configure -text \
+ "Select the element or elements near the cursor. If multiple\
+ elements match the selection criteria, an interactive method is\
+ initiated in which individual elements may be selected or rejected\
+ by pressing the mouse buttons 2 or 3, respectively."}
+ {Box} {.help.listwin.win configure -text \
+ "Begin drawing a box in the current default style. One corner of\
+ the box is anchored at the cursor position, and the other corner\
+ dragged with the cursor. The box is completed by pressing buttons\
+ 1 or 2 or canceled with button 3."}
+ {Arc} {.help.listwin.win configure -text \
+ "Begin drawing a circle in the current default style. The center\
+ of the circle is anchored at the cursor position, and the radius\
+ is defined by dragging the cursor to the desired position. Button\
+ 2 completes the arc, and button 3 cancels it. Button 1 switches\
+ from defining the arc radius to (in sequence) defining the arc\
+ start and stop angles, and defining the ellipse minor axis."}
+ {Text} {.help.listwin.win configure -text \
+ "Begin a normal text label. In text edit mode, all keystrokes are\
+ interpreted as input to the label, except for the key that is bound\
+ to action Text Return. Mouse buttons 1 and 2 complete the text\
+ label, while button 3 cancels (deletes) the label."}
+ {Exchange} {.help.listwin.win configure -text \
+ "If two elements are selected, their relative positions (drawing\
+ order) are swapped (drawing order determines what objects obscure\
+ other objects when overlapping). If one element is selected, it\
+ is brought to the front of the drawing, unless it is already at\
+ the front, in which case it is sent to the back."}
+ {Copy} {.help.listwin.win configure -text \
+ "Make a copy of the selected elements or element closest to the\
+ cursor. Elements are dragged as a group with the cursor. Mouse\
+ button 1 places the copies, creates a new set of copies, and\
+ continues the copy operation. Mouse button 2 places the copies\
+ and ends the copy operation. Mouse button 3 removes the current\
+ selection being dragged and completes the copy operation."}
+ {Move} {.help.listwin.win configure -text \
+ "Move the selected elements or element nearest the cursor. This\
+ function is normally handled by the mouse button press, not the\
+ Move binding."}
+ {Join} {.help.listwin.win configure -text \
+ "Join selected elements into a single element. If all of the selected\
+ elements are polygons, the new element will be a single polygon. If\
+ the selected elements include a mixture of one or more types\
+ (polygons, arcs, splines, and paths), the resulting type will be a\
+ path."}
+ {Unjoin} {.help.listwin.win configure -text \
+ "Break the selected path or path nearest the cursor into its\
+ constituent elements. This operation applies only to paths."}
+ {Spline} {.help.listwin.win configure -text \
+ "Begin a bezier curve (inconsistently and, technically, incorrectly\
+ referred to in XCircuit documentation as a spline). The curve is\
+ anchored at the cursor position, and the other endpoint of the\
+ curve is dragged with the cursor. Mouse button 2 completes the\
+ curve. Mouse button 3 cancels (deletes) the curve. Mouse button\
+ 1 switches between the two endpoints and two control points."}
+ {Edit} {.help.listwin.win configure -text \
+ "Edit the selected element or element nearest the cursor. The\
+ edit function applies to polygons, arcs, splines, paths, and\
+ labels, but not to object instances (editing the instance implies\
+ editing the object itself, which requires the Push function).\
+ Editing a label, arc, or spline is the same as creating it.\
+ Editing a polygon (including boxes and wires) allows individual\
+ points to be selected and moved. In all cases except labels,\
+ mouse button 1 moves to the next point, mouse button 2 completes\
+ the edit, and mouse button 3 cancels the last edit maneuver."}
+ {Undo} {.help.listwin.win configure -text \
+ "Undo the last action. Note that not all actions are undoable."}
+ {Redo} {.help.listwin.win configure -text \
+ "Perform again the last action which was undone with the Undo\
+ function."}
+ {Select Save} {.help.listwin.win configure -text \
+ "Take all of the selected elements and turn them into a new\
+ object. The individual elements will be removed from the page\
+ and replaced with an instance of the newly defined object, and\
+ the object itself will be placed in the User Library. The\
+ user will be prompted for a name of the new library object."}
+ {Unselect} {.help.listwin.win configure -text \
+ "Remove the element closest to the cursor from the list of\
+ currently selected objects."}
+ {Dashed} {.help.listwin.win configure -text \
+ "Set the border style of the selected elements or element\
+ closest to the cursor to a dashed line."}
+ {Dotted} {.help.listwin.win configure -text \
+ "Set the border style of the selected elements or element\
+ closest to the cursor to a dotted line."}
+ {Solid} {.help.listwin.win configure -text \
+ "Set the border style of the selected elements or element\
+ closest to the cursor to a solid line."}
+ {Prompt} {.help.listwin.win configure -text \
+ "Generate the TCL command prompt."}
+ {Dot} {.help.listwin.win configure -text \
+ "Create a solder dot, connecting wires passing through it. The\
+ dot is placed at the current cursor position. If a library\
+ object named dot exists, it is used."}
+ {Wire} {.help.listwin.win configure -text \
+ "Begin drawing a wire (or unclosed polygon). The wire is anchored\
+ at the cursor position, and the other end is dragged with the\
+ cursor. Mouse button 1 anchors the endpoint and starts a new\
+ wire segment. Mouse button 2 anchors the endpoint and completes\
+ the wire. Mouse button 3 deletes the last anchored point."}
+ {Nothing} {.help.listwin.win configure -text \
+ "Null function. Does nothing."}
+ {Exit} {.help.listwin.win configure -text \
+ "Exit the program immediately without prompting for action on\
+ pages which have been changed but not saved."}
+ {Start} {.help.listwin.win configure -text \
+ "General-purpose start function, normally associated with mouse\
+ button 1."}
+ {Finish} {.help.listwin.win configure -text \
+ "General-purpose completion function, normally associated with mouse\
+ button 2."}
+ {Cancel} {.help.listwin.win configure -text \
+ "General-purpose cancelation function, normally associated with mouse\
+ button 3."}
+ {Snap To} {.help.listwin.win configure -text \
+ "Toggle the state of the snapping function. If on, points and element\
+ positions are always snapped to the snap grid. If off, points and\
+ element position are unconstrained."}
+ {Netlist} {.help.listwin.win configure -text \
+ "Generate a netlist of the default type."}
+ {Swap} {.help.listwin.win configure -text \
+ "Switch between editing a schematic and its symbol. If the schematic\
+ covers multiple pages, will switch between the secondary page, primary\
+ page, and symbol."}
+ {Pin Label} {.help.listwin.win configure -text \
+ "Create a local pin, a label that is interpreted as\
+ the primary name of the network to which it is attached."}
+ {Pin Global} {.help.listwin.win configure -text \
+ "Create a global pin, a label that is interpreted as\
+ belonging to the same network whereever it occurs on\
+ the schematic."}
+ {Info Label} {.help.listwin.win configure -text \
+ "Create an info label, a label that is not displayed\
+ except when editing the object, and which is parsed\
+ to extract information on how to output the device in\
+ a netlist."}
+ {Connectivity} {.help.listwin.win configure -text \
+ "Highlight the connectivity of the electrical network\
+ that includes the selected item or that is closest\
+ to the cursor. Item must be a valid network element."}
+ {Sim} {.help.listwin.win configure -text \
+ "Generate a .sim (flat) netlist from the current page schematic,\
+ especially for use with the IRSIM simulator and the netgen and\
+ gemini LVS netlist comparators."}
+ {SPICE} {.help.listwin.win configure -text \
+ "Generate a .spc (hierarchical) netlist from the current page\
+ schematic. The format is compatible with Berkeley spice3 and\
+ tclspice."}
+ {PCB} {.help.listwin.win configure -text \
+ "Generate a .pcbnet netlist from the current page schematic.\
+ This format is compatible with the pcb layout program."}
+ {SPICE Flat} {.help.listwin.win configure -text \
+ "Generate a .fspc (flattened) SPICE netlist from the current\
+ page schematic."}
+ {default} {.help.listwin.win configure -text ""}
+ }
+}
+
+#-----------------------------------------------------------------
+# Procedure to generate the help window
+#-----------------------------------------------------------------
+
+proc xcircuit::makehelpwindow {} {
+ toplevel .help -bg beige
+ wm withdraw .help
+
+ frame .help.title -bg beige
+ frame .help.listwin
+
+ pack .help.title -side top -fill x
+ pack .help.listwin -side top -fill both -expand true
+
+ label .help.title.field -text "XCircuit Help" -bg beige
+ button .help.title.dbut -text "Dismiss" -bg beige -command {wm withdraw .help}
+ pack .help.title.field -side left -padx 10
+ pack .help.title.dbut -side right -ipadx 10
+
+ listbox .help.listwin.func -yscrollcommand ".help.listwin.sb set" \
+ -setgrid 1 -height 20
+ listbox .help.listwin.keys -yscrollcommand ".help.listwin.sb set" \
+ -setgrid 1 -height 20
+ scrollbar .help.listwin.sb -orient vertical -command \
+ [list scrollboth [list .help.listwin.func .help.listwin.keys]]
+ message .help.listwin.win -width 200 -justify left -anchor n \
+ -relief groove -text "Click on a function for help text"
+
+ grid .help.listwin.func -row 0 -column 0 -sticky news -padx 1 -pady 1
+ grid .help.listwin.keys -row 0 -column 1 -sticky news -padx 1 -pady 1
+ grid .help.listwin.sb -row 0 -column 2 -sticky ns -padx 1 -pady 1
+ grid .help.listwin.win -row 0 -column 3 -sticky news -padx 1 -pady 1
+
+ grid columnconfigure .help.listwin 1 -weight 1 -minsize 100
+ grid rowconfigure .help.listwin 0 -weight 1 -minsize 100
+
+ bind .help.listwin.func <ButtonRelease-1> "xcircuit::printhelp"
+}
+
+#-----------------------------------------------------------------
+# Procedure to update and display the help window
+#-----------------------------------------------------------------
+
+proc xcircuit::helpwindow {} {
+
+ # Create the help window if it doesn't exist
+ if {[catch {wm state .help}]} {
+ xcircuit::makehelpwindow
+ }
+
+ .help.listwin.func delete 0 end
+ .help.listwin.keys delete 0 end
+
+ set k [lsort -dictionary [xcircuit::bindkey]]
+
+ .help.listwin.func insert end "Function"
+ .help.listwin.keys insert end "Keys"
+ .help.listwin.func insert end ""
+ .help.listwin.keys insert end ""
+
+ foreach i $k {
+ set pkeys [xcircuit::bindkey -func $i]
+ .help.listwin.func insert end "$i"
+ .help.listwin.keys insert end "$pkeys"
+ }
+
+ wm deiconify .help
+}
+
+#-----------------------------------------------------------------
diff --git a/lib/tcl/xcircuit.bat.in b/lib/tcl/xcircuit.bat.in
new file mode 100644
index 0000000..8b78f73
--- /dev/null
+++ b/lib/tcl/xcircuit.bat.in
@@ -0,0 +1,34 @@
+@echo off
+rem
+rem This script starts xcircuit under the Tcl interpreter,
+rem reading commands from a special .wishrc script which
+rem launches magic and retains the Tcl interactive interpreter.
+rem
+
+set XCIRCUIT_LIB_DIR=XCLIBDIR
+set XCIRCUIT_WISH=WISH_EXE
+
+set loclibdir=%XCIRCUIT_LIB_DIR%
+
+set TKCON=1
+for %%i in (%*) do (
+ if "%%i" == "-noconsole" set TKCON=0
+)
+
+if "%TKCON%" == "1" (
+
+ if not exist %loclibdir%/CONSOLE set loclibdir=%loclibdir%/tcl
+
+ start %XCIRCUIT_WISH% %loclibdir%/CONSOLE -eval "source %loclibdir%/CONSOLE_SCRIPT" -slave "package require Tk; set argv [list %*]; set argc [llength argv]; source %loclibdir%/WRAPPER_INIT"
+
+) else (
+
+
+rem Run the stand-in for wish (xcircexec), which acts exactly like "wish"
+rem except that it replaces ~/.wishrc with xcircuit.tcl. This executable is
+rem *only* needed when running without the console; the console itself is
+rem capable of sourcing the startup script.
+
+ %loclibdir%/xcircexec -- %*
+
+)
diff --git a/lib/tcl/xcircuit.sh.in b/lib/tcl/xcircuit.sh.in
new file mode 100755
index 0000000..d9800c2
--- /dev/null
+++ b/lib/tcl/xcircuit.sh.in
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# This script starts xcircuit under the Tcl interpreter,
+# reading commands from a special .wishrc script which
+# launches xcircuit and retains the Tcl interactive interpreter.
+#
+
+loclibdir=${XCIRCUIT_LIB_DIR:=XCLIBDIR}
+export XCIRCUIT_LIB_DIR
+XCIRCUIT_WISH=WISH_EXE
+export XCIRCUIT_WISH
+
+# Hacks for Cygwin
+if [ ${TERM:=""} = "cygwin" ]; then
+ export PATH=$PATH:TCLLIBDIR
+ export DISPLAY=${DISPLAY:=":0"}
+fi
+
+TKCON=true
+for i in $@ ; do
+ case $i in
+ -noc*)
+ TKCON=;;
+ --help)
+ echo "Standard usage:"
+ echo " xcircuit [filename]"
+ echo "Online documentation:"
+ echo " http://opencircuitdesign.com/xcircuit"
+ exit 0
+ ;;
+ --version)
+ echo "XCircuit version PROG_VERSION revision PROG_REVISION"
+ exit 0
+ ;;
+ esac
+done
+
+if [ $TKCON ]; then
+
+ if [ ! -f ${loclibdir}/CONSOLE ]; then
+ loclibdir=${loclibdir}/tcl
+ fi
+
+ exec ${loclibdir}/CONSOLE \
+ -eval "source ${loclibdir}/CONSOLE_SCRIPT" \
+ -slave "package require Tk; set argc $#; set argv [list $*]; \
+ source ${loclibdir}/WRAPPER_INIT"
+else
+
+#
+# Run the stand-in for wish (xcircexec), which acts exactly like "wish"
+# except that it replaces ~/.wishrc with xcircuit.tcl. This executable is
+# *only* needed when running without the console; the console itself is
+# capable of sourcing the startup script.
+#
+ exec ${loclibdir}/xcircexec -- $@
+
+fi
diff --git a/lib/tcl/xcircuit.tcl.in b/lib/tcl/xcircuit.tcl.in
new file mode 100755
index 0000000..3d4504b
--- /dev/null
+++ b/lib/tcl/xcircuit.tcl.in
@@ -0,0 +1,261 @@
+# Wishrc startup for ToolScript (xcircuit)
+#
+# Loads the shared object (xcircuit.so) file into Tcl, runs the
+# wrapper script to generate the GUI, then runs the initialization
+# routine for the XCircuit package.
+
+global XCOps
+
+set envlibdir [array get env "XCIRCUIT_LIB_DIR"]
+if {$envlibdir == {}} {
+ set XCIRCUIT_LIB_DIR LIBDIR
+}
+unset envlibdir
+
+set envsrcdir [array get env "XCIRCUIT_SRC_DIR"]
+if {$envsrcdir != {}} {
+ set path [lindex $envsrcdir 1]
+} else {
+ set path SCRIPTSDIR
+ set XCIRCUIT_SRC_DIR $path
+}
+unset envsrcdir
+
+if {[string compare $tcl_platform(platform) "windows"] == 0} {
+ set libext .dll
+} else {
+ set libext .so
+}
+
+set tcllibdir $path
+if {![file exists ${tcllibdir}/xcircuit$libext]} {
+ set tcllibdir ${path}/tcl
+}
+if {![file exists ${tcllibdir}/xcircuit$libext]} {
+ puts stderr "Error: Cannot find file xcircuit$libext"
+}
+load ${tcllibdir}/xcircuit$libext
+
+package require Xcircuit
+
+# It is important to make sure no magic commands overlap with Tcl built-in
+# commands, because otherwise the namespace import will fail.
+
+proc pushnamespace { name } {
+
+ set y [namespace eval ${name} info commands ::${name}::*]
+ set z [info commands]
+
+ foreach v $y {
+ regsub -all {\*} $v {\\*} i
+ set x [namespace tail $i]
+ if {[lsearch $z $x] < 0} {
+ namespace import $i
+ } else {
+ puts "Warning: ${name} command '$x' use fully-qualified name '$v'"
+ }
+ }
+}
+
+proc popnamespace { name } {
+ set z [info commands]
+ set l [expr [string length ${name}] + 5]
+
+ while {[set v [lsearch $z ${name}_tcl_*]] >= 0} {
+ set y [lindex $z $v]
+ set w [string range $y $l end]
+ interp alias {} ::$w {}
+ rename ::$y ::$w
+ puts "Info: replacing ::$w with ::$y"
+ }
+ namespace forget ::${name}::*
+}
+
+set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front
+
+# Have we called xcircuit from tkcon?
+
+if {[lsearch [interp aliases] tkcon] != -1} {
+ set XcConsole tkcon
+ wm withdraw .
+
+ # Rename conflicting TkCon commands before pushing xcircuit's namespace
+
+ if {[lsearch [info commands] orig_edit] < 0} { rename edit orig_edit }
+} else {
+
+ # Extend the "unknown" command-line handler to be compatible with the
+ # way we have renamed certain core Tcl/Tk functions.
+
+ rename unknown tcl_unknown
+ proc unknown { args } {
+ # CAD tools special:
+ # Check for commands which were renamed to tcl_(command)
+
+ set cmd [lindex $args 0]
+ if {[lsearch [info commands] tcl_$cmd] >= 0} {
+ set arglist [concat tcl_$cmd [lrange $args 1 end]]
+ set ret [catch {eval $arglist} result]
+ if {$ret == 0} {
+ return $result
+ } else {
+ return -code $ret -errorcode $errorCode $result
+ }
+ }
+ return [eval [concat tcl_unknown $args]]
+ }
+}
+
+# Rename conflicting Tcl/Tk commands before pushing xcircuit's namespace
+
+if {[lsearch [info commands] tcl_label] < 0} { rename label tcl_label }
+
+# Allow commands in the xcircuit namespace to be called from the toplevel namespace
+
+pushnamespace xcircuit
+
+#----------------------------------------------------------------------
+# Cross-Application section
+#----------------------------------------------------------------------
+
+# Check namespaces for existence of other applications
+set UsingMagic 0
+set UsingIRSIM 0
+set UsingNetgen 0
+set nlist [namespace children]
+foreach i $nlist {
+ switch $i {
+ ::magic { set UsingMagic 1 }
+ ::irsim { set UsingIRSIM 1 }
+ ::netgen { set UsingNetgen 1 }
+ }
+}
+
+# Setup IRSIM assuming that the Tcl version is installed.
+# We do not need to rename procedure irsim to NULL because it is
+# redefined in a script, which simply overwrites the original.
+
+proc irsim { args } {
+ global CAD_ROOT
+ set irsimscript [glob -nocomplain ${CAD_ROOT}/irsim/tcl/irsim.tcl]
+ if { ${irsimscript} == {} } {
+ puts stderr "\"irsim\" requires Tcl-based IRSIM version 9.6 or newer."
+ puts stderr "Could not find script \"irsim.tcl\". If IRSIM is installed in a"
+ puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
+ puts stderr "\"source <path>/irsim.tcl\" before doing \"irsim\"."
+ } else {
+ source $irsimscript
+ eval {irsim} $args
+ }
+}
+
+# Setup Magic assuming that the Tcl version is installed.
+
+proc magic { args } {
+ global CAD_ROOT
+ set magicscript [glob -nocomplain ${CAD_ROOT}/magic/tcl/magic.tcl]
+ if { ${magicscript} == {} } {
+ puts stderr "\"magic\" requires Tcl-based Magic version 7.2 or newer."
+ puts stderr "Could not find script \"magic.tcl\". If Magic is installed in a"
+ puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
+ puts stderr "\"source <path>/magic.tcl\"."
+ } else {
+ set argv $args
+ set argc [llength $args]
+ uplevel #0 source $magicscript
+ }
+}
+
+# Setup Netgen assuming that the Tcl version is installed.
+
+proc netgen { args } {
+ global CAD_ROOT
+ set netgenscript [glob -nocomplain ${CAD_ROOT}/netgen/tcl/netgen.tcl]
+ if { ${netgenscript} == {} } {
+ puts stderr "\"netgen\" requires Tcl-based Netgen version 1.2 or newer."
+ puts stderr "Could not find script \"netgen.tcl\". If Netgen is installed in a"
+ puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
+ puts stderr "\"source <path>/netgen.tcl\"."
+ } else {
+ set argv $args
+ set argc [llength $args]
+ source $netgenscript
+ }
+}
+
+# Source the default resources file
+
+source ${tcllibdir}/resource.tcl
+
+# Sourcing of individual resource overrides
+
+set envhomedir [array get env "HOME"]
+if {$envhomedir != {}} {
+ set homepath [lindex $envhomedir 1]
+ set homedefaults ${homepath}/.Xdefaults
+ if {[file exists $homedefaults]} {
+ if {[catch {option readfile $homedefaults userDefault}]} {
+ puts stderr "Warning: Error parsing file $homedefaults"
+ }
+ }
+ unset homedefaults
+ unset homepath
+}
+unset envhomedir
+
+# Run the xcircuit start function
+
+if {[string length $argv] == 0} {
+ # Source the GUI-generating script
+ source ${tcllibdir}/wrapper.tcl
+ xcircuit::start .xcircuit
+} else {
+ set do_wrapper true
+ set argafter {xcircuit::start}
+ for {set i 0} {$i < $argc} {incr i 1} {
+ set x [lindex $argv $i]
+ switch -regexp -- $x {
+ ^-now {
+ set do_wrapper false
+ }
+ ^-r {
+ set XCOps(library) "all"
+ }
+ ^-noc {
+ # this option already handled---absorb it and do nothing.
+ }
+ default {
+ lappend argafter $x
+ }
+ }
+ }
+
+ # Set up for interactive or filter (batch) mode processing
+ if {$do_wrapper} {
+ # Source the GUI-generating script
+ source ${tcllibdir}/wrapper.tcl
+ set argafter [linsert $argafter 1 .xcircuit]
+ } else {
+ simple .xcdummy -exitproc "quitnocheck"
+ set XCOps(window) .xcdummy
+ }
+ unset x i do_wrapper
+ eval $argafter ;# xcircuit::start .xcircuit ${argv}
+}
+unset tcllibdir
+
+# The GUI wrapper iconfies the window while generating it
+catch {wm deiconify $XCOps(toplevel)}
+
+# Invoke the "wire" button by default
+catch {$XCOps(focus).mainframe.toolbar.bw invoke}
+
+# Xcircuit start function drops back to interpreter after initialization & setup
+
+if {[string range [wm title .] 0 3] == "wish"} {
+ wm withdraw .
+}
+
+if {[string range [wm title .] 0 8] == "xcircexec"} {
+ wm withdraw .
+}
diff --git a/lib/tcl/xcstartup.tcl b/lib/tcl/xcstartup.tcl
new file mode 100644
index 0000000..a117e04
--- /dev/null
+++ b/lib/tcl/xcstartup.tcl
@@ -0,0 +1,65 @@
+# XCircuit startup script for Tcl/Tk version
+# Does the work previously handled by "builtins.lps". Commands
+# "loadlibrary" and "loadfontencoding" should no longer be used.
+# Update, version 3.3.34: Commands "library override" and
+# "font override" should not be used; set XCOps(fontoverride)
+# and XCOps(liboverride) instead.
+#
+# Written by Tim Edwards 12/19/00, 6/24/02 (tim@bach.ece.jhu.edu)
+# The Johns Hopkins University
+
+global XCOps
+
+#
+# Look for a file "site.tcl" in the scripts directory. If it's there,
+# execute it instead of this file. "site.tcl" must NEVER be overwritten
+# by any installation procedure.
+#
+
+if {![catch {source ${XCIRCUIT_SRC_DIR}/site.tcl}]} {return}
+
+if {[catch {set XCOps(fontoverride)}]} {
+
+ loadfont times_roman.xfe
+ loadfont times_romaniso.xfe
+ loadfont helvetica.xfe
+ loadfont helveticaiso.xfe
+ loadfont courier.xfe
+ loadfont courieriso.xfe
+ loadfont symbol.xfe
+
+# Alternate font encodings: Uncomment these if you want them
+# loaded by default
+#
+# loadfont times_romaniso2.xfe
+# loadfont courieriso2.xfe
+# loadfont helveticaiso2.xfe
+# loadfont times_romaniso5.xfe
+# loadfont courieriso5.xfe
+# loadfont helveticaiso5.xfe
+}
+
+if {[catch {set XCOps(liboverride)}]} {
+
+# Create library pages
+ library make Generic
+
+# First library page
+ library 1 load generic.lps
+ library 1 load analog.lps
+ library 1 load avlsi.lps
+ library 1 load digital.lps
+ library 1 load digitaltcl.lps
+
+# Second library page
+ library make AnalogLib
+ library 2 load analoglib3.lps
+
+# Third library page
+# library make LeadFrame
+# library 3 load ic_templates.lps
+
+# Fourth library page
+# library make 74LSXX
+# library 4 load quadparts.lps
+}
diff --git a/lib/xcircps2.pro b/lib/xcircps2.pro
new file mode 100644
index 0000000..60e3b99
--- /dev/null
+++ b/lib/xcircps2.pro
@@ -0,0 +1,166 @@
+%%BeginProlog
+%
+% PostScript prolog for output from xcircuit
+% Version: 3.8
+%
+% Electrical circuit (and otherwise general) drawing program
+%
+% Written by Tim Edwards 8/5/93--11/1/10 (tim.edwards@multigig.com)
+% The Johns Hopkins University (1993-2004)
+% MultiGiG, Inc. (2004-2012)
+%
+%%BeginResource: procset XCIRCproc 3.8 0
+%
+% supporting definitions --- these are the primary xcircuit types.
+
+/XCIRCsave save def
+/topmat matrix currentmatrix def
+
+/fontslant { /slant exch def [1 0 slant 1 0 0]
+ exch findfont exch makefont dup length dict /ndict exch def
+ { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall
+ ndict definefont pop} def
+/ul { dup type /stringtype eq showflag 1 eq and { gsave
+ currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_)
+ false charpath flattenpath pathbbox grestore exch pop 1 index
+ sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0
+ rlineto stroke moveto } if } def
+/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave
+ currentpoint topmat setmatrix 2 index stringwidth pop 3 index
+ true charpath flattenpath pathbbox grestore exch pop
+ exch pop topmat setmatrix (_) true charpath pathbbox grestore
+ exch pop 1 index sub setlinewidth exch pop currentpoint
+ exch 4 1 roll exch sub add moveto pop 0 rlineto stroke
+ moveto } if } def
+/stW { gsave currentpoint newpath moveto true charpath flattenpath
+ pathbbox pop exch pop sub grestore } def
+/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs
+ 0 currentpoint pop put} def
+/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def
+/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt
+ {currentpoint exch pop moveto exit} {pop} ifelse } for } def
+/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def
+/hS { qS qS } def
+/pspc 0 def
+/cf0 { scalefont setfont } bind def
+/Kn { dup kY add /kY exch def rmoveto } bind def
+/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.33 mul neg Kn} def
+/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul
+ 0.67 mul Kn } def
+/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def
+/MR { /twidth exch def } def
+/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def
+/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq
+ { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def}
+ {fscale0 mul fscale mul cf0} ifelse } def
+/ctmk { counttomark dup 2 add -1 roll pop } bind def
+/label { gsave translate 0 0 moveto dup scale neg
+ /rotval exch def /twidth 100000 def /just exch def just 384 and
+ 0 gt {/mshow {pop} def} {/mshow {show} def} ifelse just 16 and 0
+ gt {gsave rotval rotate 0 1 dtransform gsave pagemat setmatrix
+ idtransform exch grestore 1 0 dtransform gsave pagemat setmatrix
+ idtransform exch grestore dup abs 1e-9 lt {pop mul 0 gt} {3 1 roll
+ pop pop 0 lt} ifelse grestore {-1 /rotval rotval neg def /just just
+ dup 3 and 1 ne {3 xor} if def} {1} ifelse exch -1e-9 lt {-1 /rotval
+ rotval neg def /just just dup 12 and 4 ne {12 xor} if def} {1}
+ ifelse scale } if /showflag 0 def /fspc pspc def /Bline 0 def /Tabs
+ 0 array def /fscale 1.0 def /kY 0 def gsave dup 1 add copy dup
+ 1 0 dtransform exch atan rotate {exch dup type /stringtype eq {gsave
+ dup gsave newpath 0 0 moveto true charpath flattenpath pathbbox pop
+ exch pop exch pop grestore currentpoint pop add twidth
+ ge {grestore CR exch 1 add dup 2 add {CR} exch 1 roll exch} {grestore}
+ ifelse true charpath flattenpath} {dup type /arraytype eq {exec} {12
+ string cvs true charpath flattenpath} ifelse} ifelse} repeat exch pop
+ pathbbox grestore 3 -1 roll pop 3 1 roll just 1 and 0 gt {just 2 and
+ 0 gt {exch pop neg fspc sub} {exch sub 0.5 mul neg} ifelse} {pop neg
+ fspc add} ifelse exch Bline exch just 4 and 0 gt {just 8 and 0 gt
+ {exch pop neg fspc sub} {add 0.5 mul neg} ifelse} {pop neg fspc add}
+ ifelse rotval rotate Kn currentpoint translate /showflag 1 def /Bline
+ 0 def /Tabs 0 array def /fscale 1.0 def /kY 0 def {dup type
+ /stringtype eq {mshow} {dup type /arraytype eq {exec} {12 string cvs
+ mshow} ifelse} ifelse} repeat grestore endclip} def
+/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label
+ /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def
+/pinglobal { pinlabel } def
+/infolabel { pinlabel } def
+/graphic { gsave 4 index cvx exec /DataSource get resetfile translate 0 0
+ moveto neg rotate dup scale cvx exec image grestore endclip} def
+
+/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def
+/cRedef {/defColor currentcolor 3 array astore def} def
+/begingate {dup type /dicttype ne {1 dict} if begin % default params
+ dup type /dicttype ne {1 dict} if begin % instanced params
+ /hlevel hlevel 1 add def /defColor currentcolor sce 3 array astore
+ def gsave sce translate 0 0 moveto neg rotate dup type /nametype
+ eq not { dup abs currentlinewidth exch div setlinewidth } { pop }
+ ifelse dup abs scale clipped 1 and 1 eq {/clipped clipped 1 add def}
+ if} bind def
+/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef
+ scb end end endclip} bind def
+
+/hlevel 0 def
+/endclip {clipped 1 and 1 eq {grestore /clipped clipped 1 sub def} if} def
+/tmpa [1 0 0 1 0 0] def
+/gar {8 8 true tmpa {<c0 c0 00 00 0c 0c 00 00>} imagemask} bind
+{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind
+{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind
+{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind
+{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind
+{8 8 true tmpa {<df cf 8f 9f fd fc f8 f9>} imagemask} bind
+{8 8 true tmpa {<ff 3f 3f ff ff f3 f3 ff>} imagemask} bind 7 array astore def
+/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll
+ neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy
+ gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll
+ { 3 index exch 5 exch put dup -8 3 index { 3 index
+ exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def
+/setstyles {
+ currentlinewidth mul setlinewidth /style exch def style 2048 and 0 gt
+ clipped 1 and 0 eq and {clip newpath /clipped clipped 1 add def} {
+ style 1 and 0 gt not {closepath} if
+ style 1024 and 0 gt {2 setlinecap 0 setlinejoin} if
+ style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if
+ style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if
+ gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt {
+ 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore
+ {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill}
+ {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse}
+ {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt
+ style 512 eq or {newpath} {stroke} ifelse grestore endclip} ifelse} def
+
+/addtoy {exch dup dup 2 mul 3 add 1 roll -1 1 { 4 1 roll dup 4 1 roll add
+ 4 -1 roll 2 mul 1 add index 2 mul 2 add 2 roll} for pop} def
+/addtoy1 {1 exch addtoy pop} def
+/addtoy3 {3 exch addtoy pop} def
+/addtoy4 {4 exch addtoy pop} def
+/addtox {exch dup dup 2 mul 3 add 1 roll -1 1 { 4 1 roll dup 4 1 roll 3 -1 roll
+ add exch 4 -1 roll 2 mul 1 add index 2 mul 2 add 2 roll} for pop} def
+/addtox1 {1 exch addtox pop} def
+/addtox3 {3 exch addtox pop} def
+/addtox4 {4 exch addtox pop} def
+/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def
+/xcarc { gsave newpath arc setstyles } def
+/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll
+ 3 index div 1 scale } def
+/ele { 0 4 1 roll 0 4 1 roll } bind def
+/ellipse { gsave elb newpath ele arc setmatrix setstyles } def
+/pellip { elb ele arc setmatrix } def
+/nellip { elb ele arcn setmatrix } def
+/spline { gsave moveto curveto setstyles } def
+/polyc { {lineto} repeat } bind def
+/beginpath { gsave moveto } bind def
+/endpath { setstyles } bind def
+/bop { 1 setlinecap 2 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef
+ /clipped 0 def} def
+/psinsertion {/PSobj save def /showpage {} def /setpagedevice {pop} def bop
+ rotate translate dup scale} def
+/end_insert {PSobj restore} def
+/setpagemat {/pagemat matrix currentmatrix def} def
+/inchscale {setpagemat 0.375 mul dup scale} def
+/cmscale {setpagemat 0.35433071 mul dup scale} def
+
+%%EndResource
+%%EndProlog
+
diff --git a/lib/xcircuit.1.in b/lib/xcircuit.1.in
new file mode 100644
index 0000000..b59b986
--- /dev/null
+++ b/lib/xcircuit.1.in
@@ -0,0 +1,1332 @@
+.TH XCircuit 1 "January 5, 2000" "X11R6"
+.SH NAME
+xcircuit - Draw circuit schematics or almost anything; make
+circuit netlists from schematics.
+.SH SYNOPSIS
+.B xcircuit [\fIfilename\fP[,...]]
+.SH DESCRIPTION
+The program xcircuit is a generic drawing program tailored
+especially for making publication-quality renderings of
+circuit diagrams (hence the name). The output is pure
+PostScript, and the graphical interface attempts to maintain
+as much consistency as possible between the X11 window
+rendering and the final printer output.
+.sp
+\fIxcircuit\fP is mouse, menu, and keyboard\-driven, with the emphasis
+on single-character keyboard macros.
+.SH OPTIONS
+.TP 8
+.B \fIfilename\fP[,...]
+Begin running xcircuit by loading in the PostScript file
+filename. If filename does not have a .ps extension,
+xcircuit will attempt to look for both the filename
+as entered and, upon failure, with the .ps extension.
+The file must be in xcircuit format. \fIfilename\fP
+may also be a comma-separated list of files.
+
+.SH BASIC ELEMENTS
+There are five drawing elements. These are as follows:
+.TP 3
+.B a)
+polygon (multiple lines which may or may not be closed and filled)
+.TP 3
+.B b)
+arc (ellipse segment which may be closed and/or filled as above)
+.TP 3
+.B c)
+label (any text)
+.TP 3
+.B d)
+curve (based on the PostScript "curveto" algorithm)
+.TP 3
+.B e)
+object instance (see below)
+.PP
+There are two composite elements, which are:
+.TP 3
+.B f)
+path (a connected series of polygons, arcs, and curves)
+.TP 3
+.B g)
+object (something containing polygons, arcs, labels,
+curves, paths, and instances of other objects)
+
+.SH MOUSE BUTTONS
+The mouse button system, the object library, and the paged buffer
+system are loosely based on the
+Caltech circuit-simulation program "log" (either "analog" or "diglog").
+.sp
+The general idea is to make the most commonly-used functions the
+easiest to perform, and (to the extent possible) to scale (inversely)
+the complexity of performing a function with the frequency of that task.
+Because this program is tailored to circuit drawing, the most common
+functions are drawing lines and moving object instances. The next most
+common function is selection of elements singly or in groups.
+.sp
+Mouse button 1 can be tapped to start a connected chain of lines, the
+most common drawing function. In addition, button 1
+has a function called "grab", which occurs after the button has
+been continually pressed for a short length of time (about 1/5 second).
+As the name implies, "grab" grabs hold of an element which can then
+be moved around the screen.
+.sp
+Button 2 can be used to select an item if tapped, and if pressed
+and held down, a box will be drawn and everything inside that box
+selected when the button is released. In all other cases, button 2
+will complete a command. For users who have only two mouse buttons
+and do not emulate the middle mouse button with the combination of
+buttons 1 and 3, use the combination of the Shift key and mouse
+button 1 to emulate mouse button 2.
+.sp
+Button 3 will normally abort a command. During editing of an arc,
+spline, or polygon, button 3 will revert back to the previous form,
+or abort if there is no remaining edit history.
+.sp
+All other commands are
+available from the pulldown menus and/or from the keyboard using
+single-key macros (with easy-to-remember mnemonics).
+Keyboard commands are quicker, since they act on the present cursor
+position, whereas menu commands require an extra step.
+
+.SH BUILT-IN LIBRARY
+The library is intended to provide a convenient way to store and
+retrieve elements of a picture which will be used more than once.
+For the application of circuit drawing, a built-in library provides
+basic objects such as transistors, amplifiers, resistors, capacitors,
+arrows, circles, power and ground symbols, and the like. This file
+is a composite of several library files (such as "builtins.lps",
+"analog.lps", and "digital.lps") which are called by the startup
+script
+PYTHON ("xcstartup.py")
+TCL ("xcstartup.tcl")
+NOINTERP ("startup.script")
+The program first looks for the startup script in
+the current directory, and then searches in the directory given by
+the environment variable "XCIRCUIT_LIB_DIR", and finally, in the
+hard-coded global directory (LIBDIR) if it could not find it elsewhere.
+Thus each user can add to or modify the file of builtins to reflect
+personal taste. Since the PostScript output contains all object
+definitions, these changes to the built-in functions are inherently
+transferrable. Xcircuit will automatically resolve conflicts between
+objects having the same name but different contents.
+.sp
+The library is accesible from the pull-down menu or with the "l"
+keyboard macro. When inside the library, clicking the first mouse
+button on an object "grabs" that object and returns the graphics
+state immediately to the page being edited, so that the object
+will be placed when the mouse button is released.
+
+.SH ZOOMING
+Xcircuit has unconstrained zooming and snap-to positioning. Objects
+scale completely: line widths and text sizes will increase/decrease
+proportionally with the zoom, as well as dot/dash spacing and all
+other features. Xcircuit does have a minimum integer grid in
+coordinate space, which translates to 0.005 inches at an output scale
+of 1. The maximum zoom scale gives a screen size translating to
+about 100 by 100 inches at an output scale of 1. The effective
+scale can be varied by changing the output scale (reached from the
+"File/Write" menu selection) in order to fit a drawing to a page or
+to get a grid matched to a specific dimension. A separate scale
+parameter changes the scale of the reported position relative to
+the output scale (as it will appear on a printed page).
+
+.SH SNAP-TO GRID
+The snap-to grid is an all-important feature for circuit drawing,
+wherein it is critical that elements line up properly with one another.
+In \fIxcircuit\fP, there is no way to get off the snap-to grid except by
+turning the snap function off and physically pushing elements off
+the grid. Generally, it is most convenient to leave the snap functon
+on and use key macros "+" and "-" to double/halve it as necessary.
+In any case, objects can always be returned to the snap grid with
+the "snap" function (key macro "S").
+
+.SH SELECTION MECHANISM
+Objects are selected using a variety of search methods. The
+select box (formed by holding down mouse button 2 and dragging
+the pointer) uses the simplest method, searching for
+curve/polygon segment endpoints, arc centers, and label
+and object bounding boxes falling within the select box frame.
+General object selection is more complicated. Polygons, Arcs,
+and Curves are selected by their outer edges, not the interiors.
+Currently this is also true for filled instances of those types.
+A line is selected if the pointer is in a
+region describing a box around it, which is adusted according
+to the scale (zoom factor). Every object has an
+associated bounding box, which is rectangular but may be rotated
+with respect to the top level window. An object instance is
+selected if the pointer falls within its bounding box. Each
+label also has a bounding box carefully calculated from the width
+of the text string.
+.sp
+Often the selection mechanism will find multiple elements in
+range of the pointer. In this case, each object in turn will be
+presented, colored in blue (or the specified "querycolor" in the
+defaults file), and the user has the option of accepting the
+highlighted element for selection using the mouse button 1, or
+rejecting it with mouse button 3. When all the elements under
+consideration have been accepted or rejected, the program
+proceeds to execute whatever function was in progress. This
+selection method takes a little while to get used to, but is
+sensible and seems to work well.
+
+.SH COLOR
+Color in xcircuit is implemented with the idea of "color inheritance".
+Every page has a "default color" of black. All elements which have
+color value "Inherit" will inherit the default color, black. If an
+object instance is painted blue (for instance), all components in
+that object which have color value "Inherit" will inherit its color,
+blue. The reason for this is that it allows different object
+instances to be painted different colors (such as if one part of
+a circuit is highlighted for emphasis), while making it possible for
+object instances to be multicolored, if necessary. Changing the
+color of an object instance will have no observable effect on the
+drawing if none of the components of the object inherit that color.
+An object may have both normally colored components and components
+which inherit their color, in which case only those components with
+the "Inherit" value will change color when the color of the object
+instance is changed.
+
+.SH SCHEMATIC CAPTURE
+XCircuit implements a sophisticated schematic capture. Unlike
+virtually all schematic capture software currently available,
+xcircuit allows the designer to draw the circuit in a "natural"
+way, making use both of schematic hierarchies and simple
+hierarchies created simply by grouping elements together. If
+the chosen netlist format is hierarchical (like SPICE), both
+hierarchical forms will be retained in the output. For element
+grouping, input/output ports connecting into to the group will
+be determined automatically, from context. A schematic capture
+tutorial is available from the xcircuit website,
+.br
+http://opencircuitdesign.com/xcircuit/tutorial/tutorial2.html.
+.br
+
+Netlist types currently available are "SPICE", "sim", and "PCB".
+
+.SH KEYBOARD COMMANDS
+.br
+.PP
+\fBBasic keyboard commands:\fP
+.TP 12
+.B Z
+Zoom in by a factor of 3/2. If this key is pressed while a
+selection box is active (created with the middle mouse
+button), then acts like Zoom Box function.
+.TP 12
+.B z
+Zoom out by a factor of 3/2.
+.TP 12
+.B p
+Pan the screen so that the point under the mouse is brought
+to the center of the program window. This function can also
+be conveniently performed by clicking on the scrollbars.
+The scrollbars cannot be moved continuously due to the slow
+time for screen refresh.
+.TP 12
+.B cursors
+The arrow keys perform a pan of one-half window size in the
+direction of the arrow pressed.
+.TP 12
+.B l
+Go to the Library of built-in objects. From the library,
+use mouse button1 to grab an object and bring it back to
+the edit screen, or button3 to return without selecting
+an object instance. While in the library screen, the
+zoom and pan functions can be used to move around.
+.TP 12
+.B >
+Push into an on-screen object in order to edit that object
+.TP 12
+.B <
+Return from editing an object. Object pushes and pops can
+be stacked indefinitely.
+.TP 12
+.B space
+Refresh the screen.
+.TP 12
+.B digits 0-9
+Switch to one of the first ten editing pages. Pages greater
+than 10 can be reached from the "Window/Goto Page" menu
+selection.
+.TP 12
+.B + and -
+Change snap-to grid spacing by a factor of two up or down.
+.TP 12
+.B | : and _
+(Bar, colon, and underline) Change style on the currently
+selected object to dashed, dotted, and solid, respectively.
+.TP 12
+.B h or ?
+Print a help page summary of commands
+.PP
+.sp
+\fBCommands to create elements:\fP
+.TP 4
+.B a
+Arc. Center is fixed at the initial position of the cursor.
+The mouse position changes the radius of the circle.
+In snap-to mode the arc boundry will pass through the snap point
+closest to the cursor. Mouse button 1 cycles from controlling
+the radius to controlling the starting point, the ending point,
+and separately controlling the minor axis to create ellipse.
+Mouse button 2 completes the arc.
+.TP 4
+.B b
+Box. This is a convenience function for generating rectangular
+closed polygons. Creates a rectangle with one corner fixed at
+the position of the cursor. Subsequent movement of the cursor
+defines the point diametrically opposed. Mouse buttons 1 or 2
+complete the box.
+.TP 4
+.B s
+Spline curve. The first endpoint is defined by the initial cursor
+position. Mouse position adjusts the other endpoint of the curve.
+Mouse button 1 cycles from controlling position of the endpoint
+to controlling positions of the curve control points and the curve
+starting point. Mouse button 2 completes the curve.
+.TP 4
+.B t
+Text. Text starts out justified according to the styles chosen
+in the pull-down menu. Text can be rejustified using the menu
+or by typing the numbers on the keypad (\fBshift-keypad-1\fP through
+\fBshift-keypad-9\fP). The position of the keys on the keypad
+matches the justification. Subscripts, superscripts, font
+changes, text size changes, underlining, and overlining are all
+available from the pull-down menu. Text edit mode recognizes
+\fBHome\fP and \fBEnd\fP keys to move to the beginning and end
+of the string, respectively. If the X11 environment maps
+control key sequences to character encodings (such as ISO-Latin1),
+these may be used to insert non-ASCII text. Another method of
+inserting non-ASCII characters is the use of the backslash
+character, which duplicates the action of the
+Text/Insert/Character menu button.
+.TP 4
+.B M, m
+Make object. Takes all the elements currently selected and
+compiles them into an object. The object is then placed in the
+user library. The elements just selected are deleted from the
+screen and replaced by the new object. The center point of the
+resulting object is chosen as the closest snap-to point to the
+center of the object's bounding box; if another center is desired,
+then the object can be edited using the ">" command and its contents
+moved with respect to its origin. \fINote:\fP Objects cannot have
+the same name as PostScript commands or have the same name as any
+other object in memory. If such a name is found, an underscore ("_")
+will be prepended to the name as many times as is necessary to
+differentiate it from all other known objects.
+The name also cannot contain special PostScript characters such as
+slash; any such characters found will be replaced with underscores.
+.sp
+.PP
+\fBMajor editing commands:\fP
+.TP 4
+.B d
+Delete. Select the nearest element or elements and delete it/them.
+.TP 4
+.B u
+Undelete. Xcircuit saves up to 10 delete events to be recovered.
+Delete events are stored in order of occurrence, and the most
+recent delete event is the first to be recovered.
+When multiple elements are deleted at the same time, all of them
+are stored as one delete event, and restored together.
+.TP 4
+.B x
+Deselect. Elements which have been selected can be deselected on
+a per-item basis. In order not to be too confusing, deselect does
+not query if multiple items are found under the cursor; it just
+deselects them all.
+.TP 4
+.B c
+Copy. Make a copy of the object(s) nearest the cursor. Object
+is automatically grabbed for moving to a new position. The
+next button1 or button2 press will place the element. Button2
+will end the copy, and button1 will continue the copy function.
+.TP 4
+.B e
+Edit. The action of Edit is dependent on the type of element
+selected. These are detailed below:
+.TP 12
+.B Label
+Returns to text editing mode, starting with the cursor
+at the end of the string. Mode is like regular text entry
+except that Button 3 returns text to its original string.
+.TP 12
+.B Polygon
+Grabs one point of a polygon for repositioning. Button 1 cycles
+between points, button 2 accepts the new polygon, and button 3
+returns to the previous state, unless there is no remaining edit
+history, in which case it aborts the command.
+Key macros available during polygon edit are:
+.sp
+"x"---Breaks the polygon at the given point.
+.sp
+"e"---Moves edit position to the next point.
+.sp
+"i" or "Insert"---Inserts a new point at the position.
+.sp
+"d" or "Delete"---Deletes the current edit point.
+.sp
+There are four modes for polygon editing; see the
+"\fBPolygon Edit\fP" section below for details.
+.TP 12
+.B Arc
+Allows resizing of the radius. Mouse button 1 or the "e" key
+will cycle between control of the radius, the endpoint angles,
+and the ellipse minor axis. Mouse button 2 accepts the new
+arc. Button 3 returns to the previous editing state,
+unless there is no remaining edit history, in which case it
+aborts the command.
+.TP 12
+.B Curve
+Allows repositioning of one end of the curve.
+Originally, the starting angle of the curve is kept fixed.
+Mouse button 1 or the "e" key cycles between the four
+control points of the curve, allowing control over the
+angle of the curve at its endpoint and the shape of the
+curve. Mouse button 2 accepts the new curve. Button 3
+reverts back to the previous edit state
+unless there is no remaining edit history, in which case
+it terminates the command.
+.TP 12
+.B Object instance
+Object instances have no properties to change
+except scale, and do not respond to the "edit" command.
+Scale can be changed by selecting "Options/Other/Object Size"
+from the menu.
+.sp
+.PP
+\fBMinor editing commands:\fP
+.TP 4
+.B R
+Rotate the selected element(s) or element under the cursor
+counterclockwise in 15 degree intervals.
+.TP 4
+.B r
+Rotate the selected element(s) or element under the cursor
+clockwise in 15 degree intervals.
+.TP 4
+.B O
+Rotate the selected element(s) or element under the cursor
+counterclockwise by 5 degree intervals. This is currently
+the smallest angle resolution available to xcircuit.
+.TP 4
+.B o
+Rotate the selected element(s) or element under the cursor
+clockwise by 5 degree intervals.
+.TP 4
+.B f
+Flip an element around a vertical axis defined by an object's
+origin for an object instance, or across an axis defined by
+the pointer position for arcs, polygons, and curves.
+.TP 4
+.B F
+Flip an element around a horizontal axis defined
+similarly to the "f" command.
+.TP 4
+.B X
+If two elements are selected, their order is exchanged
+(this is only relevant if one element occludes another).
+If one element is selected, it is raised up one in the
+stack, and if it is already on top of the stack, it is
+shuffled to the bottom.
+.TP 4
+.B S
+Snap the nearest object to the snap-to grid. For
+curves the control and endpoints are snapped; for polygons, each
+point is snapped; for arcs, the centerpoint is snapped; for labels
+and object instances, the designated point of origin is snapped.
+.TP 4
+.B j
+Join polygons together. This only makes sense if it is possible
+to make a single continuous (open or closed) polygon from the
+selected parts. Otherwise a warning will be posted and the parts
+will remain separate.
+.TP 4
+.B A
+Attach an element to a polygon, arc, or curve.
+The element to be attached must be the one currently grabbed
+(either by a "drag", copy command, or edit command).
+Until it is released, it will be forced to align
+its center (object, arc), endpoint (polygon, curve), or
+position (label) with the closest polygon, arc, or curve.
+Note that this is a very powerful tool for generating, for
+example, lines tangent to a curve, or objects arranged in
+a circle or along a line.
+.sp
+.PP
+\fBLibrary editing commands:\fP
+.TP 4
+.B D
+Delete. The selected objects will be deleted from the library
+unless other library objects or pages contain references to that
+object. \fBNote:\fP Unlike deleting object instances with the
+"\fBd\fP" command, this command deletes the actual object and
+releases all memory associated with that object, so the
+object cannot be undeleted.
+.TP 4
+.B C
+Copy. Makes a copy of an object from either library page and
+places the new copy in the user library. The new object will
+be renamed to avoid naming conflicts.
+.TP 4
+.B M
+Move. If one object has been selected, it is moved to the
+position of the cursor. If two objects have been selected,
+their positions in the library are exchanged.
+.TP 4
+.B E
+Edit label. Edit the object name whose label is under the
+cursor. After editing, the object name will be checked for
+conflicts with other object names, and altered if necessary.
+.TP 4
+.B H
+Hide object. If the object is a sub-instance of another object,
+but is not meant to be used by itself, it can be "hidden" so
+that it will not appear by itself on the library page.
+.sp
+.SH MENU COMMANDS
+.sp
+.TP 4
+.B Write Postscript (W)
+This command brings up a popup menu with a number of options.
+First, it gives the name of the file if one exists, or else it
+gives the default name of the buffer (usually \fBPage\fP \fIn\fP,
+where \fIn\fP is the number of the buffer).
+Next, it gives a preview of the picture scale and output
+styles, which include Landscape/Portrait orientation and
+Encapulated/Unencapsulated (full page) PostScript modes.
+The former allows adjustment of the nominal size of the picture
+when drawn in PostScript. The default scale is 1.00, which
+makes the text scale of 1.0 about 14 points on the PostScript
+page. The width and height of the resulting
+picture are also given, in inches, and any of the three
+values can be changed. The values of the other two will
+be updated accordingly. Pages which have the same name
+will be grouped together into a single file, allowing
+multiple pages to be stored in the same PostScript file.
+However, as Encapsulated PostScript does not make sense
+for this kind of file, it is not an option.
+.sp
+The \fBWrite File\fP button writes the current page to an
+output file. If the page has a name other than the default,
+the file will automatically be saved under that name. Otherwise,
+it is necessary to change the name of the buffer. If a file of
+that name already exists on the disk, the button will read
+\fBOverwrite File\fP.
+.TP 4
+.B Read PostScript
+Reads in a file of Xcircuit format. The
+file name is requested by a popup prompt, and an extension
+of ".ps" will be added if necessary. The file is read
+into the current page, which is cleared first if anything
+is in it. If the file is a multiple-page file, the current
+page will be overwritten with the first page from the file,
+but other pages will be loaded into empty buffers.
+LGF Xcircuit can also read "lgf"-format files from
+LGF the Chipmunk CAD tools programs "analog" and "diglog".
+.TP 4
+.B Import PostScript
+Acts like "Read PostScript" except that the page is not
+reset first, so graphics are added on top of existing
+graphics on the page.
+.TP 4
+.B Clear Page
+Clears the current page of all elements and resets the
+name. The contents cannot be recovered.
+.TP 4
+.B Alt Color
+Switches between the two xcircuit color schemes. The
+color schemes can be redefined through XDefaults
+(see below). The default color schemes are black-on-white
+and white-on-black. The latter is less straining to the
+eyes, but the former matches the black ink on white paper
+PostScript output. Any color scheme other than black-on-white
+is not recommended for drawings with color, as the actual
+output does not match the observed xcircuit screen.
+.TP 4
+.B Grid
+Turns the grid lines on and off.
+.TP 4
+.B Axes
+Turns the axis lines on and off. The axes mark the
+origin (0,0) of the page. On the top level (TopObject),
+the origin has no particular relevance, since encapsulated
+output will define its own boundaries, and full-page
+(unencapsulated) output will be centered on the output
+page, not according to the Xcircuit coordinate system.
+.TP 4
+.B Grid spacing
+Changes the spacing of the grid lines.
+Default spacing is 1/6 inch, which is about
+the width of the letter 'W' in default text scale.
+.TP 4
+.B Grid type/display
+This is a submenu allowing the coordinates and coordinate
+grid to be specified in alternate units. Listing of
+coordinates in the top window can be in default fractional
+inches, decimal inches, or centimeters. Default spacing
+of grid lines is either one-quarter inch or one-half
+centimeter. Selecting an A:B scale With option
+"\fBDrawing Scale\fP" causes all listed coordinates to be
+multiplied by the scale. \fINote:\fP Xcircuit will make
+an attempt to keep objects on the snap/grid spacing when
+switching between inch and centimeter scales. In order
+to do this, it will change the output scale by the ratio
+of 2.54 to 2.5, thus keeping a closer correspondence between
+inches and centimeters. To get true centimeters on the
+output page, the output scale (from the "File/Write Xcircuit PS")
+can be reset to 1.0 at the expense of having all objects
+intended for the inch grid displaced off of the snap grid.
+.TP 4
+.B Snap-to
+Turns the snap-to grid on and off. When the grid
+is on, movement and placement of elements is restricted
+to points on the snap-to grid.
+.TP 4
+.B Snap spacing
+Determines the spacing of the points in the
+snap-to grid. Default is 1/12 inch, which is half
+the grid line spacing.
+.TP 4
+.B Linewidth
+Controls the default linewidth against which
+all linewidths in the drawing are scaled.
+.TP 4
+.B Polygon Edit
+The options in this submenu control how the position of
+lines are affected when a point in a polygon is selected
+for editing. "\fBRhomboid-X\fP" mode moves adjoining
+points as necessary to keep all horizontal lines horizontal;
+"\fBRhomboid-Y\fP" mode acts similarly to keep all vertical
+lines vertical. "\fBRhomboid-A\fP" is similar to Manhattan
+mode but also tracks non-Manhattan lines.
+The default mode is "\fBManhattan Box Edit\fP",
+which is a combination of Rhomboid-X and Rhomboid-Y. In
+"\fBNormal\fP" mode, only the point being edited can be moved.
+.TP 4
+.B \fPArc/Box/Curve\fB Border
+The options under this menu determine the
+border style of arcs, polygons, and curves. If an element
+is selected, it will be modified; otherwise, if
+no objects are selected, the style chosen is made
+default for all subsequent arcs, polygons, and curves.
+Elements may be drawn with or without borders (but
+for obvious reasons cannot be made both borderless
+and unfilled, which would be invisible)
+The borders may be closed or unclosed. For an arc,
+closed means that a chord is drawn connecting the two
+endpoints, if the beginning and ending angles do not
+complete a full circle. Borders may be solid, dashed,
+dotted, and of varying width.
+.TP 4
+.B \fPArc/Box/Curve\fB Fill
+The options under this menu determine the
+fill style of arcs, polygons, and curves.
+Fill style may be solid, empty, or one of 7 stipple
+patterns varying from light to dark, which are drawn
+both in xcircuit and PostScript as stipple patterns.
+Stipples can be transparent or opaque.
+\fIWarning\fP: Transparent
+stipples are NOT inherent to PostScript and the hacks
+necessary to implement them cause slow rendering on
+a printer or PostScript previewer. Due to the
+device-dependent nature of the routines, patterns
+will look abnormally large on PostScript previewers.
+This transparancy feature has been added with the
+expectation that most circuit schematics will not
+rely heavily upon halftoning. Complicated color
+patterns can be created using transparent colored,
+stippled elements on top of solid-color elements.
+\fINote\fP: Ordering of elements is according to
+order created. A different ordering can be achieved
+using the "\fBX\fP" (exchange) command. This method
+is not especially easy to work with, and hopefully
+something better will be implemented in the future.
+.TP 4
+.B \fPArc/Box/Curve\fB Color
+See the COLOR section above for a discussion of color
+inheritance. This menu shows all the colors available
+to xcircuit with the option of adding more colors.
+Currently the entry style for colors is by name or by
+RGB content in the X11 style of #rrggbb where rr, gg,
+and bb are hex values ranging from 00 to FF. The only
+limit to the number of colors is the X Server's colormap
+depth. If the colormap is full, xcircuit attempts to
+allocate the closest possible color to the one requested.
+.TP 4
+.B Zoom Box
+This zoom feature requests the user to create a box
+(using either mouse button 1 or 2, expanding the box
+while holding down the button). When the button is
+released, the view will zoom to the area of that box.
+.TP 4
+.B Full View
+This zoom feature calculates the bounding box
+of the entire picture and adjusts the scale to make
+it fit comfortably inside the program window.
+.SH TEXT FEATURES
+Xcircuit's ability to handle text is arguably the
+most complicated part of the program, and also of
+the PostScript output. Careful attention to text
+justification and style is the key to a good drawing.
+.TP 4
+.B Text Size
+Alters the size of the labels. The value is
+a scale, with a default of 1.0 which translates to
+14 points on the PostScript page if the default page
+scale of 1 is used. If a label is selected, only that
+label is affected. If a label is being edited, scale
+changes starting at the edit position. Otherwise, it
+becomes the default size for all subsequent labels. Size
+affects the entire text string. Text size can be changed
+anywhere inside of a string. However, text sizes inside
+a string are all given relative to the label size, not as
+an absolute point size. Sizes of subscripts and superscripts
+are given relative to the natural size of the subscript or
+superscript (2/3 the size of the text for which it is a
+modifier).
+.TP 4
+.B \fPText\fB Font
+Standard printer fonts Times-Roman, Helvetica,
+Courier, and Symbol, are readily available.
+"User-defined" fonts can also be added; however,
+support is currently limited, and requires a font
+object (.lps) file and encoding (.xfe) file,
+examples of which are found in the fonts subdirectory
+of the xcircuit library directory.
+.TP 4
+.B \fPText\fB Style
+Four standard font styles are available,
+matching the standard printer font variations: Normal,
+Italic (or oblique), Bold, and BoldItalic.
+PostScript matrix manipulation allows slanted versions
+of any font, such as Symbol, for which none is otherwise
+available.
+.TP 4
+.B \fPText\fB Insert
+The Insert menu allows insertion of special characters
+which are otherwise not (necessarily) allowed from the
+keyboard. These include tab-stop, tab-forward, tab-backward,
+kern, half-space, quarter-space, and "Character". The latter
+option brings up a page showing the 256-character encoding
+vector for the font, allowing point-and-click entry of any
+character in the font. "Kern" instructions allow characters
+to be offset vertically or horizontally relative to the rest
+of the text.
+.TP 4
+.B \fPText\fB Encoding
+Two standard font encodings are available by default,
+Standard (Adobe) Encoding, and ISO-Latin1 encoding.
+ISO-Latin2 and ISO-Latin5 encodings exist in the
+library directory, but require the use of the program
+"ogonkify" (not included) to produce correct output on
+a printer.
+.TP 4
+.B Super and Subscripts
+Superscript and subscript are
+designed to closely match those in TeX output, though
+they lack the proper context-dependent kerning and
+other fancy features of TeX. A superscript following
+a subscript results in a superscripted subscript.
+To get a superscript on top of a subscript, use the
+backspace character (see below).
+The Normalscript style is the way to get
+out of a sub or superscript and return to the normal
+size and position.
+Quick super/sub/normalscripting is available from the
+keypad with the "\fB+\fP" (plus), "\fB-\fP" (minus),
+and "\fBEnter\fP" keys, respectively.
+.TP 4
+.B Overline and Underline
+Overlining and underlining styles
+remain in effect until the next occurrence of a style
+or font change. Overlining is
+lower if all the characters are lowercase and do not
+include the "tall" lowercase characters. Overlining
+or underlining can be stopped at any time using the No
+Line style. Over and Underlining is *always* preferable
+to using a line. PostScript will adjust the over or
+underline to the text size and extent and actually grab
+the "_" character and compute its thickness in order to
+draw the line.
+.TP 4
+.B Tabbing
+From version 2.3, xcircuit allows embedded tab stops.
+Tab stops must be defined before using tab-forward or
+tab-backward. The "Tab" keyboard key inserts an
+embedded tab-forward instruction into a label. Tab-stop
+and tab-backward can be inserted using the Text->Insert
+menu. A tab-forward instruction moves the cursor
+to the first defined tab stop forward of the current
+position. A tab-backward instruction moves the cursor
+to the first defined tab stop backward of the current
+position. If no appropriate tab stop exists, the
+instruction has no effect.
+.TP 4
+.B Backspace
+The use of the backspace character is deprecated from
+xcircuit version 2.3. The effect of an embedded backspace
+is more reliably produced using tab-stop and tab-backward.
+.TP 4
+.B Halfspace and Quarterspace
+These options allow fine control over spacing, particularly
+useful when writing equations.
+.TP 4
+.B Justification
+Text justification always starts with the
+default, chosen from the options in the menu, but may
+be changed at any time using the numbers on the keypad.
+The position of the keys on the keypad reflect the
+point of justification: 1, 4, and 7 are right-justified,
+7, 8, and 9 are bottom justified, 5 is centered in both
+directions. Since the letters drawn by xcircuit are
+optimized for the Helvetica font, correct justification
+is the main way to get text to come out on the PostScript
+page in the desired way, relative to objects or boxes or
+whatever.
+.SH .XCIRCUITRC FILE
+Certain parameters of the xcircuit program can be
+initialized from a file called \fB.xcircuitrc\fP, which
+is first searched for in the current directory, and then
+in the user's home directory as defined by the environment
+variable $HOME.
+PYTHON The XCircuitrc file is written in
+PYTHON Python (see www.python.org), with certain commands whose
+PYTHON main purpose is to transfer data structures between
+PYTHON the Python interpreter and XCircuit.
+PYTHON These commands are as follows:
+PYTHON .TP 6
+PYTHON .B library("\fIlibname\fP" [, \fInum\fP])
+PYTHON Loads a library named \fIlibname\fP (with or without .lps
+PYTHON extension) into the set of built-in objects. \fInum\fP,
+PYTHON if specified, puts the specified library onto library page
+PYTHON \fInum\fP (starts at 1).
+PYTHON .TP 6
+PYTHON .B override("library")
+PYTHON Causes the default libraries defined in "builtins.lps"
+PYTHON \fInot\fP to be loaded.
+PYTHON .TP 6
+PYTHON .B override("colors")
+PYTHON Causes the default colors \fInot\fP to be loaded; this will
+PYTHON not override the allocation of black and white, however,
+PYTHON for obvious reasons.
+PYTHON .TP 6
+PYTHON .B font("\fIfontname\fP")
+PYTHON Adds a font named \fIfontname\fP (as recognized by a
+PYTHON printer) to the menu of selectable fonts.
+PYTHON .TP 6
+PYTHON .B color("\fIcolorname\fP")
+PYTHON Adds a color named \fIcolorname\fP (standard X11
+PYTHON conventions) to the menu of selectable colors.
+PYTHON .TP 6
+PYTHON .B bind("\fIkey\fP", "\fIfunction\fP")
+PYTHON Binds the key (or button) named \fIkey\fP to the function named
+PYTHON \fIfunction\fP. If only one argument is given, it can be
+PYTHON either a key name or a function name, and bind() returns
+PYTHON the associated binding(s). If no argument is given, then
+PYTHON bind() returns a dictionary of all key bindings.
+PYTHON Valid function names are listed in section "KEY BINDINGS" below.
+PYTHON .TP 6
+PYTHON .B unbind("\fIkey\fP", "\fIfunction\fP")
+PYTHON Unbinds the key (or button) named \fIkey\fP from the function named
+PYTHON \fIfunction\fP.
+PYTHON Valid function names are listed in section "KEY BINDINGS" below.
+PYTHON .TP 6
+PYTHON .B set("\fItype\fP", "\fIvalue\fP")
+PYTHON Sets internal xcircuit variables, where \fItype\fP can be one of:
+PYTHON .sp
+PYTHON \fBboxedit\fP
+PYTHON .sp
+PYTHON Where \fIvalue\fP is one of "manhattan", "rhomboid-x", "rhomboid-y",
+PYTHON or "normal". Determines the default way manhattan-aligned polygon
+PYTHON edges are manupulated during edits.
+PYTHON .sp
+PYTHON \fBlinewidth\fP
+PYTHON .sp
+PYTHON Where \fIvalue\fP is a real number indicating the default
+PYTHON width of lines.
+PYTHON .sp
+PYTHON set("\fBbeep\fP", "on"|"off")
+PYTHON .sp
+PYTHON Where \fIvalue\fP can be \fBon\fP or \fBoff\fP, depending on
+PYTHON whether or not you want the machine beeping at you when it
+PYTHON gives critical warnings.
+PYTHON .sp
+PYTHON set("\fBcolorscheme\fP", "normal"|"inverse")
+PYTHON .sp
+PYTHON Where \fIvalue\fP is \fBinverse\fP to swap the two color schemes
+PYTHON and make the second scheme appear as default.
+PYTHON .sp
+PYTHON \fIh\fP = newelement("\fIname\fP")
+PYTHON .sp
+PYTHON Creates a new element and returns a handle (pointer) \fIh\fP to it which
+PYTHON can be used to get and set element attributes. Valid names are
+PYTHON "Arc", "Spline", "Polygon", "Object Instance", "Label", and "Path".
+PYTHON .sp
+PYTHON \fId\fP = getattr(\fIh\fP)
+PYTHON .sp
+PYTHON Creates a dictionary \fId\fP of attributes for the element with handle
+PYTHON \fIh\fP. Dictionary keys depend on the element.
+PYTHON .sp
+PYTHON setattr(\fIh\fP, \fId\fP)
+PYTHON .sp
+PYTHON Applies the dictionary \fId\fP key:value pairs to the element pointed to
+PYTHON by handle \fIh\fP.
+PYTHON .sp
+PYTHON \fId\fP = getpage(\fIvalue\fP)
+PYTHON .sp
+PYTHON Returns a dictionary \fId\fP containing information about the page \fIvalue\fP.
+PYTHON If \fIvalue\fP is not specified, returns information about the current page.
+PYTHON The dictionary includes a list "\fIparts\fP" of handles to every element drawn
+PYTHON on the indicated page.
+PYTHON .sp
+PYTHON \fId\fP = getlibrary(\fIname\fP)
+PYTHON .sp
+PYTHON Returns a dictionary of objects for the indicated library,
+PYTHON referenced by \fIname\fP, or by page number. The dictionary contains a
+PYTHON list "\fIobjects\fP" of names of every object in the library.
+PYTHON .sp
+PYTHON \fId\fP = getobject(\fIname\fP)
+PYTHON .sp
+PYTHON Returns a dictionary containing all information about an object, which
+PYTHON is referenced by \fIname\fP. The dictionary contains keys "\fIname\fP",
+PYTHON containing the object name, "\fIwidth\fP" and "\fIheight\fP", a
+PYTHON list "\fIparts\fP" containing handles to each element comprising the
+PYTHON object, and a list "\fIparameters\fP" containing all the parameters
+PYTHON defined for the object and their default values.
+PYTHON .sp
+PYTHON zoom(\fIfactor\fP)
+PYTHON .sp
+PYTHON Zooms by amount \fIfactor\fP. Values greater than 1 indicate a zoom in;
+PYTHON values less than 1 indicate a zoom out.
+PYTHON .sp
+PYTHON pan(\fIposition\fP)
+PYTHON .sp
+PYTHON Centers the screen on the (user) coordinate \fIposition\fP, which can be
+PYTHON either a (X,Y) tuple or two integers X, Y.
+PYTHON .sp
+PYTHON refresh()
+PYTHON .sp
+PYTHON Refreshes the screen. The screen is automatically refreshed after every
+PYTHON Python command, but the \fBrefresh()\fP function can be used along with the
+PYTHON \fBpause()\fP function for animation effects.
+PYTHON .sp
+PYTHON pause(\fIdelay\fP)
+PYTHON .sp
+PYTHON Pauses for \fIdelay\fP seconds (is a floating-point number). Useful in
+PYTHON conjunction with \fBrefresh()\fP for animation effects.
+PYTHON .sp
+PYTHON \fIt\fP = getcursor()
+PYTHON .sp
+PYTHON Returns a tuple \fIt\fP containing the current X and Y position of the cursor.
+PYTHON .sp
+PYTHON .sp
+PYTHON \fIt\fP = getwindow()
+PYTHON .sp
+PYTHON Returns a tuple \fIt\fP containing the current window width and height.
+PYTHON .sp
+PYTHON popupprompt(\fIprompt\fP, \fIfunction\fP)
+PYTHON .sp
+PYTHON Generates a popup window with text entry. \fIprompt\fP will be printed above
+PYTHON the text entry window. Python function \fIfunction\fP (referenced by name)
+PYTHON will be called when clicking the "Okay" button or pressing the Return key
+PYTHON ends the text entry. The function will be passed the contents of the text
+PYTHON window as its (only) parameter.
+PYTHON .sp
+PYTHON filepopup(\fIprompt\fP, \fIfunction\fP)
+PYTHON .sp
+PYTHON Operates exactly like \fBpopupprompt()\fP, except that the window is a file
+PYTHON browser instead of a simple text entry window.
+PYTHON .sp
+PYTHON .sp
+PYTHON simplepopup(\fIprompt\fP, \fIfunction\fP)
+PYTHON .sp
+PYTHON Operates exactly like \fBpopupprompt()\fP, except that there is no text entry
+PYTHON window, only a prompt string and the choice of "Okay" and "Cancel".
+PYTHON .sp
+PYTHON newbutton(\fIparent\fP, \fIname\fP, \fIfunction\fP)
+PYTHON .sp
+PYTHON Generates a new menu button under the menu cascade labeled \fIparent\fP.
+PYTHON The new button will display the label \fIname\fP, and pushing the button
+PYTHON will call the Python function \fIfunction\fP.
+PYTHON .sp
+PYTHON page(\fInumber\fP)
+PYTHON .sp
+PYTHON Go to the page numbered \fInumber\fP.
+PYTHON .sp
+PYTHON reset()
+PYTHON .sp
+PYTHON Erases the current page unconditionally, unless dependencies such as a link
+PYTHON to a symbol exist.
+
+NOINTERP Commands are:
+NOINTERP .TP 6
+NOINTERP .B library \fIlibname\fP
+NOINTERP Loads a library named \fIlibname\fP (with or without .lps
+NOINTERP extension) into the set of built-in objects.
+NOINTERP .TP 6
+NOINTERP .B override default library
+NOINTERP Causes the default libraries defined in "builtins.lps"
+NOINTERP \fInot\fP to be loaded.
+NOINTERP .TP 6
+NOINTERP .B override default colors
+NOINTERP Causes the default colors \fInot\fP to be loaded; this will
+NOINTERP not override the allocation of black and white, however,
+NOINTERP for obvious reasons.
+NOINTERP .TP 6
+NOINTERP .B font \fIfontname\fP
+NOINTERP Adds a font named \fIfontname\fP (as recognized by a
+NOINTERP printer) to the menu of selectable fonts.
+NOINTERP .TP 6
+NOINTERP .B color \fIcolorname\fP
+NOINTERP Adds a color named \fIcolorname\fP (standard X11
+NOINTERP conventions) to the menu of selectable colors.
+NOINTERP .TP 6
+NOINTERP .B set \fItype\fP \fIvalue\fP
+NOINTERP Sets internal xcircuit variables, where \fItype\fP can be one of:
+NOINTERP .sp
+NOINTERP \fBboxedit\fP
+NOINTERP .sp
+NOINTERP Where \fIvalue\fP is one of "manhattan", "rhomboid-x", "rhomboid-y",
+NOINTERP or "normal". Determines the default way manhattan-aligned polygon
+NOINTERP edges are manupulated during edits.
+NOINTERP .sp
+NOINTERP \fBlinewidth\fP
+NOINTERP .sp
+NOINTERP Where \fIvalue\fP is a real number indicating the default
+NOINTERP width of lines.
+NOINTERP .sp
+NOINTERP \fBbeep\fP
+NOINTERP .sp
+NOINTERP Where \fIvalue\fP can be \fBon\fP or \fBoff\fP, depending on
+NOINTERP whether or not you want the machine beeping at you when it
+NOINTERP gives critical warnings.
+NOINTERP .sp
+NOINTERP \fBcolorscheme\fP
+NOINTERP .sp
+NOINTERP Where \fIvalue\fP is \fBinverse\fP to swap the two color schemes
+NOINTERP and make the second scheme appear as default.
+
+TCL The startup file is written in Tcl. The command-line interface can
+TCL be found in the online documentation on the website
+TCL .sp
+TCL \fBhttp://www.opencircuitdesign.com/xcircuit/\fP.
+TCL .sp
+
+.SH CRASH RECOVERY
+XCircuit implements a crash recovery system by which a copy of the current
+file is made every 15 minutes (see Xdefaults, below, for changing this
+value). XCircuit deletes this file upon a normal exit. If, however,
+XCircuit crashes or is terminated by Control-C or other sudden death,
+the backup copy will remain. On startup, XCircuit checks the /tmp
+directory for any XCircuit backup files belonging to the user. If one
+is found, XCircuit will prompt the user for recovery. Note that the
+backup is unique in that it contains a copy of the entire user space at
+the time of the crash. Filenames may get overwritten, as the backup
+will treat all pages as belonging to the same file.
+
+.SH KEY BINDINGS
+As noted above, keys can be bound and unbound through command-line
+functions "bind" and "unbind". Default key bindings are used throughout
+this manual page. Key names use the notation of
+/usr/X11R6/include/keysymdef.h, but with the notation "XK_" being
+optional, and including the addition of prefixes "Shift_", "Control_",
+"Capslock_", and "Alt_", which may be used in any combination. Note
+that "Shift_" is not used for ASCII characters (e.g., "A" is used
+instead of "Shift_a") unless used in combination with other special
+keys (such as "Control_Shift_A" to distinguish from "Control_a",
+should that be desired). "Button1", "Button2", and "Button3" are
+also valid names indicating functions attached to the mouse buttons
+in normal drawing mode. Valid functions which may be bound are as
+follows, with their default values given:
+.br
+.sp
+
+ Function name Function performed Default key binding
+ ---------------------------------------------------------------------
+ "Page", change page, Number keys 1-9 and 0
+ "Justify", change text justification, Keypad keys 1-9
+ "Superscript", set text superscript, Keypad +
+ "Subscript", set text subscript, Keypad -
+ "Normalscript", cancel sub/superscript, Keypad Enter
+ "Nextfont", change to next font, Alt-f
+ "Boldfont", change to bold font, Alt-b
+ "Italicfont", change to italic font, Alt-i
+ "Normalfont", cancel italic/bold, Alt-n
+ "Underline", generate underline, Alt-u
+ "Overline", generate overline, Alt-o
+ "ISO Encoding", change to ISO encoding, Alt-e
+ "Return", embedded return character, Alt-Enter
+ "Halfspace", embedded half-space, Alt-h
+ "Quarterspace", embedded quarter-space, Alt-q
+ "Special", special character, Alt-c
+ "Parameter", embedded parameter, Alt-p
+ "Edit Break", break at point, x
+ "Edit Delete", delete point, d, Delete
+ "Edit Insert", insert point, i, Insert
+ "Edit Next", go to next point, e
+ "Attach", attach line to object, A
+ "Next Library", go to next library, l
+ "Library Directory", library directory, L
+ "Library Move", arrange library objects, M
+ "Library Copy", get object in copy mode, c
+ "Library Edit", edit library name, E
+ "Library Delete", delete library object, D
+ "Library Duplicate", duplicate object, C
+ "Library Hide", hide library object, H
+ "Page Directory ", page directory, P
+ "Library Pop", return from library, <
+ "Help", generate help screen, h, ?
+ "Redraw", redraw the window, space
+ "View", fit page to window, v
+ "Zoom In", zoom in, Z
+ "Zoom Out", zoom out, z
+ "Pan", center pan, p
+ "Double Snap", increase snap space, +
+ "Halve Snap", decrease snap space, -
+ "Pan Left", pan left one-half page, Left arrow
+ "Pan Right", pan right one-half page, Right arrow
+ "Pan Up", pan up one-half page, Up arrow
+ "Pan Down", pan down one-half page, Down arrow
+ "Write", popup output window, W
+ "Rotate", Rotate, r,R,o,O
+ "Flip X", Flip horizontal, f
+ "Flip Y", Flip vertical, F
+ "Snap", Snap to grid, S
+ "Pop", Return from object edit, <
+ "Push", Edit object, >
+ "Delete", Delete element, d
+ "Select", Select element, Select
+ "Box", Create box, b
+ "Arc", Create arc, a
+ "Text", Create label, t
+ "Exchange", Exchange vertical order, X
+ "Copy", Copy element, c
+ "Join", Join into path, j
+ "Unjoin", Split path into elements, J
+ "Spline", Create spline, s
+ "Edit", Edit element, e
+ "Undelete", Undelete last deleted, u
+ "Select Save", Make object from selected, M,m
+ "Unselect", Unselect element, x
+ "Dashed", Set line style to dashed, |
+ "Dotted", Set line style to dotted, :
+ "Solid", Set line style to solid, _
+ "Prompt", Execute from command line, %
+ "Dot", Place dot at location, .
+ "Exit", Exit xcircuit Ctrl-Alt-q
+ "Netlist", Generate a netlist, Alt-q
+ "Swap", Swap schematic, symbol, /
+ "Pin Label", Create pin label, T
+ "Info Label", Create info label, I
+ "Connectivity", Show wire connectivity, Alt-w
+ "Sim", Generate sim netlist, Alt-s
+ "SPICE", Generate SPICE netlist, Alt-S
+ "PCB", Generate PCB netlist, Alt-p
+ "SPICE Flat" Generate flattened SPICE, Alt-f
+ ------------------------------------------------------------------
+.br
+.sp
+2-Button mouse users may find it useful to forego the Shift-Button1
+combination and instead put the following commands in the startup
+script:
+.br
+.sp
+bind('Escape', 'Cancel')
+.br
+unbind('Button3', Cancel')
+.br
+bind('Button3', 'Finish')
+.br
+.sp
+This will move the 3rd mouse button bindings to the "Escape" key, and
+duplicate the 2nd mouse button bindings onto the 3rd.
+.br
+.sp
+.SH X DEFAULTS
+The color scheme of xcircuit has a default setup, but accepts
+alternate color schemes using the following keywords which can be put
+in the X Defaults (.Xdefaults, .Xresources) file, such as:
+.sp
+.EX 0
+ !
+.br
+ ! Sample X defaults for xcircuit, black-on-white version
+.br
+ !
+.br
+ xcircuit*foreground : Black
+.br
+ xcircuit*background : White
+.br
+ xcircuit*gridcolor : Gray85
+.br
+ xcircuit*snapcolor : Orange
+.br
+ xcircuit*selectcolor : Blue
+.br
+ xcircuit*querycolor : Green
+.br
+ xcircuit*axescolor : NavajoWhite3
+.br
+ xcircuit*offbuttoncolor : Gray30
+.br
+ xcircuit*auxiliarycolor : MediumOrchid1
+.EE
+.sp
+Two color schemes are supported at a time, ostensibly for those people
+who prefer the lessened eye strain of a white-on-black scheme. The
+names of the secondary colors are the same as those for the primary
+colors, but followed by "2", e.g., "xcircuit*foreground2".
+.sp
+.sp
+One other resource defines the number of minutes between automatic saves
+to the temporary file (in case of a crash or emergency Ctrl-C exit):
+.sp
+.EX 0
+ xcircuit.timeout : 15
+.EE
+.sp
+Xcircuit also recognizes the core resources, such as width and height:
+.sp
+.EX 0
+ xcircuit.width : 600
+.br
+ xcircuit.height : 500
+.EE
+.sp
+All xcircuit foreground and background colors are taken from the
+Xdefaults foreground and background. To get, for instance, white-on-black
+menus and buttons with a black-on-white drawing area, use the following:
+.sp
+.EX 0
+ xcircuit*foreground : White
+.br
+ xcircuit*background : DarkSlateGray
+.br
+ xcircuit.foreground : Black
+.br
+ xcircuit.background : White
+.br
+This will ensure that only the drawing area is black-on-white, but all other
+windows will appear in the less eye-straining white-on-black.
+.br
+Five different fonts can be specified in the Xdefaults. \fihelpfont\fp is
+the style of fonts on the help popup window. \fifilefont\fp is the style
+of fonts in the list of files in the file selection popup window. \fitextfont\fp
+is the style of font for entering text in the popup dialog boxes. \fititlefont\fp
+is the style of font for the cascade menu titles. All other fonts take the
+type \fifont\fp. For example:
+.br
+ xcircuit*font : *times-bold-r-normal--14*
+.br
+ xcircuit*helpfont : *times-medium-r-normal--12*
+.br
+ xcircuit*filefont : *times-medium-r-normal--14*
+.br
+ xcircuit*textfont : *courier-medium-r-normal--14*
+.br
+ xcircuit*titlefont : *times-bold-r-normal--18*
+.SH FILES
+The file path used by xcircuit to find library files is system-dependent
+(i.e., can be changed at compile time), and can be overridden in many
+ways (in .xcircuitrc or by the XCIRCUIT_LIB_DIR environment variable),
+but by default is:
+.sp
+.TP 28
+.B LIBDIR
+.sp
+.TP 15
+.B xcircps2.pro
+PostScript prolog appended to each file
+.TP 15
+PYTHON .B xcstartup.py
+TCL .B xcstartup.tcl
+NOINTERP .B startup.script
+This startup script contains commands of the type
+PYTHON \fBlibrary\fP("\fIname\fP", \fInumber\fP
+TCL \fBlibrary\fP \fIname\fP \fInumber\fP
+NOINTERP \fBlibrary\fP \fIname\fP \fInumber\fP
+which cause the designated library \fIname\fP to be immediately loaded
+into library page \fInumber\fP. The startup script is also responsible
+for loading fonts, and may also be used to load colors on the color
+palette, set other options, and execute commands.
+.TP 15
+.B generic.lps, analog.lps, digital.lps, avlsi.lps, analoglib2.lps
+Files containing pre-compiled circuit elements. The \fB.lps\fP extension
+is unique for xcircuit libraries.
+.TP 15
+.B fonts
+This subdirectory contains font definition files for xcircuit's
+vector-drawn fonts. Characters are defined by xcircuit objects and
+stored in a \fB.lps\fP library. The encoding scheme and other font
+information is stored in a \fB.xfe\fP ("xcircuit font encoding")
+file.
+.TP 15
+.B ~/.xcircuitrc \fPor\fB ./xcircuitrc
+Personal xcircuit initializer; commands are outlined above.
+Libraries listed in this file will be appended to the builtin libraries.
+.SH ENVIRONMENT VARIABLES
+\fBxcircuit\fP understands the following environment variables:
+.sp
+.TP 15
+.B TMPDIR
+Directory for temporary (e.g., backup) files (defaults to TEMP_DIR).
+
+.TP 15
+.B XCIRCUIT_LIB_DIR
+Directory where xcircuit libraries and startup files can be found
+(defaults to BUILTINS_DIR).
+
+.TP 15
+.B XAPPLRESDIR
+Directory where the xcircuit application defaults can be found
+(defaults to RESOURCES_DIR)
+
+.TP 15
+.B HOME
+Directory where xcircuit will look for startup files, after searching the
+current directory.
+
+.TP 15
+.B HOST, HOSTNAME, USER
+Environment variables which xcircuit uses to fill in header information
+in the PostScript output (HOST and HOSTNAME are equivalent).
+
+.SH BUGS
+PostScript printers have device-dependent limits on the number of
+statements within a "def" definition. If an object definition has an
+unusually large number of components, xcircuit will flag a warning when
+writing the file. However, there is no way to ensure that a file will be
+accepted by a given printer. The best way to avoid the problem is to make
+sure that large drawings make good use of hierarchically nested user-defined
+objects. Note that printer errors arising from this problem have not been
+observed in practice, and given the typical size of on-board memory on most
+modern laser printers, probably never will be.
+.sp
+A list of bugs can be found in the Manifest file in the source directory.
+.SH ONLINE TUTORIAL
+Look for the xcircuit online tutorial at
+.sp
+http://opencircuitdesign.com/xcircuit/tutorial/tutorial.html
+.SH SEE ALSO
+xfig(1), another powerful freeware drawing program worthy of mention
+(see www.xfig.org).
+Another schematic capture package worth noting is "gschem" from the
+gEDA package (see www.geda.seul.org).
+.SH NOTES
+PostScript is a registered trademark of Adobe Systems Incorporated.
+.br
+XCircuit Copyright (c) 2002 Tim Edwards. XCircuit is freely distributed
+under a generous public license. See the source distribution for details.
+.br
+Xw widget set Copyright (c) 1988 by Hewlett-Packard Company and the
+Massachusetts Institute of Technology.
+.SH AUTHOR
+Tim Edwards <tim@opencircuitdesign.com>. Thanks to Tomas Rokicki for
+the PostScript routine which manufactures a Symbol-Oblique font.
+Thanks to Dave Gillespie and John Lazzaro for the program "analog"
+on which the graphical interface of xcircuit is (roughly) based.
+Thanks to many beta-testers, some of whom were kind enough to send
+patches. Most contributors have been named in the Manifest file in
+the source distribution.
diff --git a/libraries.c b/libraries.c
new file mode 100644
index 0000000..ce57086
--- /dev/null
+++ b/libraries.c
@@ -0,0 +1,1814 @@
+/*-------------------------------------------------------------------------*/
+/* libraries.c --- xcircuit routines for the builtin and user libraries */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/13/93 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+#include <math.h>
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*-------------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*-------------------------------------------------------------------------*/
+
+extern Display *dpy; /* Works well to make this globally accessible */
+extern int *appcolors;
+extern Cursor appcursors[NUM_CURSORS];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern char _STR[150];
+extern short fontcount;
+extern fontinfo *fonts;
+extern Boolean was_preselected;
+
+/*---------------------------------------------------------*/
+/* Find the Helvetica font for use in labeling the objects */
+/*---------------------------------------------------------*/
+
+short findhelvetica()
+{
+ short fval;
+
+ if (fontcount == 0) loadfontfile("Helvetica");
+
+ for (fval = 0; fval < fontcount; fval++)
+ if (!strcmp(fonts[fval].psname, "Helvetica"))
+ break;
+
+ /* If not there, use the first Helvetica font */
+
+ if (fval == fontcount) {
+ for (fval = 0; fval < fontcount; fval++)
+ if (!strcmp(fonts[fval].family, "Helvetica"))
+ break;
+ }
+
+ /* If still not there, use the first non-Symbol font */
+ /* If this doesn't work, then the libraries are probably misplaced. . .*/
+
+ if (fval == fontcount) {
+ for (fval = 0; fval < fontcount; fval++)
+ if (strcmp(fonts[fval].family, "Symbol"))
+ break;
+ }
+
+ return fval;
+}
+
+/*-------------------------------------------*/
+/* Return to drawing window from the library */
+/*-------------------------------------------*/
+
+void catreturn()
+{
+ /* Pop the object being edited from the push stack. */
+
+ popobject(NULL, (pointertype)1, NULL);
+}
+
+/*------------------------------------------------------*/
+/* Find page number from cursor position */
+/* Mode = 0: Look for exact corresponding page number */
+/* and return -1 if out-of-bounds */
+/* Mode = 1: Look for position between pages, return */
+/* page number of page to the right. */
+/*------------------------------------------------------*/
+
+int pageposition(short libmode, int x, int y, int mode)
+{
+ int xin, yin, bpage, pages;
+ int gxsize, gysize, xdel, ydel;
+
+ pages = (libmode == PAGELIB) ? xobjs.pages : xobjs.numlibs;
+ computespacing(libmode, &gxsize, &gysize, &xdel, &ydel);
+ window_to_user(x, y, &areawin->save);
+
+ if (mode == 0) { /* On-page */
+ if (areawin->save.x >= 0 && areawin->save.y <= 0) {
+ xin = areawin->save.x / xdel;
+ yin = areawin->save.y / ydel;
+ if (xin < gxsize && yin > -gysize) {
+ bpage = (xin % gxsize) - (yin * gxsize);
+ if (bpage < pages)
+ return bpage;
+ }
+ }
+ return -1;
+ }
+ else { /* Between-pages */
+ xin = (areawin->save.x + (xdel >> 1)) / xdel;
+ if (xin > gxsize) xin = gxsize;
+ if (xin < 0) xin = 0;
+ yin = areawin->save.y / ydel;
+ if (yin > 0) yin = 0;
+ if (yin < -gysize) yin = -gysize;
+ bpage = (xin % (gxsize + 1)) + 1 - (yin * gxsize);
+ if (bpage > pages + 1) bpage = pages + 1;
+ return bpage;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Find the number of other pages linked to the */
+/* indicated page (having the same filename, and */
+/* ignoring empty pages). result is the total number */
+/* of pages in the output file. */
+/*------------------------------------------------------*/
+
+short pagelinks(int page)
+{
+ int i;
+ short count = 0;
+
+ for (i = 0; i < xobjs.pages; i++)
+ if (xobjs.pagelist[i]->pageinst != NULL)
+ if (xobjs.pagelist[i]->pageinst->thisobject->parts > 0)
+ if ((i == page) || (xobjs.pagelist[i]->filename &&
+ xobjs.pagelist[page]->filename &&
+ (!filecmp(xobjs.pagelist[i]->filename,
+ xobjs.pagelist[page]->filename))))
+ count++;
+
+ return count;
+}
+
+/*------------------------------------------------------*/
+/* This is an expanded version of pagelinks() (above), */
+/* to deal with the separate issues of independent top- */
+/* level schematics and subcircuits. For the indicated */
+/* page, return a list of pages depending on the mode: */
+/* */
+/* mode = INDEPENDENT: independent top-level pages */
+/* mode = DEPENDENT: dependent pages (subcircuits) */
+/* mode = PAGE_DEPEND: subcircuits of the current page, */
+/* mode = LINKED_PAGES: subcircuits of the current */
+/* page, including parameter links */
+/* mode = TOTAL_PAGES: independent pages + subcircuits */
+/* mode = ALL_PAGES: all pages in xcircuit */
+/* */
+/* The list is the size of the number of pages, and */
+/* entries corresponding to the requested mode are set */
+/* nonzero (the actual number indicates the number of */
+/* references to the page, which may or may not be */
+/* useful to know). */
+/* */
+/* It is the responsibility of the calling routine to */
+/* free the memory allocated for the returned list. */
+/*------------------------------------------------------*/
+
+short *pagetotals(int page, short mode)
+{
+ int i;
+ short *counts, *icount;
+
+ if (xobjs.pagelist[page]->pageinst == NULL) return NULL;
+
+ counts = (short *)malloc(xobjs.pages * sizeof(short));
+ icount = (short *)malloc(xobjs.pages * sizeof(short));
+ for (i = 0; i < xobjs.pages; i++) {
+ *(counts + i) = 0;
+ *(icount + i) = 0;
+ }
+
+ /* Find all the subcircuits of this page */
+
+ if (mode != ALL_PAGES)
+ findsubschems(page, xobjs.pagelist[page]->pageinst->thisobject,
+ 0, counts, (mode == LINKED_PAGES) ? TRUE : FALSE);
+
+ /* Check independent entries (top-level pages which are not */
+ /* subcircuits of another page, but have the same filename */
+ /* as the page we started from). Set the counts entry to -1 */
+ /* to mark each independent page. */
+
+ if (mode != PAGE_DEPEND)
+ for (i = 0; i < xobjs.pages; i++)
+ if (xobjs.pagelist[i]->pageinst != NULL)
+ if (xobjs.pagelist[i]->pageinst->thisobject->parts > 0)
+ {
+ if (mode == ALL_PAGES)
+ (*(counts + i)) = 1;
+ else
+ {
+ if ((i == page) || (xobjs.pagelist[i]->filename
+ && xobjs.pagelist[page]->filename
+ && (!filecmp(xobjs.pagelist[i]->filename,
+ xobjs.pagelist[page]->filename))))
+ if ((mode == INDEPENDENT) || (*(counts + i) == 0))
+ (*(icount + i))++;
+ }
+ }
+
+ /* Check other dependent entries (top-level pages which are */
+ /* subcircuits of any independent page). */
+
+ if ((mode == DEPENDENT) || (mode == TOTAL_PAGES) || (mode == LINKED_PAGES))
+ {
+ for (i = 0; i < xobjs.pages; i++)
+ if ((i != page) && (*(icount + i) > 0))
+ findsubschems(i, xobjs.pagelist[i]->pageinst->thisobject,
+ 0, counts, (mode == LINKED_PAGES) ? TRUE : FALSE);
+ }
+
+ if (mode == INDEPENDENT)
+ {
+ free((char *)counts);
+ return icount;
+ }
+ else
+ {
+ if ((mode == TOTAL_PAGES) || (mode == LINKED_PAGES)) {
+ /* merge dependent and independent */
+ for (i = 0; i < xobjs.pages; i++)
+ if (*(icount + i) > 0)
+ (*(counts + i))++;
+ }
+ free((char *)icount);
+ return counts;
+ }
+}
+
+/*---------------------------------------------------------*/
+/* Test whether a library instance is a "virtual" instance */
+/*---------------------------------------------------------*/
+
+Boolean is_virtual(objinstptr thisinst) {
+ int libno;
+ liblistptr ilist;
+
+ libno = libfindobject(thisinst->thisobject, NULL);
+
+ for (ilist = xobjs.userlibs[libno].instlist; ilist != NULL; ilist = ilist->next)
+ if ((ilist->thisinst == thisinst) && (ilist->virtual == TRUE))
+ return TRUE;
+
+ return FALSE;
+}
+
+/*------------------------------------------------------*/
+/* Test whether an object is a page, and return the */
+/* page number if it is. Otherwise, return -1. */
+/*------------------------------------------------------*/
+
+int is_page(objectptr thisobj)
+{
+ int i;
+
+ for (i = 0; i < xobjs.pages; i++)
+ if (xobjs.pagelist[i]->pageinst != NULL)
+ if (xobjs.pagelist[i]->pageinst->thisobject == thisobj) return i;
+
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* Test whether an object is a library, and return the */
+/* library number if it is. Otherwise, return -1. */
+/*------------------------------------------------------*/
+
+int is_library(objectptr thisobj)
+{
+ int i;
+
+ for (i = 0; i < xobjs.numlibs; i++)
+ if (xobjs.libtop[i + LIBRARY]->thisobject == thisobj) return i;
+
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* Check for library name (string). Because XCircuit */
+/* generates the text "Library: <filename>" for */
+/* library names, we also check against <filename> */
+/* only in these names (this library name syntax is */
+/* deprecated, but the check is retained for backwards */
+/* compatibility). */
+/* */
+/* If no library matches the given name, return -1. */
+/*------------------------------------------------------*/
+
+int NameToLibrary(char *libname)
+{
+ char *slib;
+ int i;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ slib = xobjs.libtop[i + LIBRARY]->thisobject->name;
+ if (!strcmp(libname, slib)) {
+ return i;
+ }
+ else if (!strncmp(slib, "Library: ", 9)) {
+ if (!strcmp(libname, slib + 9)) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* Move an object and all of its virtual instances from */
+/* one library to another. */
+/*------------------------------------------------------*/
+
+int libmoveobject(objectptr thisobject, int libtarget)
+{
+ int j, libsource;
+ liblistptr spec, slast, srch;
+
+ libsource = libfindobject(thisobject, &j);
+
+ if (libsource == libtarget) return libsource; /* nothing to do */
+ if (libsource < 0) return libsource; /* object not in the library */
+
+ /* Move the object from library "libsource" to library "libtarget" */
+
+ xobjs.userlibs[libtarget].library = (objectptr *)
+ realloc(xobjs.userlibs[libtarget].library,
+ (xobjs.userlibs[libtarget].number + 1) * sizeof(objectptr));
+
+ *(xobjs.userlibs[libtarget].library + xobjs.userlibs[libtarget].number) = thisobject;
+ xobjs.userlibs[libtarget].number++;
+
+ for (; j < xobjs.userlibs[libsource].number; j++)
+ *(xobjs.userlibs[libsource].library + j) =
+ *(xobjs.userlibs[libsource].library + j + 1);
+ xobjs.userlibs[libsource].number--;
+
+ /* Move all instances from library "libsource" to library "libtarget" */
+
+ slast = NULL;
+ for (spec = xobjs.userlibs[libsource].instlist; spec != NULL;) {
+ if (spec->thisinst->thisobject == thisobject) {
+
+ /* Add to end of spec list in target */
+ srch = xobjs.userlibs[libtarget].instlist;
+ if (srch == NULL)
+ xobjs.userlibs[libtarget].instlist = spec;
+ else {
+ for (; srch->next != NULL; srch = srch->next);
+ spec->next = srch->next;
+ srch->next = spec;
+ }
+
+ if (slast != NULL) {
+ slast->next = spec->next;
+ spec = slast->next;
+ }
+ else {
+ xobjs.userlibs[libsource].instlist = spec->next;
+ spec = xobjs.userlibs[libsource].instlist;
+ }
+ }
+ else {
+ slast = spec;
+ spec = spec->next;
+ }
+ }
+
+ return libsource;
+}
+
+/*------------------------------------------------------*/
+/* Determine which library contains the specified */
+/* object. If found, return the library number, or */
+/* else return -1 if the object was not found in any */
+/* library. If "partidx" is non-null, fill with the */
+/* integer offset of the object from the beginning of */
+/* the library. */
+/*------------------------------------------------------*/
+
+int libfindobject(objectptr thisobject, int *partidx)
+{
+ int i, j;
+ objectptr libobj;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ libobj = *(xobjs.userlibs[i].library + j);
+ if (libobj == thisobject) {
+ if (partidx != NULL) *partidx = j;
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* ButtonPress handler during page catalog viewing mode */
+/*------------------------------------------------------*/
+
+void pagecat_op(int op, int x, int y)
+{
+ int bpage;
+ short mode;
+
+ for (mode = 0; mode < LIBRARY; mode++) {
+ if (areawin->topinstance == xobjs.libtop[mode]) break;
+ }
+ if (mode == LIBRARY) return; /* Something went wrong if this happens */
+
+ if (op != XCF_Cancel) {
+ if ((bpage = pageposition(mode, x, y, 0)) >= 0) {
+
+ if (eventmode == ASSOC_MODE) {
+ if (mode == PAGELIB) {
+ /* using changepage() allows use of new page for schematic */
+ changepage(bpage);
+ /* associate the new schematic */
+ schemassoc(topobject, areawin->stack->thisinst->thisobject);
+ /* pop back to calling (symbol) page */
+ catreturn();
+ eventmode = NORMAL_MODE;
+ }
+ else {
+ areawin->lastlibrary = bpage;
+ startcatalog(NULL, (pointertype)(LIBRARY + bpage), NULL);
+ }
+ return;
+ }
+ else if (op == XCF_Select) {
+ if (mode == PAGELIB) /* No such method for LIBLIB is defined. */
+ select_add_element(OBJINST);
+ }
+ else if ((op == XCF_Library_Pop) || (op == XCF_Finish)) {
+
+ /* like catreturn(), but don't actually go to the popped page */
+ unselect_all();
+ eventmode = NORMAL_MODE;
+ if (mode == PAGELIB) {
+ newpage(bpage);
+ }
+ else {
+ startcatalog(NULL, (pointertype)(LIBRARY + bpage), NULL);
+ }
+ return;
+ }
+ }
+ }
+ else {
+ eventmode = NORMAL_MODE;
+ catreturn();
+ }
+}
+
+/*------------------------------------------------------------------------------*/
+/* Subroutine to find the correct scale and position of the object instance */
+/* representing an entire page in the page directory. */
+/*------------------------------------------------------------------------------*/
+
+void pageinstpos(short mode, short tpage, objinstptr drawinst, int gxsize,
+ int gysize, int xdel, int ydel)
+{
+ objectptr libobj = drawinst->thisobject;
+ float scalex, scaley;
+
+ drawinst->position.x = (tpage % gxsize) * xdel;
+ drawinst->position.y = -(tpage / gxsize + 1) * ydel;
+
+ /* center the object on its page bounding box */
+
+ if (drawinst->bbox.width == 0 || drawinst->bbox.height == 0) {
+ drawinst->scale = 0.45 * libobj->viewscale;
+ drawinst->position.x += 0.05 * xdel - libobj->pcorner.x * drawinst->scale;
+ drawinst->position.y += 0.05 * ydel - libobj->pcorner.y * drawinst->scale;
+ }
+ else {
+ scalex = (0.9 * xdel) / drawinst->bbox.width;
+ scaley = (0.9 * ydel) / drawinst->bbox.height;
+ if (scalex > scaley) {
+ drawinst->scale = scaley;
+ drawinst->position.x -= (drawinst->bbox.lowerleft.x * scaley);
+ drawinst->position.x += (xdel - (drawinst->bbox.width * scaley)) / 2;
+ drawinst->position.y += 0.05 * ydel - drawinst->bbox.lowerleft.y
+ * drawinst->scale;
+ }
+ else {
+ drawinst->scale = scalex;
+ drawinst->position.y -= (drawinst->bbox.lowerleft.y * scalex);
+ drawinst->position.y += (ydel - (drawinst->bbox.height * scalex)) / 2;
+ drawinst->position.x += 0.05 * xdel - drawinst->bbox.lowerleft.x
+ * drawinst->scale;
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Make a new instance for inserting into the page directory */
+/*--------------------------------------------------------------*/
+
+objinstptr newpageinst(objectptr pageobj)
+{
+ objinstptr newinst = (objinstptr) malloc(sizeof(objinst));
+ instancedefaults(newinst, pageobj, 0, 0);
+ newinst->type = OBJINST;
+ newinst->color = DEFAULTCOLOR;
+ newinst->style = NORMAL; /* Do not scale linewidth with page scale */
+ return newinst;
+}
+
+/*-----------------------------------------------------------*/
+/* Find spacing of objects for pages in the page directories */
+/*-----------------------------------------------------------*/
+
+void computespacing(short mode, int *gxsize, int *gysize, int *xdel, int *ydel)
+{
+ int pages = (mode == PAGELIB) ? xobjs.pages : xobjs.numlibs;
+
+ *gxsize = (int)sqrt((double)pages) + 1;
+ *gysize = 1 + pages / (*gxsize);
+
+ /* 0.5 is the default vscale; g#size is the number of pages per line */
+
+ *xdel = areawin->width / (0.5 * (*gxsize));
+ *ydel = areawin->height / (0.5 * (*gysize));
+}
+
+/*-------------------------------------------------------------------*/
+/* Draw the catalog of page ordering or the library master directory */
+/*-------------------------------------------------------------------*/
+
+void composepagelib(short mode)
+{
+ genericptr *pgen;
+ objinstptr drawinst;
+ objectptr libobj, directory = xobjs.libtop[mode]->thisobject;
+ short i;
+ polyptr *drawbox;
+ labelptr *pagelabel;
+ stringpart *strptr;
+ pointlist pointptr;
+ int margin, xdel, ydel, gxsize, gysize;
+ int pages = (mode == PAGELIB) ? xobjs.pages : xobjs.numlibs;
+ short fval = findhelvetica();
+
+ /* Like the normal libraries, instances come from a special list, so */
+ /* they should not be destroyed, but will be null'd out and retrieved */
+ /* from the list. */
+
+ for (pgen = directory->plist; pgen < directory->plist + directory->parts; pgen++)
+ if (IS_OBJINST(*pgen)) *pgen = NULL;
+
+ reset(directory, NORMAL);
+
+ /* generate the list of object instances */
+
+ directory->plist = (genericptr *)malloc(sizeof(genericptr));
+ directory->parts = 0;
+
+ computespacing(mode, &gxsize, &gysize, &xdel, &ydel);
+ margin = xdel / 40; /* margin between pages */
+
+ for (i = 0; i < pages; i++) {
+ drawinst = (mode == PAGELIB) ? xobjs.pagelist[i]->pageinst :
+ xobjs.libtop[i + LIBRARY];
+ if (drawinst != NULL) {
+ libobj = drawinst->thisobject;
+
+ /* This is a stop-gap measure. . . should be recalculating the bounds of */
+ /* the instance on every action, not just before arranging the library. */
+ drawinst->bbox.lowerleft.x = libobj->bbox.lowerleft.x;
+ drawinst->bbox.lowerleft.y = libobj->bbox.lowerleft.y;
+ drawinst->bbox.width = libobj->bbox.width;
+ drawinst->bbox.height = libobj->bbox.height;
+ /* End stop-gap measure */
+
+ PLIST_INCR(directory);
+ *(directory->plist + directory->parts) = (genericptr)drawinst;
+ directory->parts++;
+ pageinstpos(mode, i, drawinst, gxsize, gysize, xdel, ydel);
+ }
+
+ /* separate pages (including empty ones) with bounding boxes */
+
+ NEW_POLY(drawbox, directory);
+ (*drawbox)->color = LOCALPINCOLOR; /* default red */
+ (*drawbox)->style = NORMAL; /* CLOSED */
+ (*drawbox)->width = 1.0;
+ (*drawbox)->number = 4;
+ (*drawbox)->points = (pointlist) malloc(4 * sizeof(XPoint));
+ (*drawbox)->passed = NULL;
+ (*drawbox)->cycle = NULL;
+ pointptr = (*drawbox)->points;
+ pointptr->x = (i % gxsize) * xdel + margin;
+ pointptr->y = -(i / gxsize) * ydel - margin;
+ pointptr = (*drawbox)->points + 1;
+ pointptr->x = ((i % gxsize) + 1) * xdel - margin;
+ pointptr->y = -(i / gxsize) * ydel - margin;
+ pointptr = (*drawbox)->points + 2;
+ pointptr->x = ((i % gxsize) + 1) * xdel - margin;
+ pointptr->y = -((i / gxsize) + 1) * ydel + margin;
+ pointptr = (*drawbox)->points + 3;
+ pointptr->x = (i % gxsize) * xdel + margin;
+ pointptr->y = -((i / gxsize) + 1) * ydel + margin;
+
+ /* each page gets its name printed at the bottom */
+
+ if (drawinst != NULL) {
+ NEW_LABEL(pagelabel, directory);
+ labeldefaults(*pagelabel, False, (pointptr->x + (pointptr-1)->x) / 2,
+ pointptr->y - 5);
+ (*pagelabel)->color = DEFAULTCOLOR;
+ (*pagelabel)->scale = 0.75;
+ (*pagelabel)->string->data.font = fval;
+ (*pagelabel)->passed = NULL;
+ strptr = makesegment(&((*pagelabel)->string), NULL);
+ strptr->type = TEXT_STRING;
+ strptr->data.string = (char *) malloc(1 + strlen(libobj->name));
+ strcpy(strptr->data.string, libobj->name);
+ (*pagelabel)->justify = TOP | NOTBOTTOM | NOTLEFT;
+ }
+ }
+
+ /* calculate a bounding box for this display */
+ /* and center it in its window */
+
+ calcbbox(xobjs.libtop[mode]);
+ centerview(xobjs.libtop[mode]);
+}
+
+/*------------------------------------------------------------*/
+/* Update the page or library directory based on new bounding */
+/* box information for the page or library passed in "tpage". */
+/*------------------------------------------------------------*/
+
+void updatepagelib(short mode, short tpage)
+{
+ objectptr compobj, libinst = xobjs.libtop[mode]->thisobject;
+ objinstptr pinst;
+ genericptr *gelem;
+ int i, xdel, ydel, gxsize, gysize, lpage;
+
+ /* lpage is the number of the page as found on the directory page */
+ lpage = (mode == PAGELIB) ? tpage : tpage - LIBRARY;
+ compobj = (mode == PAGELIB) ? xobjs.pagelist[tpage]->pageinst->thisobject
+ : xobjs.libtop[tpage]->thisobject;
+
+ computespacing(mode, &gxsize, &gysize, &xdel, &ydel);
+
+ for (i = 0; i < libinst->parts; i++) {
+ gelem = libinst->plist + i;
+ if (IS_OBJINST(*gelem)) {
+ pinst = TOOBJINST(gelem);
+ if (pinst->thisobject == compobj) {
+ /* recalculate scale and position of the object instance */
+ pageinstpos(mode, lpage, pinst, gxsize, gysize, xdel, ydel);
+ break;
+ }
+ }
+ }
+
+ /* if there is no instance for this page, then recompose the whole library */
+
+ if (i == libinst->parts) composelib(mode);
+}
+
+/*----------------------*/
+/* Rearrange pages */
+/*----------------------*/
+
+void pagecatmove(int x, int y)
+{
+ int bpage;
+ objinstptr exchobj;
+ Pagedata *ipage, **testpage, **tpage2;
+
+ if (areawin->selects == 0) return;
+ else if (areawin->selects > 2) {
+ Wprintf("Select maximum of two objects.");
+ return;
+ }
+
+ /* Get the page corresponding to the first selected object */
+
+ exchobj = SELTOOBJINST(areawin->selectlist);
+ for (testpage = xobjs.pagelist; testpage < xobjs.pagelist + xobjs.pages; testpage++)
+ if (*testpage != NULL && (*testpage)->pageinst == exchobj)
+ break;
+
+ /* If two objects are selected, then exchange their order */
+
+ if (areawin->selects == 2) {
+ exchobj = SELTOOBJINST(areawin->selectlist + 1);
+ for (tpage2 = xobjs.pagelist; tpage2 < xobjs.pagelist + xobjs.pages; tpage2++)
+ if (*tpage2 != NULL && (*tpage2)->pageinst == exchobj)
+ break;
+
+ ipage = *testpage;
+ *testpage = *tpage2;
+ *tpage2 = ipage;
+ }
+
+ /* If one object selected; find place to put from cursor position */
+
+ else if ((bpage = pageposition(PAGELIB, x, y, 1)) >= 0) {
+ int k, epage;
+ Pagedata *eptr;
+
+ /* Find page number of the original page */
+
+ epage = (int)(testpage - xobjs.pagelist);
+ eptr = *(xobjs.pagelist + epage);
+
+ /* move page (epage) to position between current pages */
+ /* (bpage - 2) and (bpage - 1) by shifting pointers. */
+
+ if ((bpage - 1) < epage) {
+ for (k = epage - 1; k >= bpage - 1; k--) {
+ *(xobjs.pagelist + k + 1) = *(xobjs.pagelist + k);
+ renamepage(k + 1);
+ }
+ *(xobjs.pagelist + bpage - 1) = eptr;
+ renamepage(bpage - 1);
+ }
+ else if ((bpage - 2) > epage) {
+ for (k = epage + 1; k <= bpage - 2; k++) {
+ *(xobjs.pagelist + k - 1) = *(xobjs.pagelist + k);
+ renamepage(k - 1);
+ }
+ *(xobjs.pagelist + bpage - 2) = eptr;
+ renamepage(bpage - 2);
+ }
+ }
+
+ unselect_all();
+ composelib(PAGELIB);
+ drawarea(NULL, NULL, NULL);
+}
+
+/*-----------------------------------------*/
+/* Draw the catalog of predefined elements */
+/*-----------------------------------------*/
+
+void composelib(short mode)
+{
+ genericptr *pgen;
+ objinstptr drawinst;
+ labelptr *drawname;
+ objectptr libobj, libpage = xobjs.libtop[mode]->thisobject;
+ liblistptr spec;
+ int xpos = 0, ypos = areawin->height << 1;
+ int nypos = 220, nxpos;
+ short fval;
+ short llx, lly, urx, ury, width, height, xcenter;
+
+ int totalarea, targetwidth;
+ double scale, savescale;
+ short savemode;
+ XPoint savepos;
+
+ /* Also make composelib() a wrapper for composepagelib() */
+ if ((mode > FONTLIB) && (mode < LIBRARY)) {
+ composepagelib(mode);
+ return;
+ }
+
+ /* The instances on the library page come from the library's */
+ /* "instlist". So that we don't destroy the actual instance when we */
+ /* call reset(), we find the pointer to the instance and NULL it. */
+
+ for (pgen = libpage->plist; pgen < libpage->plist + libpage->parts; pgen++)
+ if (IS_OBJINST(*pgen)) *pgen = NULL;
+
+ /* Before resetting, save the position and scale. We will restore */
+ /* them at the end. */
+
+ savepos = libpage->pcorner;
+ savescale = libpage->viewscale;
+ reset(libpage, NORMAL);
+
+ /* Return if library defines no objects or virtual instances */
+
+ if (xobjs.userlibs[mode - LIBRARY].instlist == NULL) return;
+
+ /* Find the Helvetica font for use in labeling the objects */
+
+ fval = findhelvetica();
+
+ /* Attempt to produce a library with the same aspect ratio as the */
+ /* drawing window. This is only approximate, and does not take */
+ /* into account factors such as the length of the name string. */
+
+ totalarea = 0;
+ for (spec = xobjs.userlibs[mode - LIBRARY].instlist; spec != NULL;
+ spec = spec->next) {
+ libobj = spec->thisinst->thisobject;
+
+ /* "Hidden" objects are not drawn */
+ if (libobj->hidden == True) continue;
+
+ drawinst = spec->thisinst;
+ drawinst->position.x = 0;
+ drawinst->position.y = 0;
+
+ /* Get the bounding box of the instance in the page's coordinate system */
+ calcinstbbox((genericptr *)(&drawinst), &llx, &lly, &urx, &ury);
+ width = urx - llx;
+ height = ury - lly;
+ width += 30; /* space padding */
+ height += 30; /* height padding */
+ if (width < 200) width = 200; /* minimum box width */
+ if (height < 220) height = 220; /* minimum box height */
+ totalarea += (width * height);
+ }
+
+ scale = (double)totalarea / (double)(areawin->width * areawin->height);
+ targetwidth = (int)(sqrt(scale) * (double)areawin->width);
+
+ /* generate the list of object instances and their labels */
+
+ savemode = eventmode;
+ eventmode = CATALOG_MODE;
+ for (spec = xobjs.userlibs[mode - LIBRARY].instlist; spec != NULL;
+ spec = spec->next) {
+ libobj = spec->thisinst->thisobject;
+
+ /* "Hidden" objects are not drawn */
+ if (libobj->hidden == True) continue;
+
+ drawinst = spec->thisinst;
+ drawinst->position.x = 0;
+ drawinst->position.y = 0;
+
+ /* Generate the part; unlike the usual NEW_OBJINST, the */
+ /* instance record isn't allocated. */
+
+ PLIST_INCR(libpage);
+ *(libpage->plist + libpage->parts) = (genericptr)drawinst;
+ libpage->parts++;
+
+ /* Get the bounding box of the instance in the page's coordinate system */
+ calcinstbbox((genericptr *)(&drawinst), &llx, &lly, &urx, &ury);
+ xcenter = (llx + urx) >> 1;
+ width = urx - llx;
+ height = ury - lly;
+
+ /* Add an ad-hoc spacing rule of 30 for padding space between objects */
+ width += 30;
+
+ /* Prepare the object name and determine its width. Adjust width */
+ /* needed for object on the library page if necessary. */
+
+ if (fval < fontcount) {
+ stringpart *strptr;
+ TextExtents tmpext;
+
+ NEW_LABEL(drawname, libpage);
+ labeldefaults(*drawname, False, 0, 0);
+ (*drawname)->color = (spec->virtual) ?
+ OFFBUTTONCOLOR : DEFAULTCOLOR;
+ (*drawname)->scale = 0.75;
+ (*drawname)->string->data.font = fval;
+ strptr = makesegment(&((*drawname)->string), NULL);
+ strptr->type = TEXT_STRING;
+
+ strptr->data.string = strdup(libobj->name);
+ (*drawname)->justify = TOP | NOTBOTTOM | NOTLEFT;
+
+ /* If the label is longer than the object width, then */
+ /* adjust positions accordingly. Note that as an ad- */
+ /* hoc spacing rule, a padding of 30 is put between */
+ /* objects; this padding is reduced to 5 */
+
+ tmpext = ULength(*drawname, drawinst, 0, NULL);
+
+ /* Ad-hoc spacing rule is 5 for labels */
+ tmpext.width += 5;
+
+ if (tmpext.width > width)
+ width = tmpext.width;
+ }
+
+ /* Minimum allowed width is 200 */
+ if (width < 200) width = 200;
+
+ /* Determine the area needed on the page to draw the object */
+
+ nxpos = xpos + width;
+ if ((nxpos > targetwidth) && (xpos > 0)) {
+ nxpos -= xpos;
+ xpos = 0;
+ ypos -= nypos;
+ nypos = 200;
+ }
+
+ if (height > (nypos - 50)) nypos = height + 50;
+
+ drawinst->position.x = xpos + (width >> 1) - xcenter;
+ drawinst->position.y = ypos - (height + lly);
+ if (height <= 170) drawinst->position.y -= ((170 - height) >> 1);
+ drawinst->color = DEFAULTCOLOR;
+
+ if (fval < fontcount) {
+ (*drawname)->position.x = xpos + (width >> 1);
+
+ if (height > 170)
+ (*drawname)->position.y = drawinst->position.y + lly - 10;
+ else
+ (*drawname)->position.y = ypos - 180;
+
+ }
+ xpos = nxpos;
+ }
+ eventmode = savemode;
+
+ /* Compute the bounding box of the library page */
+ calcbbox(xobjs.libtop[mode]);
+
+ /* Update the library directory */
+ updatepagelib(LIBLIB, mode);
+
+ /* Restore original view position */
+ libpage->pcorner = savepos;
+ libpage->viewscale = savescale;
+}
+
+/*----------------------------------------------------------------*/
+/* Find any dependencies on an object. */
+/* Return values: 0 = no dependency, 1 = dependency on page, */
+/* 2 = dependency in another library object. */
+/* Object/Page with dependency (if any) returned in "compobjp". */
+/*----------------------------------------------------------------*/
+
+short finddepend(objinstptr libobj, objectptr **compobjp)
+{
+ genericptr *testobj;
+ short page, i, j;
+ objectptr *compobj;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ compobj = xobjs.userlibs[i].library + j;
+ *compobjp = compobj;
+
+ for (testobj = (*compobj)->plist; testobj < (*compobj)->plist
+ + (*compobj)->parts; testobj++) {
+ if (IS_OBJINST(*testobj)) {
+ if (TOOBJINST(testobj)->thisobject == libobj->thisobject) return 2;
+ }
+ }
+ }
+ }
+
+ /* also look in the xobjs.pagelist */
+
+ for (page = 0; page < xobjs.pages; page++) {
+ if (xobjs.pagelist[page]->pageinst == NULL) continue;
+ compobj = &(xobjs.pagelist[page]->pageinst->thisobject);
+ *compobjp = compobj;
+ for (testobj = (*compobj)->plist; testobj < (*compobj)->plist
+ + (*compobj)->parts; testobj++) {
+ if (IS_OBJINST(*testobj)) {
+ if (TOOBJINST(testobj)->thisobject == libobj->thisobject) return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------------*/
+/* Virtual copy: Make a separate copy of an object on the same */
+/* library page as the original, representing an instance of */
+/* the object with different parameters. The object must have */
+/* parameters for this to make sense, so check for parameters */
+/* before allowing the virtual copy. */
+/*--------------------------------------------------------------*/
+
+void catvirtualcopy()
+{
+ short i, *newselect;
+ objinstptr libobj, libinst;
+
+ if (areawin->selects == 0) return;
+ else if ((i = is_library(topobject)) < 0) return;
+
+ /* Check for existance of parameters in the object for each */
+ /* selected instance */
+
+ for (newselect = areawin->selectlist; newselect < areawin->selectlist
+ + areawin->selects; newselect++) {
+ libobj = SELTOOBJINST(newselect);
+ libinst = addtoinstlist(i, libobj->thisobject, TRUE);
+ instcopy(libinst, libobj);
+ tech_mark_changed(GetObjectTechnology(libobj->thisobject));
+ }
+
+ clearselects();
+ composelib(LIBRARY + i);
+ drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* "Hide" an object (must have a dependency or else it disappears)*/
+/*----------------------------------------------------------------*/
+
+void cathide()
+{
+ int i;
+ short *newselect;
+ objectptr *compobj;
+ objinstptr libobj;
+
+ if (areawin->selects == 0) return;
+
+ /* Can only hide objects which are instances in other objects; */
+ /* Otherwise, object would be "lost". */
+
+ for (newselect = areawin->selectlist; newselect < areawin->selectlist
+ + areawin->selects; newselect++) {
+ libobj = SELTOOBJINST(newselect);
+
+ if (finddepend(libobj, &compobj) == 0) {
+ Wprintf("Cannot hide: no dependencies");
+ }
+ else { /* All's clear to hide. */
+ libobj->thisobject->hidden = True;
+ }
+ }
+
+ clearselects();
+
+ if ((i = is_library(topobject)) >= 0) composelib(LIBRARY + i);
+
+ drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Delete an object from the library if there are no dependencies */
+/*----------------------------------------------------------------*/
+
+void catdelete()
+{
+ short *newselect, *libpobjs;
+ int i;
+ /* genericptr *testobj, *tobj; (jdk) */
+ objinstptr libobj;
+ liblistptr ilist, llist;
+ objectptr *libpage, *compobj, *tlib, *slib;
+
+ if (areawin->selects == 0) return;
+
+ if ((i = is_library(topobject)) >= 0) {
+ libpage = xobjs.userlibs[i].library;
+ libpobjs = &xobjs.userlibs[i].number;
+ }
+ else
+ return; /* To-do: Should have a mechanism here for deleting pages! */
+
+ for (newselect = areawin->selectlist; newselect < areawin->selectlist
+ + areawin->selects; newselect++) {
+ libobj = SELTOOBJINST(newselect);
+
+ /* If this is just a "virtual copy", simply remove it from the list */
+
+ llist = NULL;
+ for (ilist = xobjs.userlibs[i].instlist; ilist != NULL;
+ llist = ilist, ilist = ilist->next) {
+ if ((ilist->thisinst == libobj) && (ilist->virtual == TRUE)) {
+ if (llist == NULL)
+ xobjs.userlibs[i].instlist = ilist->next;
+ else
+ llist->next = ilist->next;
+ break;
+ }
+ }
+ if (ilist != NULL) {
+ free(ilist);
+ continue;
+ }
+
+ /* Cannot delete an object if another object uses an instance of it, */
+ /* or if the object is used on a page. */
+
+ if (finddepend(libobj, &compobj)) {
+ Wprintf("Cannot delete: dependency in \"%s\"", (*compobj)->name);
+ }
+ else { /* All's clear to delete. */
+
+ /* Clear the undo stack so that any references to this object */
+ /* won't screw up the database (this could be kinder & gentler */
+ /* by first checking if there are any references to the object */
+ /* in the undo stack. . . */
+
+ flush_undo_stack();
+
+ /* Next, remove the object from the library page. */
+
+ for (tlib = libpage; tlib < libpage + *libpobjs; tlib++)
+ if ((*tlib) == libobj->thisobject) {
+ for (slib = tlib; slib < libpage + *libpobjs - 1; slib++)
+ (*slib) = (*(slib + 1));
+ (*libpobjs)--;
+ break;
+ }
+
+ /* Next, remove all instances of the object on the library page. */
+
+ llist = NULL;
+ for (ilist = xobjs.userlibs[i].instlist; ilist != NULL;
+ llist = ilist, ilist = ilist->next) {
+ if (ilist->thisinst->thisobject == libobj->thisobject) {
+ if (llist == NULL) {
+ xobjs.userlibs[i].instlist = ilist->next;
+ free(ilist);
+ if (!(ilist = xobjs.userlibs[i].instlist)) break;
+ }
+ else {
+ llist->next = ilist->next;
+ free(ilist);
+ if (!(ilist = llist)) break;
+ }
+ }
+ }
+
+ /* Finally, delete the object (permanent---no undoing this!) */
+ tech_mark_changed(GetObjectTechnology(libobj->thisobject));
+ reset(libobj->thisobject, DESTROY);
+ }
+ }
+
+ clearselects();
+
+ if ((i = is_library(topobject)) >= 0) {
+ composelib(LIBRARY + i);
+ }
+
+ drawarea(NULL, NULL, NULL);
+}
+
+/*------------------------------------------------------*/
+/* Linked list rearrangement routines */
+/*------------------------------------------------------*/
+
+void linkedlistswap(liblistptr *spec, int o1, int o2)
+{
+ liblistptr s1, s1m, s2, s2m, stmp;
+ int j;
+
+ if (o1 == o2) return;
+
+ s1m = NULL;
+ s1 = *spec;
+ for (j = 0; j < o1; j++) {
+ s1m = s1;
+ s1 = s1->next;
+ }
+
+ s2m = NULL;
+ s2 = *spec;
+ for (j = 0; j < o2; j++) {
+ s2m = s2;
+ s2 = s2->next;
+ }
+
+ if (s2m)
+ s2m->next = s1;
+ else
+ *spec = s1;
+
+ if (s1m)
+ s1m->next = s2;
+ else
+ *spec = s2;
+
+ stmp = s1->next;
+ s1->next = s2->next;
+ s2->next = stmp;
+}
+
+/*------------------------------------------------------*/
+
+void linkedlistinsertafter(liblistptr *spec, int o1, int o2)
+{
+ liblistptr s1, s1m, s2; /* , s2m, stmp; (jdk) */
+ int j;
+
+ if ((o1 == o2) || (o1 == (o2 + 1))) return;
+
+ s1m = NULL;
+ s1 = *spec;
+ for (j = 0; j < o1; j++) {
+ s1m = s1;
+ s1 = s1->next;
+ }
+
+ s2 = *spec;
+ for (j = 0; j < o2; j++)
+ s2 = s2->next;
+
+ if (s1m)
+ s1m->next = s1->next;
+ else
+ *spec = s1->next;
+
+ if (o2 == -1) { /* move s1 to front */
+ s1->next = *spec;
+ *spec = s1;
+ }
+ else {
+ s1->next = s2->next;
+ s2->next = s1;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Set the "changed" flag in a library if any object */
+/* in that library has changed. */
+/* */
+/* If "technology" is NULL, check all objects, */
+/* otherwise only check objects with a matching */
+/* technology. */
+/*------------------------------------------------------*/
+
+void tech_set_changes(TechPtr refns)
+{
+ TechPtr ns;
+ int i, j;
+ objectptr thisobj;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ thisobj = *(xobjs.userlibs[i].library + j);
+ if (getchanges(thisobj) > 0) {
+ ns = GetObjectTechnology(thisobj);
+ if ((refns == NULL) || (refns == ns))
+ ns->flags |= TECH_CHANGED;
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Mark a technology as having been modified. */
+/*------------------------------------------------------*/
+
+void tech_mark_changed(TechPtr ns)
+{
+ if (ns != NULL) ns->flags |= TECH_CHANGED;
+}
+
+/*------------------------------------------------------*/
+/* Rearrange objects in the library */
+/*------------------------------------------------------*/
+
+void catmove(int x, int y)
+{
+ int i, j, k, s1, s2, ocentx, ocenty, rangey, l; /* rangex, (jdk) */
+ liblistptr spec;
+ objinstptr exchobj, lobj;
+
+ /* make catmove() a wrapper for pagecatmove() */
+
+ if ((i = is_library(topobject)) < 0) {
+ pagecatmove(x, y);
+ return;
+ }
+
+ if (areawin->selects == 0) return;
+
+ /* Add selected object or objects at the cursor position */
+
+ window_to_user(x, y, &areawin->save);
+
+ s2 = -1;
+ for (j = 0, spec = xobjs.userlibs[i].instlist; spec != NULL;
+ spec = spec->next, j++) {
+ lobj = spec->thisinst;
+ for (k = 0; k < areawin->selects; k++) {
+ exchobj = SELTOOBJINST(areawin->selectlist + k);
+ if (lobj == exchobj) break;
+ }
+ if (k < areawin->selects) continue; /* ignore items being moved */
+
+ ocentx = lobj->position.x + lobj->bbox.lowerleft.x
+ + (lobj->bbox.width >> 1);
+ ocenty = lobj->position.y + lobj->bbox.lowerleft.y
+ + (lobj->bbox.height >> 1);
+ rangey = (lobj->bbox.height > 200) ?
+ (lobj->bbox.height >> 1) : 100;
+
+ if ((areawin->save.y < ocenty + rangey) && (areawin->save.y
+ > ocenty - rangey)) {
+ s2 = j - 1;
+ if (areawin->save.x < ocentx) break;
+ else s2 = j;
+ }
+ }
+ if ((s2 == -1) && (spec == NULL)) {
+ if (areawin->save.y <
+ xobjs.libtop[i + LIBRARY]->thisobject->bbox.lowerleft.y)
+ s2 = j - 1;
+ else if (areawin->save.y <=
+ xobjs.libtop[i + LIBRARY]->thisobject->bbox.lowerleft.y +
+ xobjs.libtop[i + LIBRARY]->thisobject->bbox.height) {
+ unselect_all();
+ Wprintf("Could not find appropriate place to insert object");
+ return;
+ }
+ }
+
+ /* Find object number s2 (because s2 value may change during insertion) */
+ if (s2 > -1) {
+ for (k = 0, spec = xobjs.userlibs[i].instlist; k < s2; spec = spec->next, k++);
+ lobj = spec->thisinst;
+ }
+ else lobj = NULL;
+
+ /* Move items; insert them after item s2 in order selected */
+
+ j = i;
+ for (k = 0; k < areawin->selects; k++) {
+
+ /* Find number of lobj (may have changed) */
+
+ if (lobj == NULL)
+ s2 = -1;
+ else {
+ for (s2 = 0, spec = xobjs.userlibs[i].instlist; spec != NULL;
+ spec = spec->next, s2++)
+ if (spec->thisinst == lobj)
+ break;
+ }
+
+ exchobj = SELTOOBJINST(areawin->selectlist + k);
+ for (s1 = 0, spec = xobjs.userlibs[i].instlist; spec != NULL;
+ spec = spec->next, s1++)
+ if (spec->thisinst == exchobj)
+ break;
+
+ if (spec == NULL) {
+ /* Object came from another library */
+ if ((l = libmoveobject(exchobj->thisobject, i)) >= 0) j = l;
+ }
+ else {
+ linkedlistinsertafter(&(xobjs.userlibs[i].instlist), s1, s2);
+ }
+ }
+
+ unselect_all();
+ composelib(LIBRARY + i);
+ if (j != i) {
+ composelib(LIBRARY + j);
+ centerview(xobjs.libtop[LIBRARY + j]);
+ }
+
+ drawarea(NULL, NULL, NULL);
+}
+
+/*------------------------------------------------------*/
+/* Make a duplicate of an object, put in the User */
+/* Library or the current library (if we're in one). */
+/* */
+/* Updated 2/8/2014 for use with technology namespaces: */
+/* it is most likely that the copied object is to be */
+/* modified but kept in the same namespace. So, when */
+/* renaming the object, prepend "_" to the object name */
+/* instead of the namespace prefix. */
+/*------------------------------------------------------*/
+
+void copycat()
+{
+ short *newselect;
+ objectptr *newobj, *curlib, oldobj;
+ objinstptr libobj;
+ oparamptr ops, newops;
+ int i, libnum;
+ char *cptr;
+
+ libnum = is_library(topobject);
+ if (libnum < 0) libnum = USERLIB - LIBRARY; /* default */
+
+ for (newselect = areawin->selectlist; newselect < areawin->selectlist
+ + areawin->selects; newselect++) {
+
+ libobj = SELTOOBJINST(newselect);
+ oldobj = libobj->thisobject;
+
+ /* generate new entry in user library */
+
+ curlib = (objectptr *) realloc(xobjs.userlibs[libnum].library,
+ (xobjs.userlibs[libnum].number + 1) * sizeof(objectptr));
+ xobjs.userlibs[libnum].library = curlib;
+ newobj = xobjs.userlibs[libnum].library + xobjs.userlibs[libnum].number;
+ *newobj = (objectptr) malloc(sizeof(object));
+ xobjs.userlibs[libnum].number++;
+
+ /* give the new object a unique name */
+
+ cptr = strstr(oldobj->name, "::");
+ if (cptr == NULL)
+ sprintf((*newobj)->name, "_%s", oldobj->name);
+ else {
+ strcpy((*newobj)->name, oldobj->name);
+ sprintf((*newobj)->name + (cptr - oldobj->name) + 2, "_%s", cptr + 2);
+ }
+ checkname(*newobj);
+
+ /* copy other object properties */
+
+ (*newobj)->bbox.width = oldobj->bbox.width;
+ (*newobj)->bbox.height = oldobj->bbox.height;
+ (*newobj)->bbox.lowerleft.x = oldobj->bbox.lowerleft.x;
+ (*newobj)->bbox.lowerleft.y = oldobj->bbox.lowerleft.y;
+ (*newobj)->pcorner.x = oldobj->pcorner.x;
+ (*newobj)->pcorner.y = oldobj->pcorner.y;
+ (*newobj)->viewscale = oldobj->viewscale;
+ /* don't attach the same schematic. . . */
+ (*newobj)->symschem = NULL;
+ /* don't copy highlights */
+ (*newobj)->highlight.netlist = NULL;
+ (*newobj)->highlight.thisinst = NULL;
+
+ /* Copy the parameter structure */
+ (*newobj)->params = NULL;
+ for (ops = oldobj->params; ops != NULL; ops = ops->next) {
+ newops = (oparamptr)malloc(sizeof(oparam));
+ newops->next = (*newobj)->params;
+ newops->key = strdup(ops->key);
+ (*newobj)->params = newops;
+ newops->type = ops->type;
+ newops->which = ops->which;
+ switch (ops->type) {
+ case XC_INT:
+ newops->parameter.ivalue = ops->parameter.ivalue;
+ break;
+ case XC_FLOAT:
+ newops->parameter.fvalue = ops->parameter.fvalue;
+ break;
+ case XC_STRING:
+ newops->parameter.string = stringcopy(ops->parameter.string);
+ break;
+ case XC_EXPR:
+ newops->parameter.expr = strdup(ops->parameter.expr);
+ break;
+ }
+ }
+
+ (*newobj)->schemtype = oldobj->schemtype;
+ (*newobj)->netnames = NULL;
+ (*newobj)->ports = NULL;
+ (*newobj)->calls = NULL;
+ (*newobj)->polygons = NULL;
+ (*newobj)->labels = NULL;
+ (*newobj)->valid = False;
+ (*newobj)->traversed = False;
+ (*newobj)->hidden = False;
+
+ /* copy over all the elements of the original object */
+
+ (*newobj)->parts = 0;
+ (*newobj)->plist = (genericptr *)malloc(sizeof(genericptr));
+
+ for (i = 0; i < oldobj->parts; i++) {
+ switch(ELEMENTTYPE(*(oldobj->plist + i))) {
+ case(PATH): {
+ register pathptr *npath, cpath = TOPATH(oldobj->plist + i);
+
+ NEW_PATH(npath, (*newobj));
+ pathcopy(*npath, cpath);
+ } break;
+
+ case(ARC): {
+ register arcptr *narc, carc = TOARC(oldobj->plist + i);
+
+ NEW_ARC(narc, (*newobj));
+ arccopy(*narc, carc);
+ } break;
+
+ case(POLYGON): {
+ register polyptr *npoly, cpoly = TOPOLY(oldobj->plist + i);
+
+ NEW_POLY(npoly, (*newobj));
+ polycopy(*npoly, cpoly);
+ } break;
+
+ case(SPLINE): {
+ register splineptr *nspl, cspl = TOSPLINE(oldobj->plist + i);
+
+ NEW_SPLINE(nspl, (*newobj));
+ splinecopy(*nspl, cspl);
+ } break;
+
+ case(LABEL): {
+ register labelptr *nlabel, clabel = TOLABEL(oldobj->plist + i);
+
+ NEW_LABEL(nlabel, (*newobj));
+ labelcopy(*nlabel, clabel);
+ } break;
+
+ case(OBJINST): {
+ register objinstptr *ninst, cinst = TOOBJINST(oldobj->plist + i);
+
+ NEW_OBJINST(ninst, (*newobj));
+ instcopy(*ninst, cinst);
+ } break;
+ }
+ }
+ }
+
+ /* make instance for library and measure its bounding box */
+ addtoinstlist(USERLIB - LIBRARY, *newobj, FALSE);
+
+ composelib(USERLIB);
+ unselect_all();
+
+ if (areawin->topinstance == xobjs.libtop[USERLIB])
+ drawarea(NULL, NULL, NULL);
+ else startcatalog(NULL, (pointertype)USERLIB, NULL);
+}
+
+/*--------------------------------------------------------*/
+/* ButtonPress handler during normal catalog viewing mode */
+/*--------------------------------------------------------*/
+
+void catalog_op(int op, int x, int y)
+{
+ short *newselect;
+ objinstptr *newobject, *libobj;
+ objectptr libpage = topobject;
+ short ocentx, ocenty, rangex, rangey, xdiff, ydiff, flag = 0;
+ XPoint oldpos;
+
+ /* Make catalog_op() a wrapper for pagecat_op() */
+
+ if (is_library(topobject) < 0) {
+ pagecat_op(op, x, y);
+ return;
+ }
+
+ /* If XCF_Cancel was invoked, return without a selection. */
+
+ if (op == XCF_Cancel) {
+ eventmode = NORMAL_MODE;
+ catreturn();
+ }
+ else {
+
+ window_to_user(x, y, &areawin->save);
+
+ for (libobj = (objinstptr *)topobject->plist; libobj <
+ (objinstptr *)topobject->plist + topobject->parts; libobj++) {
+ if (IS_OBJINST(*libobj)) {
+
+ ocentx = (*libobj)->position.x + (*libobj)->bbox.lowerleft.x
+ + ((*libobj)->bbox.width >> 1);
+ ocenty = (*libobj)->position.y + (*libobj)->bbox.lowerleft.y
+ + ((*libobj)->bbox.height >> 1);
+
+ rangex = ((*libobj)->bbox.width > 200) ?
+ ((*libobj)->bbox.width >> 1) : 100;
+ rangey = ((*libobj)->bbox.height > 200) ?
+ ((*libobj)->bbox.height >> 1) : 100;
+
+ if (areawin->save.x > ocentx - rangex && areawin->save.x <
+ ocentx + rangex && areawin->save.y < ocenty + rangey
+ && areawin->save.y > ocenty - rangey) {
+
+ /* setup to move object around and draw the selected object */
+
+ if (eventmode == ASSOC_MODE) {
+
+ /* revert to old page */
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = (areawin->stack == NULL) ?
+ xobjs.pagelist[areawin->page]->pageinst
+ : areawin->stack->thisinst;
+ /* associate the new object */
+ schemassoc(topobject, (*libobj)->thisobject);
+ setpage(TRUE);
+ catreturn();
+ eventmode = NORMAL_MODE;
+ }
+ else if ((op == XCF_Library_Pop) || (op == XCF_Library_Copy)) {
+ int saveselects;
+
+ /* revert to old page */
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = (areawin->stack == NULL) ?
+ xobjs.pagelist[areawin->page]->pageinst
+ : areawin->stack->thisinst;
+
+ /* retrieve drawing window state and set position of object to
+ be correct in reference to that window */
+
+ snap(x, y, &oldpos);
+
+ saveselects = areawin->selects;
+ areawin->selects = 0;
+ setpage(FALSE);
+ areawin->selects = saveselects;
+
+ snap(x, y, &areawin->save);
+ xdiff = areawin->save.x - oldpos.x;
+ ydiff = areawin->save.y - oldpos.y;
+
+ /* collect all of the selected items */
+
+ for (newselect = areawin->selectlist; newselect <
+ areawin->selectlist + areawin->selects; newselect++) {
+ NEW_OBJINST(newobject, topobject);
+ instcopy(*newobject, TOOBJINST(libpage->plist + *newselect));
+ /* color should be recast as current color */
+ (*newobject)->color = areawin->color;
+ /* position modified by (xdiff, ydiff) */
+ (*newobject)->position.x += xdiff;
+ (*newobject)->position.y += ydiff;
+
+ u2u_snap(&((*newobject)->position));
+ *newselect = (short)(newobject - (objinstptr *)topobject->plist);
+ if ((*newobject)->thisobject == (*libobj)->thisobject)
+ flag = 1;
+ }
+
+ /* add final object to the list of object instances */
+
+ if (!flag) {
+ NEW_OBJINST(newobject, topobject);
+ instcopy(*newobject, *libobj);
+ (*newobject)->color = areawin->color;
+ (*newobject)->position.x = areawin->save.x;
+ (*newobject)->position.y = areawin->save.y;
+
+ /* add this object to the list of selected items */
+
+ newselect = allocselect();
+ *newselect = (short)(newobject - (objinstptr *)topobject->plist);
+
+ }
+ if (op == XCF_Library_Copy) {
+
+ /* Key "c" pressed for "copy" (default binding) */
+
+ XDefineCursor(dpy, areawin->window, COPYCURSOR);
+ eventmode = COPY_MODE;
+#ifndef TCL_WRAPPER
+ xcAddEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, False,
+ (xcEventHandler)xlib_drag, NULL);
+#endif
+ }
+ else {
+ eventmode = MOVE_MODE;
+ was_preselected = FALSE;
+ register_for_undo(XCF_Library_Pop, UNDO_MORE, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+ }
+#ifdef TCL_WRAPPER
+ /* fprintf(stderr, "Creating event handler for xctk_drag: "); */
+ /* printeventmode(); */
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask |
+ ButtonMotionMask, (Tk_EventProc *)xctk_drag, NULL);
+#endif
+ catreturn();
+ }
+
+ /* Select the closest element and stay in the catalog. */
+ /* Could just do "select_element" here, but would not cover */
+ /* the entire area in the directory surrounding the object. */
+
+ else if (op == XCF_Select) {
+ short newinst = (short)(libobj - (objinstptr *)topobject->plist);
+ /* (ignore this object if it is already in the list of selects) */
+ for (newselect = areawin->selectlist; newselect <
+ areawin->selectlist + areawin->selects; newselect++)
+ if (*newselect == newinst) break;
+ if (newselect == areawin->selectlist + areawin->selects) {
+ newselect = allocselect();
+ *newselect = newinst;
+ XcSetFunction(GXcopy);
+ XcTopSetForeground(SELECTCOLOR);
+ UDrawObject(*libobj, SINGLE, SELECTCOLOR,
+ xobjs.pagelist[areawin->page]->wirewidth, NULL);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------*/
+/* Switch to the next catalog */
+/*------------------------------*/
+
+void changecat()
+{
+ int i, j;
+
+ if ((i = is_library(topobject)) < 0) {
+ if (areawin->lastlibrary >= xobjs.numlibs) areawin->lastlibrary = 0;
+ j = areawin->lastlibrary;
+ eventmode = CATALOG_MODE;
+ }
+ else {
+ j = (i + 1) % xobjs.numlibs;
+ if (j == i) {
+ Wprintf("This is the only library.");
+ return;
+ }
+ areawin->lastlibrary = j;
+ }
+
+ if (eventmode == CATMOVE_MODE)
+ delete_for_xfer(NORMAL, areawin->selectlist, areawin->selects);
+
+ startcatalog(NULL, (pointertype)(j + LIBRARY), NULL);
+}
+
+/*--------------------------------------*/
+/* Begin catalog viewing mode */
+/*--------------------------------------*/
+
+void startcatalog(xcWidget w, pointertype libmod, caddr_t nulldata)
+{
+ if (xobjs.libtop == NULL) return; /* No libraries defined */
+
+ if ((xobjs.libtop[libmod]->thisobject == NULL) ||
+ (areawin->topinstance == xobjs.libtop[libmod])) return;
+
+ if (libmod == FONTLIB) {
+ XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
+ if (eventmode == TEXT_MODE)
+ eventmode = FONTCAT_MODE;
+ else
+ eventmode = EFONTCAT_MODE;
+ }
+ else if (eventmode == ASSOC_MODE) {
+ XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
+ }
+ else if (libmod == PAGELIB || libmod == LIBLIB) {
+ XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
+ eventmode = CATALOG_MODE;
+ }
+ else if (eventmode != CATMOVE_MODE) {
+ /* Don't know why I put this here---causes xcircuit to redraw */
+ /* the schematic view when switching between library pages. */
+ // finish_op(XCF_Cancel, 0, 0);
+ eventmode = CATALOG_MODE;
+ }
+
+ /* Push the current page onto the push stack, unless we're going */
+ /* to a library from the library directory or vice versa, or */
+ /* library to library. */
+
+ if (!(((is_library(topobject) >= 0)
+ || (areawin->topinstance == xobjs.libtop[LIBLIB])
+ || (areawin->topinstance == xobjs.libtop[PAGELIB]))
+ && libmod >= PAGELIB)) {
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+ }
+
+ /* set library as new object */
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = xobjs.libtop[libmod];
+
+ if (libmod == FONTLIB)
+ setpage(FALSE);
+ else {
+ setpage(TRUE);
+ transferselects();
+ }
+
+ /* draw the new screen */
+
+ refresh(NULL, NULL, NULL);
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/log_text.html b/log_text.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/log_text.html
diff --git a/menucalls.c b/menucalls.c
new file mode 100644
index 0000000..389049a
--- /dev/null
+++ b/menucalls.c
@@ -0,0 +1,1696 @@
+/*----------------------------------------------------------------------*/
+/* menucalls.c --- callback routines from the menu buttons, and */
+/* associated routines (either Tcl/Tk routines or */
+/* non-specific; Xt routines split off in file */
+/* xtfuncs.c 3/28/06) */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* External Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern char _STR2[250];
+extern char _STR[150]; /* Generic multipurpose string */
+extern xcWidget top;
+extern Display *dpy;
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern ApplicationData appdata;
+extern Cursor appcursors[NUM_CURSORS];
+extern fontinfo *fonts;
+extern short fontcount;
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local Variable definitions */
+/*----------------------------------------------------------------------*/
+
+u_short *fontnumbers;
+u_char nfontnumbers;
+
+/*----------------------------------------------*/
+/* Set Poly and Arc line styles and fill styles */
+/*----------------------------------------------*/
+
+#define BORDERS (NOBORDER | DOTTED | DASHED)
+#define ALLFILLS (FILLSOLID | FILLED)
+
+/*----------------------------------------------------------------*/
+/* setgrid, getgridspace are for grid and snap spacing sizes; */
+/* include routines to parse fractions */
+/*----------------------------------------------------------------*/
+
+void setgrid(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ float oscale, iscale = (float)xobjs.pagelist[areawin->page]->drawingscale.y /
+ (float)xobjs.pagelist[areawin->page]->drawingscale.x;
+ float fval;
+
+ /* For now, assume that the value is in the current display style. */
+ /* Might be nice in the future to make it accept any input. . . */
+
+ switch (xobjs.pagelist[areawin->page]->coordstyle) {
+ case INTERNAL:
+ if (sscanf(_STR2, "%f", &fval) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else *dataptr = fval / iscale;
+ break;
+ case CM:
+ oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
+ if (sscanf(_STR2, "%f", &fval) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else *dataptr = fval * IN_CM_CONVERT / (iscale * oscale);
+ break;
+ case DEC_INCH: case FRAC_INCH: {
+ short parts;
+ char *sptr;
+ int f2, f3;
+
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ for (sptr = _STR2; *sptr != '\0'; sptr++)
+ if (*sptr == '/') *sptr = ' ';
+ parts = sscanf(_STR2, "%f %d %d", &fval, &f2, &f3);
+ if ((parts == 0) || (parts != 1 && (fval != (float)((int)fval)))) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ break;
+ }
+ if (parts == 2) fval /= (float)f2;
+ else if (parts == 3) fval += ((float)f2 / (float)f3);
+ *dataptr = fval * 72.0 / (iscale * oscale);
+ } break;
+ }
+ if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Write a measurement value into string "buffer" dependant on */
+/* the current default units of measure (centimeters or inches). */
+/*----------------------------------------------------------------*/
+
+void measurestr(float value, char *buffer)
+{
+ float oscale, iscale;
+ iscale = (float)(xobjs.pagelist[areawin->page]->drawingscale.y) /
+ (float)(xobjs.pagelist[areawin->page]->drawingscale.x);
+
+ switch (xobjs.pagelist[areawin->page]->coordstyle) {
+ case INTERNAL:
+ sprintf(buffer, "%5.3f", value * iscale);
+ break;
+ case CM:
+ oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
+ sprintf(buffer, "%5.3f cm", value * iscale * oscale / IN_CM_CONVERT);
+ break;
+ case DEC_INCH:
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ sprintf(buffer, "%5.3f in", value * iscale * oscale / 72.0);
+ break;
+ case FRAC_INCH:
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ fraccalc(((value * iscale * oscale) / 72.0), buffer);
+ strcat(buffer, " in");
+ break;
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* set the global default line width. The unit used internally */
+/* is twice the value passed through pointer "dataptr". */
+/*----------------------------------------------------------------*/
+
+void setwidth(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ if (sscanf(_STR2, "%f", dataptr) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ return;
+ }
+ (*dataptr) *= 2.0;
+ if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Set text scale. */
+/*--------------------------------------------------------------*/
+
+void changetextscale(float newscale)
+{
+ short *osel;
+ labelptr settext;
+ stringpart *strptr, *nextptr;
+
+ /* In edit mode, add font scale change. */
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string, True,
+ areawin->topinstance)) {
+ undrawtext(settext);
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_SCALE)
+ strptr->data.scale = newscale;
+ else if (nextptr && nextptr->type == FONT_SCALE)
+ nextptr->data.scale = newscale;
+ else
+ labeltext(FONT_SCALE, (char *)&newscale);
+ redrawtext(settext);
+ }
+ else if (stringlength(settext->string, True, areawin->topinstance) > 0)
+ labeltext(FONT_SCALE, (char *)&newscale);
+ else (settext->scale = newscale);
+ }
+
+ /* Change scale on all selected text objects */
+
+ else if (areawin->selects > 0) {
+ float oldscale;
+ Boolean waschanged = FALSE;
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == LABEL) {
+ settext = SELTOLABEL(osel);
+ oldscale = settext->scale;
+ if (oldscale != newscale) {
+ undrawtext(settext);
+ settext->scale = newscale;
+ redrawtext(settext);
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ (genericptr)settext, (double)oldscale);
+ waschanged = TRUE;
+ }
+ }
+ }
+ if (waschanged) undo_finish_series();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Auto-scale the drawing to fit the declared page size. */
+/* */
+/* If the page is declared encapsulated, then do nothing. */
+/* If a frame box is on the page, then scale to fit the frame */
+/* to the declared page size, not the whole object. */
+/*--------------------------------------------------------------*/
+
+void autoscale(int page)
+{
+ float newxscale, newyscale;
+ float scalefudge = (xobjs.pagelist[page]->coordstyle
+ == CM) ? CMSCALE : INCHSCALE;
+ int width, height;
+ polyptr framebox;
+
+ /* Check if auto-fit flag is selected */
+ if (!(xobjs.pagelist[page]->pmode & 2)) return;
+ /* Ignore auto-fit flag in EPS mode */
+ if (!(xobjs.pagelist[page]->pmode & 1)) return;
+
+ else if (topobject->bbox.width == 0 || topobject->bbox.height == 0) {
+ // Wprintf("Cannot auto-fit empty page");
+ return;
+ }
+
+ newxscale = (xobjs.pagelist[page]->pagesize.x -
+ (2 * xobjs.pagelist[page]->margins.x)) / scalefudge;
+ newyscale = (xobjs.pagelist[page]->pagesize.y -
+ (2 * xobjs.pagelist[page]->margins.y)) / scalefudge;
+
+ if ((framebox = checkforbbox(topobject)) != NULL) {
+ int i, minx, miny, maxx, maxy;
+
+ minx = maxx = framebox->points[0].x;
+ miny = maxy = framebox->points[0].y;
+ for (i = 1; i < framebox->number; i++) {
+ if (framebox->points[i].x < minx) minx = framebox->points[i].x;
+ else if (framebox->points[i].x > maxx) maxx = framebox->points[i].x;
+ if (framebox->points[i].y < miny) miny = framebox->points[i].y;
+ else if (framebox->points[i].y > maxy) maxy = framebox->points[i].y;
+ }
+ width = (maxx - minx);
+ height = (maxy - miny);
+ }
+ else {
+
+ width = toplevelwidth(areawin->topinstance, NULL);
+ height = toplevelheight(areawin->topinstance, NULL);
+ }
+
+ if (xobjs.pagelist[page]->orient == 0) { /* Portrait */
+ newxscale /= width;
+ newyscale /= height;
+ }
+ else {
+ newxscale /= height;
+ newyscale /= width;
+ }
+ xobjs.pagelist[page]->outscale = min(newxscale, newyscale);
+}
+
+/*--------------------------------------------------------------*/
+/* Parse a string for possible units of measure. Convert to */
+/* current units of measure, if necessary. Return the value */
+/* in current units, as a type float. */
+/*--------------------------------------------------------------*/
+
+float parseunits(char *strptr)
+{
+ short curtype;
+ Boolean inchunits = True;
+ float pv;
+ char units[12];
+
+ curtype = xobjs.pagelist[areawin->page]->coordstyle;
+
+ if (sscanf(strptr, "%f %11s", &pv, units) < 2)
+ return pv;
+ else {
+ if (!strncmp(units, "cm", 2) || !strncmp(units, "centimeters", 11))
+ inchunits = False;
+ switch(curtype) {
+ case CM:
+ return ((inchunits) ? (pv * 2.54) : pv);
+ default:
+ return ((inchunits) ? pv : (pv / 2.54));
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Set the output page size, in the current unit of measure */
+/* Return value: TRUE if _STR2 values were in inches, FALSE */
+/* if in centimeters. */
+/* XXX This API gives no good way to signal errors. */
+/*--------------------------------------------------------------*/
+
+Boolean setoutputpagesize(XPoint *dataptr)
+{
+ float px, py;
+ char units[10], *expos;
+#ifndef TCL_WRAPPER
+ Arg wargs[1];
+#endif
+
+ strcpy(units, "in");
+
+ if (sscanf(_STR2, "%f %*c %f %9s", &px, &py, units) < 4) {
+ if (sscanf(_STR2, "%f %*c %f", &px, &py) < 3) {
+ if ((expos = strchr(_STR2, 'x')) == NULL) {
+ Wprintf("Illegal Form for page size.");
+ return FALSE;
+ }
+ else {
+ *expos = '\0';
+ if (sscanf(_STR2, "%f", &px) == 0 ||
+ sscanf(expos + 1, "%f %9s", &py, units) == 0) {
+ Wprintf("Illegal Form for page size.");
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ /* Don't reduce page to less than the margins (1") or negative */
+ /* scales result. */
+
+ if ((px <= 2.0) || (py <= 2.0)) {
+ Wprintf("Page size too small for margins.");
+ return FALSE;
+ }
+
+ dataptr->x = (short)(px * 72.0);
+ dataptr->y = (short)(py * 72.0);
+
+ if (!strcmp(units, "cm")) {
+ dataptr->x /= 2.54;
+ dataptr->y /= 2.54;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the text size (global or selected, depending on mode */
+/*--------------------------------------------------------------*/
+
+labelptr gettextsize(float **floatptr)
+{
+ labelptr settext = NULL;
+ short *osel;
+ stringpart *strptr, *nextptr;
+ const float f_one = 1.00;
+
+ if (floatptr) *floatptr = &areawin->textscale;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ settext = *((labelptr *)EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_SCALE) {
+ if (floatptr) *floatptr = &strptr->data.scale;
+ }
+ else if (nextptr && nextptr->type == FONT_SCALE) {
+ if (floatptr) *floatptr = &nextptr->data.scale;
+ }
+ else if (floatptr) *floatptr = (float *)(&f_one);
+ }
+ else {
+ settext = *((labelptr *)EDITPART);
+ if (floatptr) *floatptr = &(settext->scale);
+ }
+ }
+ else if (areawin->selects > 0) {
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == LABEL) {
+ settext = SELTOLABEL(osel);
+ if (floatptr) *floatptr = &(settext->scale);
+ break;
+ }
+ }
+ }
+ return settext;
+}
+
+/*--------------------------------------------------------------*/
+/* Set a character kern value */
+/*--------------------------------------------------------------*/
+
+void setkern(xcWidget w, stringpart *kpart)
+{
+ char *sptr;
+ short kd[2];
+
+ kd[0] = kd[1] = 0;
+
+ if ((sptr = strchr(_STR2, ',')) == NULL)
+ Wprintf("Use notation X,Y");
+ else {
+ *sptr = '\0';
+ sscanf(_STR2, "%hd", &kd[0]);
+ sscanf(sptr + 1, "%hd", &kd[1]);
+ if (kpart == NULL)
+ labeltext(KERN, (char *)kd);
+ else {
+ labelptr curlabel = TOLABEL(EDITPART);
+ undrawtext(curlabel);
+ kpart->data.kern[0] = kd[0];
+ kpart->data.kern[1] = kd[1];
+ redrawtext(curlabel);
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the drawing scale (specified as ratio X:Y) */
+/*----------------------------------------------------------------*/
+
+void setdscale(xcWidget w, XPoint *dataptr)
+{
+ char *sptr;
+
+ if ((sptr = strchr(_STR2, ':')) == NULL)
+ Wprintf("Use ratio X:Y");
+ else {
+ *sptr = '\0';
+ sscanf(_STR2, "%hd", &(dataptr->x));
+ sscanf(sptr + 1, "%hd", &(dataptr->y));
+ Wprintf("New scale is %hd:%hd", dataptr->x, dataptr->y);
+ W1printf(" ");
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the scale of an object or group of selected objects */
+/*----------------------------------------------------------------*/
+
+void setosize(xcWidget w, objinstptr dataptr)
+{
+ float tmpres, oldsize;
+ Boolean waschanged = FALSE;
+ short *osel;
+ objinstptr nsobj;
+ int res = sscanf(_STR2, "%f", &tmpres);
+
+ // Negative values are flips---deal with them independently
+
+ if (tmpres < 0)
+ tmpres = -tmpres;
+
+ if (res == 0 || tmpres == 0) {
+ Wprintf("Illegal value");
+ return;
+ }
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == OBJINST) {
+ nsobj = SELTOOBJINST(osel);
+ oldsize = nsobj->scale;
+ nsobj->scale = (oldsize < 0) ? -tmpres : tmpres;
+
+ if (oldsize != tmpres) {
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(osel), (double)oldsize);
+ waschanged = TRUE;
+ }
+ }
+ }
+ /* unselect_all(); */
+ if (waschanged) undo_finish_series();
+ pwriteback(areawin->topinstance);
+ drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the linewidth of all selected arcs, polygons, splines, and */
+/* paths. */
+/*----------------------------------------------------------------*/
+
+void setwwidth(xcWidget w, void *dataptr)
+{
+ float tmpres, oldwidth;
+ short *osel;
+ arcptr nsarc;
+ polyptr nspoly;
+ splineptr nsspline;
+ pathptr nspath;
+
+ if (sscanf(_STR2, "%f", &tmpres) == 0) {
+ Wprintf("Illegal value");
+ return;
+ }
+ else if (areawin->selects == 0) {
+ areawin->linewidth = tmpres;
+ }
+ else {
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == ARC) {
+ nsarc = SELTOARC(osel);
+ oldwidth = nsarc->width;
+ nsarc->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == POLYGON) {
+ nspoly = SELTOPOLY(osel);
+ oldwidth = nspoly->width;
+ nspoly->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == SPLINE) {
+ nsspline = SELTOSPLINE(osel);
+ oldwidth = nsspline->width;
+ nsspline->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == PATH) {
+ nspath = SELTOPATH(osel);
+ oldwidth = nspath->width;
+ nspath->width = tmpres;
+ }
+
+ if (oldwidth != tmpres)
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(osel), (double)oldwidth);
+ }
+ unselect_all();
+ pwriteback(areawin->topinstance);
+ drawarea(NULL, NULL, NULL);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Add a new font name to the list of known fonts */
+/* Register the font number for the Alt-F cycling mechanism */
+/* Tcl: depends on command tag mechanism for GUI menu update. */
+/*--------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void makenewfontbutton()
+{
+ nfontnumbers++;
+ if (nfontnumbers == 1)
+ fontnumbers = (u_short *)malloc(sizeof(u_short));
+ else
+ fontnumbers = (u_short *)realloc(fontnumbers, nfontnumbers
+ * sizeof(u_short));
+ fontnumbers[nfontnumbers - 1] = fontcount - 1;
+}
+
+#endif /* TCL_WRAPPER */
+
+/*---------------------------------------------------------------*/
+/* Some Xcircuit routines using toggle and toggleexcl, */
+/* put here because they reference the menu structures directly. */
+/*---------------------------------------------------------------*/
+
+void setcolorscheme(Boolean boolvalue)
+{
+ if (boolvalue) {
+ PARAMCOLOR = appdata.parampix;
+ AUXCOLOR = appdata.auxpix;
+ OFFBUTTONCOLOR = appdata.buttonpix;
+ SELECTCOLOR = appdata.selectpix;
+ GRIDCOLOR = appdata.gridpix;
+ SNAPCOLOR = appdata.snappix;
+ AXESCOLOR = appdata.axespix;
+ BACKGROUND = appdata.bg;
+ FOREGROUND = appdata.fg;
+ }
+ else {
+ PARAMCOLOR = appdata.parampix2;
+ AUXCOLOR = appdata.auxpix2;
+ OFFBUTTONCOLOR = appdata.buttonpix2;
+ SELECTCOLOR = appdata.selectpix2;
+ GRIDCOLOR = appdata.gridpix2;
+ SNAPCOLOR = appdata.snappix2;
+ AXESCOLOR = appdata.axespix2;
+ BACKGROUND = appdata.bg2;
+ FOREGROUND = appdata.fg2;
+ }
+
+ BARCOLOR = appdata.barpix;
+ FILTERCOLOR = appdata.filterpix;
+
+ LOCALPINCOLOR = appdata.localcolor;
+ GLOBALPINCOLOR = appdata.globalcolor;
+ INFOLABELCOLOR = appdata.infocolor;
+ RATSNESTCOLOR = appdata.ratsnestcolor;
+ BBOXCOLOR = appdata.bboxpix;
+ CLIPMASKCOLOR = appdata.clipcolor;
+
+#if !defined(TCL_WRAPPER) && !defined(DOUBLEBUFFER)
+ {
+ Arg wargs[1];
+ XtSetArg(wargs[0], XtNbackground, BACKGROUND);
+ XtSetValues(areawin->area, wargs, 1);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Change menu selection for reported measurement units */
+/*----------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void togglegrid(u_short type)
+{
+ static char *stylenames[] = {
+ "decimal inches",
+ "fractional inches",
+ "centimeters",
+ "internal units", NULL
+ };
+
+ XcInternalTagCall(xcinterp, 3, "config", "coordstyle", stylenames[type]);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*----------------------------------------------------------------*/
+/* Called by setgridtype() to complete setting the reported */
+/* measurement units */
+/*----------------------------------------------------------------*/
+
+void getgridtype(xcWidget button, pointertype value, caddr_t calldata)
+{
+ short oldtype = xobjs.pagelist[areawin->page]->coordstyle;
+ float scalefac = getpsscale(1.0, areawin->page) / INCHSCALE;
+
+#ifndef TCL_WRAPPER
+ togglegridstyles(button);
+#endif
+ xobjs.pagelist[areawin->page]->coordstyle = (short)value;
+
+ switch(value) {
+ case FRAC_INCH: case DEC_INCH: case INTERNAL:
+ if (oldtype == CM) {
+ xobjs.pagelist[areawin->page]->outscale *= scalefac;
+#ifndef TCL_WRAPPER
+ /* Note: Tcl defines a method for selecting standard */
+ /* page sizes. We really DON'T want to reset the size */
+ /* just because we switched measurement formats! */
+
+ xobjs.pagelist[areawin->page]->pagesize.x = 612;
+ xobjs.pagelist[areawin->page]->pagesize.y = 792; /* letter */
+#endif
+ }
+ break;
+ case CM:
+ if (oldtype != CM) {
+ xobjs.pagelist[areawin->page]->outscale *= scalefac;
+#ifndef TCL_WRAPPER
+ xobjs.pagelist[areawin->page]->pagesize.x = 595;
+ xobjs.pagelist[areawin->page]->pagesize.y = 842; /* A4 */
+#endif
+ }
+ break;
+ }
+ if (oldtype != xobjs.pagelist[areawin->page]->coordstyle) {
+ drawarea(NULL, NULL, NULL);
+ W1printf(" ");
+ }
+}
+
+/*------------------------------------------------------*/
+/* Make new library, add new button to the "Libraries" */
+/* cascaded menu, compose the library page, update the */
+/* library directory, and go to that library page. */
+/*------------------------------------------------------*/
+
+void newlibrary(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ int libnum = createlibrary(FALSE);
+ startcatalog(w, libnum, NULL);
+}
+
+/*----------------------------------------------*/
+/* Find an empty library, and return its page */
+/* number if it exists. Otherwise, return -1. */
+/* This search does not include the so-called */
+/* "User Library" (last library in list). */
+/*----------------------------------------------*/
+
+int findemptylib()
+{
+ int i;
+
+ for (i = 0; i < xobjs.numlibs - 1; i++) {
+ if (xobjs.userlibs[i].number == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*----------------------------------------------*/
+/* Make new page; goto that page */
+/* (wrapper for routine events.c:newpage()) */
+/*----------------------------------------------*/
+
+void newpagemenu(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ newpage((short)value);
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------*/
+/* Make new library and add a new button to the */
+/* "Libraries" cascaded menu. */
+/*----------------------------------------------*/
+
+int createlibrary(Boolean force)
+{
+ /* xcWidget libmenu, newbutton, oldbutton; (jdk) */
+#ifndef TCL_WRAPPER
+ Arg wargs[2];
+#endif
+ /* char libstring[20]; (jdk) */
+ int libnum;
+ objectptr newlibobj;
+
+ /* If there's an empty library, return its number */
+ if ((!force) && (libnum = findemptylib()) >= 0) return (libnum + LIBRARY);
+ libnum = (xobjs.numlibs++) + LIBRARY;
+ xobjs.libtop = (objinstptr *)realloc(xobjs.libtop,
+ (libnum + 1) * sizeof(objinstptr));
+ xobjs.libtop[libnum] = xobjs.libtop[libnum - 1];
+ libnum--;
+
+ newlibobj = (objectptr) malloc(sizeof(object));
+ initmem(newlibobj);
+ xobjs.libtop[libnum] = newpageinst(newlibobj);
+
+ sprintf(newlibobj->name, "Library %d", libnum - LIBRARY + 1);
+
+ /* Create the library */
+
+ xobjs.userlibs = (Library *) realloc(xobjs.userlibs, xobjs.numlibs
+ * sizeof(Library));
+ xobjs.userlibs[libnum + 1 - LIBRARY] = xobjs.userlibs[libnum - LIBRARY];
+ xobjs.userlibs[libnum - LIBRARY].library = (objectptr *) malloc(sizeof(objectptr));
+ xobjs.userlibs[libnum - LIBRARY].number = 0;
+ xobjs.userlibs[libnum - LIBRARY].instlist = NULL;
+
+ sprintf(_STR2, "xcircuit::newlibrarybutton \"%s\"", newlibobj->name);
+ Tcl_Eval(xcinterp, _STR2);
+
+ /* Update the library directory to include the new page */
+
+ composelib(LIBLIB);
+
+ return libnum;
+}
+
+/*--------------------------------------------------------------*/
+/* Routine called by newpage() if new button needs to be made */
+/* to add to the "Pages" cascaded menu. */
+/*--------------------------------------------------------------*/
+
+void makepagebutton()
+{
+ /* xcWidget pagemenu, newbutton; (jdk) */
+ /* char pagestring[10]; (jdk) */
+
+ /* make new entry in the menu */
+
+ sprintf(_STR2, "newpagebutton \"Page %d\"", xobjs.pages);
+ Tcl_Eval(xcinterp, _STR2);
+
+ /* Update the page directory */
+
+ composelib(PAGELIB);
+}
+
+/*----------------------------------------------------------------*/
+/* Find the Page menu button associated with the page number */
+/* (passed parameter) and set the label of that button to the */
+/* object name (= page label) */
+/*----------------------------------------------------------------*/
+
+void renamepage(short pagenumber)
+{
+ objinstptr thisinst = xobjs.pagelist[pagenumber]->pageinst;
+ char *pname, *plabel;
+
+ if ((pagenumber >= 0) && (pagenumber < xobjs.pages - 1) &&
+ (thisinst != NULL)) {
+ plabel = thisinst->thisobject->name;
+ pname = (char *)malloc(28 + strlen(plabel));
+ sprintf(pname, "xcircuit::renamepage %d {%s}", pagenumber + 1, plabel);
+ Tcl_Eval(xcinterp, pname);
+ free(pname);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Same routine as above, for Library page menu buttons */
+/*--------------------------------------------------------------*/
+
+void renamelib(short libnumber)
+{
+ if (libnumber <= xobjs.numlibs) return;
+
+ sprintf(_STR2, "xcircuit::renamelib %d \"%s\"", libnumber - LIBRARY + 1,
+ xobjs.libtop[libnumber]->thisobject->name);
+ Tcl_Eval(xcinterp, _STR2);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the color menu */
+/*--------------------------------------------------------------*/
+
+void setcolormark(int colorval)
+{
+ /* Set GUI variables and execute any command tags associated */
+ /* with the "color" command */
+
+ char cstr[6];
+ int i;
+
+ if (colorval != DEFAULTCOLOR) {
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == colorval) {
+ sprintf(cstr, "%5d", i);
+ break;
+ }
+ }
+
+#ifdef TCL_WRAPPER
+ XcInternalTagCall(xcinterp, 3, "color", "set", (colorval == DEFAULTCOLOR) ?
+ "inherit" : cstr);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Set the checkmarks on the element styles menu */
+/*----------------------------------------------------------------*/
+
+void setallstylemarks(u_short styleval)
+{
+ /* Execute any command tags associated */
+ /* with the "fill" and "border" commands. */
+
+ char fstr[10];
+ int fillfactor;
+ const char *bptr;
+
+ const char *borders[] = {"solid", "unbordered", "dashed", "dotted", NULL};
+ enum BorderIdx { SolidIdx, UnborderedIdx, DashedIdx, DottedIdx };
+
+ if (styleval & FILLED) {
+ fillfactor = (int)(12.5 * (float)(1 + ((styleval & FILLSOLID) >> 5)));
+ if (fillfactor < 100)
+ sprintf(fstr, "%d", fillfactor);
+ else
+ strcpy(fstr, "solid");
+ }
+ else
+ strcpy(fstr, "unfilled");
+
+ switch (styleval & BORDERS) {
+ case DASHED:
+ bptr = borders[DashedIdx];
+ break;
+ case DOTTED:
+ bptr = borders[DottedIdx];
+ break;
+ case NOBORDER:
+ bptr = borders[UnborderedIdx];
+ break;
+ default:
+ bptr = borders[SolidIdx];
+ break;
+ }
+
+ XcInternalTagCall(xcinterp, 3, "fill", fstr,
+ (styleval & OPAQUE) ? "opaque" : "transparent");
+ XcInternalTagCall(xcinterp, 3, "border", "bbox", (styleval & BBOX) ? "true" :
+ "false");
+ XcInternalTagCall(xcinterp, 3, "border", "clipmask", (styleval & CLIPMASK) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 2, "border", (styleval & UNCLOSED) ? "unclosed" :
+ "closed");
+ XcInternalTagCall(xcinterp, 2, "border", bptr);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Check for a bounding box polygon */
+/*--------------------------------------------------------------*/
+
+polyptr checkforbbox(objectptr localdata)
+{
+ polyptr *cbbox;
+
+ for (cbbox = (polyptr *)localdata->plist; cbbox <
+ (polyptr *)localdata->plist + localdata->parts; cbbox++)
+ if (IS_POLYGON(*cbbox))
+ if ((*cbbox)->style & BBOX) return *cbbox;
+
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Set a value for element style. "Mask" determines the bits */
+/* to be affected, so that "value" may turn bits either on or */
+/* off. */
+/*--------------------------------------------------------------*/
+
+int setelementstyle(xcWidget w, u_short value, u_short mask)
+{
+ Boolean preselected, selected = False;
+ short *sstyle;
+ u_short newstyle, oldstyle;
+
+ if (areawin->selects == 0) {
+ preselected = FALSE;
+ if (value & BBOX)
+ checkselect(POLYGON);
+ else
+ checkselect(ARC | SPLINE | POLYGON | PATH);
+ }
+ else preselected = TRUE;
+
+ if (areawin->selects > 0) {
+ if (value & BBOX) {
+ polyptr ckp;
+ if (areawin->selects != 1) {
+ Wprintf("Choose only one polygon to be the bounding box");
+ return -1;
+ }
+ else if (SELECTTYPE(areawin->selectlist) != POLYGON) {
+ Wprintf("Bounding box can only be a polygon");
+ return -1;
+ }
+ else if (((ckp = checkforbbox(topobject)) != NULL) &&
+ (ckp != SELTOPOLY(areawin->selectlist))) {
+ Wprintf("Only one bounding box allowed per page");
+ return -1;
+ }
+ }
+
+ for (sstyle = areawin->selectlist; sstyle < areawin->selectlist
+ + areawin->selects; sstyle++) {
+ short stype = SELECTTYPE(sstyle);
+ if (stype & (ARC | POLYGON | SPLINE | PATH)) {
+ short *estyle;
+ switch (stype) {
+ case ARC:
+ estyle = &((SELTOARC(sstyle))->style);
+ break;
+ case SPLINE:
+ estyle = &((SELTOSPLINE(sstyle))->style);
+ break;
+ case POLYGON:
+ estyle = &((SELTOPOLY(sstyle))->style);
+ break;
+ case PATH:
+ estyle = &((SELTOPATH(sstyle))->style);
+ break;
+ }
+ oldstyle = newstyle = *estyle;
+ newstyle &= ~(mask);
+ newstyle |= value;
+
+ if (oldstyle != newstyle) {
+ if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
+ Wprintf("Must have either a border or filler");
+ continue;
+ }
+
+ XSetFunction(dpy, areawin->gc, GXcopy);
+ XSetForeground(dpy, areawin->gc, BACKGROUND);
+ easydraw(*sstyle, DOFORALL);
+
+ *estyle = newstyle;
+ if (mask & BBOX)
+ (SELTOPOLY(sstyle))->color = (value & BBOX) ? BBOXCOLOR
+ : DEFAULTCOLOR;
+
+ XSetFunction(dpy, areawin->gc, GXxor);
+ XSetForeground(dpy, areawin->gc, SELECTCOLOR ^ BACKGROUND);
+ easydraw(*sstyle, DOFORALL);
+
+#ifdef TCL_WRAPPER
+ register_for_undo(XCF_ChangeStyle,
+ (sstyle == areawin->selectlist + areawin->selects - 1) ?
+ UNDO_DONE : UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(sstyle), (int)oldstyle);
+#else
+ /* Tcl version differs in that the element is not deselected after */
+
+ register_for_undo(XCF_ChangeStyle, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(sstyle), (int)oldstyle);
+#endif
+ }
+ selected = True;
+ }
+ }
+ }
+ if (selected)
+ pwriteback(areawin->topinstance);
+ else {
+ newstyle = areawin->style;
+ if (value & BBOX) {
+ Wprintf("Cannot set default style to Bounding Box");
+ newstyle &= ~(BBOX);
+ return -1;
+ }
+ else if (value & CLIPMASK) {
+ Wprintf("Cannot set default style to Clip Mask");
+ newstyle &= ~(CLIPMASK);
+ return -1;
+ }
+ else {
+ newstyle &= ~mask;
+ newstyle |= value;
+ }
+
+ if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
+ Wprintf("Must have either a border or filler");
+ return -1;
+ }
+ areawin->style = newstyle;
+#ifndef TCL_WRAPPER
+ overdrawpixmap(w);
+#endif
+ }
+#ifndef TCL_WRAPPER
+ setallstylemarks(newstyle);
+#endif
+ if (!preselected)
+ unselect_all();
+
+ return (int)newstyle;
+}
+
+/*-----------------------------------------------*/
+/* Set the color value for all selected elements */
+/*-----------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void setcolor(xcWidget w, int cindex)
+{
+ short *scolor;
+ int *ecolor, cval, oldcolor;
+ Boolean selected = False;
+ stringpart *strptr, *nextptr;
+
+ if (cindex == -1) cval = -1;
+ else cval = colorlist[cindex].color.pixel;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ labelptr curlabel = TOLABEL(EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
+ areawin->topinstance);
+ if (strptr && strptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ strptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else if (nextptr && nextptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ nextptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else {
+ sprintf(_STR2, "%d", cindex);
+ labeltext(FONT_COLOR, (char *)&cindex);
+ }
+ }
+
+ else if (areawin->selects > 0) {
+ for (scolor = areawin->selectlist; scolor < areawin->selectlist
+ + areawin->selects; scolor++) {
+ ecolor = &(SELTOCOLOR(scolor));
+ oldcolor = *ecolor;
+ *ecolor = cval;
+ selected = True;
+
+ register_for_undo(XCF_Color, (scolor == areawin->selectlist
+ + areawin->selects - 1) ? UNDO_DONE : UNDO_MORE,
+ areawin->topinstance,
+ SELTOGENERIC(scolor), (int)oldcolor);
+ }
+ }
+
+ setcolormark(cval);
+ if (!selected) {
+ if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE)
+ areawin->color = cval;
+ }
+ else pwriteback(areawin->topinstance);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the font menu */
+/*--------------------------------------------------------------*/
+
+void togglefontmark(int fontval)
+{
+ if (fonts[fontval].family != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "family", fonts[fontval].family);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label style menu */
+/* fvalue is for font, jvalue is for justification */
+/*------------------------------------------------------*/
+
+void togglestylemark(int styleval)
+{
+ char *cstyle = translatestyle(styleval);
+ if (cstyle != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "style", cstyle);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label encoding menu */
+/*------------------------------------------------------*/
+
+void toggleencodingmark(int encodingval)
+{
+ char *cenc = translateencoding(encodingval);
+ if (cenc != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "encoding", cenc);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label justification & flags menu */
+/*------------------------------------------------------*/
+
+void togglejustmarks(int justvalue)
+{
+ XcInternalTagCall(xcinterp, 4, "label", "justify", (justvalue & RIGHT) ? "right" :
+ (justvalue & NOTLEFT) ? "center" : "left",
+ (justvalue & TOP) ? "top" : (justvalue & NOTBOTTOM) ? "middle" : "bottom");
+ XcInternalTagCall(xcinterp, 3, "label", "flipinvariant", (justvalue & FLIPINV) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 3, "label", "latex", (justvalue & LATEXLABEL) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 3, "label", "visible", (justvalue & PINVISIBLE) ?
+ "true" : "false");
+}
+
+/*-------------------------------------------------------------*/
+/* Simultaneously set all relevant checkmarks for a text label */
+/*-------------------------------------------------------------*/
+
+void setfontmarks(short fvalue, short jvalue)
+{
+ if ((fvalue >= 0) && (fvalue < fontcount)) {
+ toggleencodingmark(fvalue);
+ togglestylemark(fvalue);
+ togglefontmark(fvalue);
+ }
+ togglejustmarks(jvalue);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Parameterize a label string (wrapper for parameterize()). */
+/* Assumes that the name has been generated by the popup prompt */
+/* and is therefore held in variable _STR2 */
+/*--------------------------------------------------------------*/
+
+void stringparam(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ genericptr *settext;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = (genericptr *)EDITPART;
+ makeparam(TOLABEL(settext), _STR2);
+ unselect_all();
+ setparammarks(NULL);
+ }
+ else if (checkselect(LABEL)) parameterize(P_SUBSTRING, _STR2, -1);
+}
+
+/*--------------------------------------------------------------*/
+/* Numerical parameterization (wrapper for parameterize()). */
+/*--------------------------------------------------------------*/
+
+void startparam(xcWidget w, pointertype value, caddr_t calldata)
+{
+ if (value == (pointertype)P_SUBSTRING) {
+ strcpy(_STR2, (calldata != NULL) ? (char *)calldata : "substring");
+ stringparam(w, NULL, NULL);
+ }
+ else if ((eventmode != NORMAL_MODE) || (areawin->selects > 0))
+ parameterize((int)value, (char *)calldata, -1);
+}
+
+/*---------------------------------------------------------------*/
+/* Unparameterize a label string (wrapper for unparameterize()). */
+/*---------------------------------------------------------------*/
+
+void startunparam(xcWidget w, pointertype value, caddr_t calldata)
+{
+ if (areawin->selects > 0)
+ unparameterize((int)value);
+ unselect_all();
+ setparammarks(NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set checkmarks on font menu according to the global defaults */
+/*----------------------------------------------------------------*/
+
+void setdefaultfontmarks()
+{
+ setfontmarks(areawin->psfont, areawin->justify);
+}
+
+/*----------------------------------------------------------------*/
+/* Pick up font name from _STR2 and pass it to loadfontfile() */
+/*----------------------------------------------------------------*/
+
+void locloadfont(xcWidget w, char *value)
+{
+ loadfontfile(_STR2);
+ free(value);
+}
+
+/*----------------------------------------------------------------*/
+/* Find the best matching font given new font, style, or encoding */
+/*----------------------------------------------------------------*/
+/* newfont, style, or encoding = -1 when not applicable */
+/* Return the number of the best matching font. */
+/*----------------------------------------------------------------*/
+
+short findbestfont(short curfont, short newfont, short style, short encoding) {
+
+ char *newfamily;
+ short i, newstyle, newenc;
+
+ if (fontcount == 0) return -1;
+ if (curfont < 0) curfont = 0;
+
+ if (newfont < 0)
+ newfamily = fonts[curfont].family;
+ else if (newfont >= fontcount) { /* move to next font family */
+ short newidx;
+ newfont = 0;
+ while (strcmp(fonts[fontnumbers[newfont]].family, fonts[curfont].family))
+ newfont++;
+ newidx = (newfont + 1) % nfontnumbers;
+ while (!strcmp(fonts[curfont].family, fonts[fontnumbers[newidx]].family) &&
+ newfont != newidx)
+ newidx = (newidx + 1) % nfontnumbers;
+ newfamily = fonts[fontnumbers[newidx]].family;
+ newfont = fontnumbers[newidx];
+ }
+ else
+ newfamily = fonts[newfont].family;
+
+ if (style < 0)
+ newstyle = fonts[curfont].flags & 0x03;
+ else
+ newstyle = style & 0x03;
+
+ if (encoding < 0)
+ newenc = fonts[curfont].flags & 0xf80;
+ else
+ newenc = encoding << 7;
+
+ /* Best position is a match on all conditions */
+
+ for (i = 0; i < fontcount; i++)
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ ((fonts[i].flags & 0x03) == newstyle) &&
+ ((fonts[i].flags & 0xf80) == newenc))
+ return i;
+
+ /* Fallback position 1: Match requested property and one other. */
+ /* order of preference: */
+ /* Requested property Priority 1 Priority 2 */
+ /* Font Style Encoding */
+ /* Style Font (none) */
+ /* Encoding Font (none) */
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ (fonts[i].flags & 0x03) == newstyle) return i;
+ }
+ else if (style >= 0) {
+ if (((fonts[i].flags & 0x03) == newstyle) &&
+ (!strcmp(fonts[i].family, newfamily))) return i;
+ }
+ else if (encoding >= 0) {
+ if (((fonts[i].flags & 0xf80) == newenc) &&
+ (!strcmp(fonts[i].family, newfamily))) return i;
+ }
+ }
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ ((fonts[i].flags & 0xf80) >> 7) == newenc) return i;
+ }
+ }
+
+ /* Fallback position 2: Match only the requested property. */
+ /* For font selection only: Don't want to select a new font */
+ /* just because a certain style or encoding wasn't available.*/
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if (!strcmp(fonts[i].family, newfamily)) return i;
+ }
+ }
+
+ /* Failure to find matching font property */
+
+ if (style >= 0) {
+ Wprintf("Font %s not available in this style", newfamily);
+ }
+ else {
+ Wprintf("Font %s not available in this encoding", newfamily);
+ }
+ return (-1);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the font. This depends on the system state as to whether */
+/* font is set at current position in label, for an entire label, */
+/* or as the default font to begin new labels. */
+/*----------------------------------------------------------------*/
+
+void setfontval(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+ i = findbestfont(tc, (short)value, -1, -1);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+ togglefontmark(i);
+ }
+ }
+ return;
+ }
+ }
+
+ /* otherwise, look for the last style used in the string */
+ tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ /* Font change command will always find a value since at least one */
+ /* font has to exist for the font menu button to exist. */
+
+ if ((newfont = (int)findbestfont(tc, (short)value, -1, -1)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+
+ if (w != NULL) togglefontmark(newfont);
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontval() */
+/*----------------------------------------------------------------*/
+
+void setfont(xcWidget w, pointertype value, caddr_t calldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontval(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontval(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontval(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the style (bold, italic, normal) for the font, similarly */
+/* to the above routine setfontval(). */
+/*----------------------------------------------------------------*/
+
+void setfontstyle(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+
+ /* find font which matches family and style, if available */
+
+ i = findbestfont(tc, -1, (short)value, -1);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+#ifndef TCL_WRAPPER
+ togglefontstyles(w);
+#endif
+ }
+ }
+ return;
+ }
+ }
+
+ /* Otherwise, look for the last font used in the string */
+ /* Fix by Dimitri Princen. Was areawin->textpos - 2; was there a */
+ /* reason for that? */
+
+ tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ if ((newfont = (int)findbestfont(tc, -1, (short)value, -1)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+#ifdef TCL_WRAPPER
+ toggleencodingmark(value);
+#else
+ togglefontstyles(w);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontstyle() */
+/*----------------------------------------------------------------*/
+
+void fontstyle(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontstyle(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontstyle(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontstyle(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the encoding (standard, ISO-Latin1, special) for the font, */
+/* similarly to the above routine setfontval(). */
+/*----------------------------------------------------------------*/
+
+void setfontencoding(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+
+ i = findbestfont(tc, -1, -1, (short)value);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+#ifdef TCL_WRAPPER
+ toggleencodingmark(value);
+#else
+ toggleencodings(w);
+#endif
+ }
+ }
+ return;
+ }
+ }
+
+ /* otherwise, look for the last style used in the string */
+ tc = findcurfont(areawin->textpos - 2, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ if ((newfont = (int)findbestfont(tc, -1, -1, (short)value)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+
+#ifndef TCL_WRAPPER
+ toggleencodings(w);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontencoding() */
+/*----------------------------------------------------------------*/
+
+void fontencoding(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontencoding(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontencoding(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontencoding(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------*/
+/* Generate the table of special characters */
+/* */
+/* Return FALSE if the edited label is LaTeX- */
+/* compatible, since LaTeX text does not */
+/* usually contain special characters, but it */
+/* does contain a lot of backslashes. */
+/*----------------------------------------------*/
+
+Boolean dospecial()
+{
+ labelptr curlabel;
+ int cfont;
+
+ curlabel = TOLABEL(EDITPART);
+ if (curlabel->justify & LATEXLABEL) return False;
+
+ cfont = findcurfont(areawin->textpos, curlabel->string, areawin->topinstance);
+ composefontlib(cfont);
+ startcatalog(NULL, FONTLIB, NULL);
+ return True;
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/menudep.c b/menudep.c
new file mode 100644
index 0000000..5d83545
--- /dev/null
+++ b/menudep.c
@@ -0,0 +1,164 @@
+/*----------------------------------------------------------------------*/
+/* menudep.c */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+/* Parse file menus.h and create file of definitions for use by */
+/* "NameToWidget" to find the menu in the widget menu tree. */
+/*----------------------------------------------------------------------*/
+/* */
+/* example: For menustruct Fonts[], */
+/* #define FontsButton 1 */
+/* */
+/* Name is the menustruct name appended with the word "Button". */
+/* The Widget itself will be placed in the WidgetList "menuwidgets" */
+/* */
+/* NAMING CONVENTIONS: */
+/* Cascade Widget: name of menustruct + "Button" */
+/* Button Widgets: name of menustruct + modified name of button */
+/* + "Button" */
+/* */
+/* "modified name" means that only alphanumeric characters are */
+/* used and the macro (if any) in parentheses is removed. */
+/*----------------------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+#endif
+
+#include "xcircuit.h"
+
+#define _MENUDEP
+#include "menus.h"
+
+int menucount;
+FILE *mp;
+
+/*----------------------------------------------------------------------*/
+
+char *normalize(char *textin)
+{
+ char *tptr = textin;
+ char *sptr;
+ char *newptr = (char *)malloc((strlen(textin) + 1) * sizeof(char));
+ sptr = newptr;
+
+ while (*tptr != '\0') {
+ switch(*tptr) {
+ case ' ': case ':': case '/': case '!': case '_': case '-':
+ case '&': case '.': case '<': case '>':
+ break;
+ case '(':
+ while (*tptr != '\0' && *tptr != ')') tptr++;
+ if (*tptr == '\0') {
+ printf("Open parenthesis in menu.h: %s\n", textin);
+ exit(1);
+ }
+ break;
+ default:
+ *sptr++ = *tptr;
+ break;
+ }
+ tptr++;
+ }
+ *sptr = '\0';
+ return newptr;
+}
+
+/*----------------------------------------------------------------------*/
+
+void log_entry(char *menuname, char *buttonname)
+{
+ char *n1, *n2;
+ n1 = normalize(menuname);
+ n2 = normalize(buttonname);
+ if (strlen(n2) == 0)
+ menucount++;
+ else
+ fprintf(mp, "#define %s%sButton (menuwidgets[%d])\n",
+ n1, n2, menucount++);
+ free(n1);
+ free(n2);
+}
+
+/*----------------------------------------------------------------------*/
+
+void toolbar_entry(char *buttonname)
+{
+ char *n1;
+ n1 = normalize(buttonname);
+ fprintf(mp, "#define %sToolButton (menuwidgets[%d])\n", n1, menucount++);
+ free(n1);
+}
+
+/*----------------------------------------------------------------------*/
+
+void searchsubmenu(char *menuname, menuptr buttonmenu, int arraysize)
+{
+ menuptr p;
+
+ for (p = buttonmenu; p < buttonmenu + arraysize; p++) {
+ if (p->submenu != NULL)
+ searchsubmenu(p->name, p->submenu, p->size);
+ else if (p->name[0] != ' ') /* anything but a separator */
+ log_entry(menuname, p->name);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+int main()
+{
+ short i;
+
+ menucount = 0;
+
+ if ((mp = fopen("menudep.h", "w")) == NULL) {
+ printf("Unable to open menudep.h for output\n");
+ exit(1);
+ }
+
+ fprintf(mp, "/*-------------------------------------------------------*/\n");
+ fprintf(mp, "/* menudep.h generated automatically by program menudep */\n");
+ fprintf(mp, "/* from file menus.h. Do not edit. */\n");
+ fprintf(mp, "/*-------------------------------------------------------*/\n\n");
+
+ /* run the same routine as "createmenus()" in xcircuit.c so that the */
+ /* ordering will be the same. */
+
+ for (i = 0; i < maxbuttons; i++)
+ searchsubmenu(TopButtons[i].name, TopButtons[i].submenu,
+ TopButtons[i].size);
+
+#ifdef HAVE_XPM
+ for (i = 0; i < toolbuttons; i++)
+ toolbar_entry(ToolBar[i].name);
+#endif
+
+ fprintf(mp, "#define MaxMenuWidgets %d\n", menucount);
+ fprintf(mp, "\n/*-------------------------------------------------------*/\n\n");
+
+ fclose(mp);
+ exit(0);
+}
+
+#else
+
+#include <stdio.h>
+
+int main()
+{
+ /* create empty file menudep.h */
+ FILE *fid = fopen("menudep.h", "w");
+ fclose(fid);
+ return 0;
+}
+
+#endif /* TCL_WRAPPER */
diff --git a/menus.h b/menus.h
new file mode 100644
index 0000000..fdd1367
--- /dev/null
+++ b/menus.h
@@ -0,0 +1,434 @@
+/*-------------------------------------------------------------------------*/
+/* menus.h */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* Hierarchical menus must be listed in bottom-up order */
+/*-------------------------------------------------------------------------*/
+/* Note: underscore (_) before name denotes a color to paint the button. */
+/* colon (:) before name denotes a stipple, defined by the data */
+/* passed to setfill(). */
+/*-------------------------------------------------------------------------*/
+
+#ifdef _MENUDEP
+
+#define submenu(a) a, (sizeof (a) / sizeof(menustruct)), NULL, NULL
+#define action(b,c) NULL, 0, NULL, NULL
+#define setaction(b,c) NULL, 1, NULL, NULL
+#define toolaction(b,c) NULL, NULL
+#define noaction NULL, 0, NULL, NULL
+#define offset(a) 0
+
+#else /* real definitions. . .*/
+
+#define submenu(a) a, (sizeof (a) / sizeof(menustruct)), \
+ (XtCallbackProc)DoNothing, NULL
+#define action(b,c) NULL, 0, (XtCallbackProc)b, c
+#define setaction(b,c) NULL, 1, (XtCallbackProc)b, c
+#define toolaction(b,c) (XtCallbackProc)b, c
+#define noaction NULL, 0, (XtCallbackProc)DoNothing, NULL
+#define offset(a) Number(XtOffset(XCWindowDataPtr, a))
+
+#endif
+
+/* Inclusions for pixmap icons */
+
+#include "tool_bar.h"
+
+/* Things commented out here are reminders of future implementations. */
+
+menustruct Fonts[] = {
+ {"Add New Font", action(addnewfont, NULL)},
+ {" ", noaction},
+};
+
+/* Note the unorthodox passing of integer constants through type pointer */
+
+menustruct FontStyles[] = {
+ {"Normal", setaction(fontstyle, Number(0))},
+ {"Bold", action(fontstyle, Number(1))},
+ {"Italic", action(fontstyle, Number(2))},
+ {"BoldItalic", action(fontstyle, Number(3))},
+ {" ", noaction},
+ {"Subscript", action(addtotext, Number(SUBSCRIPT))},
+ {"Superscript", action(addtotext, Number(SUPERSCRIPT))},
+ {"Normalscript", action(addtotext, Number(NORMALSCRIPT))},
+ {" ", noaction},
+ {"Underline", action(addtotext, Number(UNDERLINE))},
+ {"Overline", action(addtotext, Number(OVERLINE))},
+ {"No line", action(addtotext, Number(NOLINE))},
+};
+
+menustruct FontEncodings[] = {
+ {"Standard", setaction(fontencoding, Number(0))},
+ {"ISO-Latin1", action(fontencoding, Number(2))},
+};
+
+menustruct TextSpacing[] = {
+ {"Tab stop", action(addtotext, Number(TABSTOP))},
+ {"Tab forward", action(addtotext, Number(TABFORWARD))},
+ {"Tab backward", action(addtotext, Number(TABBACKWARD))},
+ {"Carriage Return", action(addtotext, Number(RETURN))},
+ {"1/2 space", action(addtotext, Number(HALFSPACE))},
+ {"1/4 space", action(addtotext, Number(QTRSPACE))},
+ {"Kern", action(getkern, NULL)},
+ {"Character", action(addtotext, Number(SPECIAL))},
+};
+
+menustruct Justifs[] = {
+ {"Left Justified", setaction(sethjust, Number(NORMAL))},
+ {"Center Justified", action(sethjust, Number(NOTLEFT))},
+ {"Right Justified", action(sethjust, Number(NOTLEFT | RIGHT))},
+ {" ", noaction},
+ {"Top Justified", action(setvjust, Number(NOTBOTTOM | TOP))},
+ {"Middle Justified", action(setvjust, Number(NOTBOTTOM))},
+ {"Bottom Justified", setaction(setvjust, Number(NORMAL))},
+ {" ", noaction},
+ {"Flip Invariant", setaction(setjustbit, Number(FLIPINV))},
+};
+
+menustruct BoxEditStyles[] = {
+ {"Manhattan Box Edit", setaction(boxedit, Number(MANHATTAN))},
+ {"Rhomboid X", action(boxedit, Number(RHOMBOIDX))},
+ {"Rhomboid Y", action(boxedit, Number(RHOMBOIDY))},
+ {"Rhomboid A", action(boxedit, Number(RHOMBOIDA))},
+ {"Normal", action(boxedit, Number(NORMAL))},
+};
+
+menustruct GridStyles[] = {
+ {"Decimal Inches", action(getgridtype, Number(DEC_INCH))},
+ {"Fractional Inches", setaction(getgridtype, Number(FRAC_INCH))},
+ {"Centimeters", action(getgridtype, Number(CM))},
+ {" ", noaction},
+ {"Drawing Scale", action(getdscale, NULL)},
+};
+
+menustruct Libraries[] = {
+ {"Add New Library", action(newlibrary, NULL)},
+ {" ", noaction},
+ {"Library 1", action(startcatalog, Number(LIBRARY))},
+ {"Library 2", action(startcatalog, Number(LIBRARY + 1))},
+};
+
+menustruct Pages[] = {
+ {"Add New Page", action(newpagemenu, Number(255))},
+ {" ", noaction},
+ {"Page 1", action(newpagemenu, Number(0))},
+ {"Page 2", action(newpagemenu, Number(1))},
+ {"Page 3", action(newpagemenu, Number(2))},
+ {"Page 4", action(newpagemenu, Number(3))},
+ {"Page 5", action(newpagemenu, Number(4))},
+ {"Page 6", action(newpagemenu, Number(5))},
+ {"Page 7", action(newpagemenu, Number(6))},
+ {"Page 8", action(newpagemenu, Number(7))},
+ {"Page 9", action(newpagemenu, Number(8))},
+ {"Page 10", action(newpagemenu, Number(9))}
+};
+
+menustruct BorderStyles[] = {
+ {"Linewidth", action(getwwidth, NULL)},
+ {" ", noaction},
+ {"Solid", setaction(setline, Number(NORMAL))},
+ {"Dashed", action(setline, Number(DASHED))},
+ {"Dotted", action(setline, Number(DOTTED))},
+ {"Unbordered", action(setline, Number(NOBORDER))},
+ {" ", noaction},
+ {"Closed", action(setclosure, Number(UNCLOSED))},
+ {"Bounding Box", action(makebbox, Number(BBOX))},
+};
+
+menustruct Colors[] = {
+ {"Add New Color", action(addnewcolor, NULL)},
+ {" ", noaction},
+ {"Inherit Color", setaction(setcolor, Number(1))},
+ {"_Black", action(setcolor, NULL)},
+ {"_White", action(setcolor, NULL)},
+};
+
+menustruct Parameterize[] = {
+ {"Substring", action(promptparam, NULL)},
+ {"Numeric", action(startparam, Number(P_NUMERIC))},
+ {"Style", action(startparam, Number(P_STYLE))},
+ {"Justification", action(startparam, Number(P_JUSTIFY))},
+ {"Start Angle", action(startparam, Number(P_ANGLE1))},
+ {"End Angle", action(startparam, Number(P_ANGLE2))},
+ {"Radius", action(startparam, Number(P_RADIUS))},
+ {"Minor Axis", action(startparam, Number(P_MINOR_AXIS))},
+ {"Rotation", action(startparam, Number(P_ROTATION))},
+ {"Scale", action(startparam, Number(P_SCALE))},
+ {"Linewidth", action(startparam, Number(P_LINEWIDTH))},
+ {"Color", action(startparam, Number(P_COLOR))},
+ {"Position", action(startparam, Number(P_POSITION))},
+};
+
+menustruct Stipples[] = {
+ {":Black", action(setfill, Number(OPAQUE | FILLED | FILLSOLID))},
+ {":Gray12", action(setfill, Number(OPAQUE | FILLED | STIP2 | STIP1))},
+ {":Gray25", action(setfill, Number(OPAQUE | FILLED | STIP2 | STIP0))},
+ {":Gray37", action(setfill, Number(OPAQUE | FILLED | STIP2))},
+ {":Gray50", action(setfill, Number(OPAQUE | FILLED | STIP0 | STIP1))},
+ {":Gray62", action(setfill, Number(OPAQUE | FILLED | STIP1))},
+ {":Gray75", action(setfill, Number(OPAQUE | FILLED | STIP0))},
+ {":Gray87", action(setfill, Number(OPAQUE | FILLED))},
+ {":White", setaction(setfill, Number(FILLSOLID))},
+ {" ", noaction},
+ {"Opaque", action(setopaque, Number(OPAQUE))},
+ {"Transparent", setaction(setopaque, Number(NORMAL))},
+};
+
+menustruct TextMenu[] = {
+ {"Text Size", action(gettsize, NULL)},
+ {"Font", submenu(Fonts)},
+ {"Style", submenu(FontStyles)},
+ {"Encoding", submenu(FontEncodings)},
+ {"Insert", submenu(TextSpacing)},
+ {"Justification (keypad)", submenu(Justifs)},
+ {"Parameterize", action(promptparam, NULL)},
+ {"Unparameterize", action(startunparam, Number(P_SUBSTRING))},
+ {" ", noaction},
+ {"Set LaTeX Mode", action(setjustbit, Number(LATEXLABEL))},
+ {" ", noaction},
+ {"Make Label (t)", action(changetool, Number(XCF_Text))},
+};
+
+menustruct PolyMenu[] = {
+ {"Border", submenu(BorderStyles)},
+ {"Fill", submenu(Stipples)},
+ {"Color", submenu(Colors)},
+ {" ", noaction},
+ {"Object size", action(getosize, NULL)},
+ {"Parameters", submenu(Parameterize)},
+ {"Center Object", setaction(toggle, offset(center))},
+ {"Manhattan Draw", action(toggle, offset(manhatn))},
+ {"Polygon Edit", submenu(BoxEditStyles)},
+};
+
+menustruct FilterMenu[] = {
+ {"Labels", setaction(selectfilter, Number(LABEL))},
+ {"Objects", setaction(selectfilter, Number(OBJINST))},
+ {"Polygons", setaction(selectfilter, Number(POLYGON))},
+ {"Arcs", setaction(selectfilter, Number(ARC))},
+ {"Splines", setaction(selectfilter, Number(SPLINE))},
+ {"Paths", setaction(selectfilter, Number(PATH))},
+};
+
+menustruct RotateMenu[] = {
+ {"Flip Horizontal (f)", action(exec_or_changetool, Number(XCF_Flip_X))},
+ {"Flip Vertical (F)", action(exec_or_changetool, Number(XCF_Flip_Y))},
+ {" ", noaction},
+ {"Rotate CW 90", action(rotatetool, Number(90))},
+ {"Rotate CW 45", action(rotatetool, Number(45))},
+ {"Rotate CW 30", action(rotatetool, Number(30))},
+ {"Rotate CW 15 (r)", action(rotatetool, Number(15))},
+ {"Rotate CW 5 (o)", action(rotatetool, Number(3))},
+ {"Rotate CW 1", action(rotatetool, Number(1))},
+ {" ", noaction},
+ {"Rotate CCW 90", action(rotatetool, Number(-90))},
+ {"Rotate CCW 45", action(rotatetool, Number(-45))},
+ {"Rotate CCW 30", action(rotatetool, Number(-30))},
+ {"Rotate CCW 15 (R)", action(rotatetool, Number(-15))},
+ {"Rotate CCW 5 (O)", action(rotatetool, Number(-5))},
+ {"Rotate CCW 1", action(rotatetool, Number(-1))},
+};
+
+menustruct LineMenu[] = {
+ {"Global Linewidth", action(getwirewidth, NULL)},
+ {"Wire Linewidth", action(getwwidth, NULL)},
+};
+
+menustruct GridMenu[] = {
+ {"Grid", setaction(toggle, offset(gridon))},
+ {"Axes", setaction(toggle, offset(axeson))},
+ {"Grid spacing", action(getgridspace, NULL)},
+ {"Grid type/display", submenu(GridStyles)},
+};
+
+menustruct SnapMenu[] = {
+ {"Snap-to", setaction(toggle, offset(snapto))},
+ {"Snap spacing", action(getsnapspace, NULL)},
+};
+
+menustruct PinConvert[] = {
+ {"Normal label", action(dopintype, Number(NORMAL))},
+ {"Local Pin", action(dopintype, Number(LOCAL))},
+ {"Global Pin", action(dopintype, Number(GLOBAL))},
+ {"Info label", action(dopintype, Number(INFO))},
+};
+
+menustruct SchemaMenu[] = {
+ {"Make Pin (T)", action(changetool, Number(XCF_Pin_Label))},
+ {"Make Info Pin (I)", action(changetool, Number(XCF_Info_Label))},
+ {"Make Global Pin (G)", action(changetool, Number(XCF_Pin_Global))},
+ {"Convert Label to...", submenu(PinConvert)},
+ {"Pin Visibility", action(setpinjustbit, Number(PINVISIBLE))},
+/* {"Make Object Non-Schematic", action(maketrivial, NULL)}, */
+ {"Make Matching Symbol", action(dobeforeswap, NULL)},
+ {"Associate with Symbol", action(startschemassoc, Number(1))},
+ {"Highlight Connectivity", action(startconnect, NULL)},
+ {"Auto-number Components", action(callwritenet, Number(4))},
+ {" ", noaction},
+ {"Write spice", action(callwritenet, Number(0))},
+ {"Write flattened spice", action(callwritenet, Number(3))},
+ {"Write sim", action(callwritenet, Number(1))},
+ {"Write pcb", action(callwritenet, Number(2))},
+};
+
+menustruct WindowMenu[] = {
+ {"Zoom In (Z)", action(zoominrefresh, NULL)},
+ {"Zoom Out (z)", action(zoomoutrefresh, NULL)},
+ {"Full View (v)", action(zoomview, NULL)},
+ {"Pan (p)", action(pantool, Number(6))},
+ {"Refresh ( )", action(refresh, NULL)},
+ {" ", noaction},
+ {"Library Directory (L)", action(startcatalog, Number(LIBLIB))},
+ {"Goto Library", submenu(Libraries)},
+ {" ", noaction},
+ {"Page Directory (P)", action(startcatalog, Number(PAGELIB))},
+ {"Goto Page", submenu(Pages)}
+};
+
+menustruct FileMenu[] = {
+#ifdef XC_WIN32
+ {"New window", action(win32_new_window, NULL)},
+ {" ", noaction},
+#endif
+ {"Read Xcircuit File", action(getfile, Number(NORMAL))},
+ {"Import Xcircuit PS", action(getfile, Number(IMPORT))},
+ {"Import background PS", action(getfile, Number(PSBKGROUND))},
+#ifdef ASG
+ {"Import SPICE deck", action(getfile, Number(IMPORTSPICE))},
+#endif
+ {"Execute script", action(getfile, Number(SCRIPT))},
+ {"Write Xcircuit PS (W)", action(outputpopup, NULL)},
+ {" ", noaction},
+ {"Add To Library", action(getlib, NULL)},
+ {"Load New Library", action(getuserlib, NULL)},
+ {"Save Library", action(savelibpopup, NULL)},
+ {" ", noaction},
+ {"Clear Page", action(resetbutton, Number(0))},
+ {" ", noaction},
+ {"Quit", action(quitcheck, NULL)},
+};
+
+menustruct OptionMenu[] = {
+ {"Alt Colors", action(inversecolor, offset(invert))},
+ {"Show Bounding box", action(toggle, offset(bboxon))},
+ {"Edit in place", setaction(toggle, offset(editinplace))},
+ {"Show Pin Positions", action(toggle, offset(pinpointon))},
+#ifdef HAVE_XPM
+ {"Disable Toolbar", action(dotoolbar, NULL)},
+#endif
+ {"Grid", submenu(GridMenu)},
+ {"Snap-to", submenu(SnapMenu)},
+ {"Linewidth", submenu(LineMenu)},
+ {"Elements", submenu(PolyMenu)},
+ {" ", noaction},
+ {"Help!", action(starthelp, NULL)},
+};
+
+menustruct EditMenu[] = {
+ {"Undo (u)", action(undo_call, NULL)},
+ {"Redo (U)", action(redo_call, NULL)},
+ {" ", noaction},
+ {"Delete (d)", action(exec_or_changetool, Number(XCF_Delete))},
+ {"Copy (c)", action(exec_or_changetool, Number(XCF_Copy))},
+ {"Edit (e)", action(exec_or_changetool, Number(XCF_Edit))},
+ {"Rotate/Flip", submenu(RotateMenu)},
+ {"Deselect (x)", action(startdesel, NULL)},
+ {"Select filter", submenu(FilterMenu)},
+ {"Push selected (>)", action(exec_or_changetool, Number(XCF_Push))},
+ {"Pop hierarchy (<)", action(popobject, Number(0))},
+ {" ", noaction},
+ {"Make User Object (m)", action(selectsave, NULL)},
+ {"Make Arc (a)", action(changetool, Number(XCF_Arc))},
+ {"Make Box (b)", action(changetool, Number(XCF_Box))},
+ {"Make Spline (s)", action(changetool, Number(XCF_Spline))},
+ {"Join (j)", action(join, NULL)},
+};
+
+menustruct TopButtons[] = {
+ {"File", submenu(FileMenu)},
+ {"Edit", submenu(EditMenu)},
+ {"Text", submenu(TextMenu)},
+ {"Options", submenu(OptionMenu)},
+ {"Window", submenu(WindowMenu)},
+ {"Netlist", submenu(SchemaMenu)},
+};
+
+short maxbuttons = sizeof(TopButtons) / sizeof(menustruct);
+
+#ifdef HAVE_XPM
+/* Toolbar buttons */
+toolbarstruct ToolBar[] = {
+ {"Pan", pn_xpm, toolaction(pantool, Number(6)),
+ "pan mode"},
+ {"Wire", w_xpm, toolaction(changetool, Number(XCF_Wire)),
+ "draw wire"},
+ {"Box", b_xpm, toolaction(changetool, Number(XCF_Box)),
+ "draw box"},
+ {"Arc", a_xpm, toolaction(changetool, Number(XCF_Arc)),
+ "draw arc"},
+ {"Spline", s_xpm, toolaction(changetool, Number(XCF_Spline)),
+ "draw spline"},
+ {"Text", t_xpm, toolaction(changetool, Number(XCF_Text)),
+ "enter text"},
+ {"Move", mv_xpm, toolaction(exec_or_changetool, Number(XCF_Move)),
+ "move element"},
+ {"Copy", cp_xpm, toolaction(exec_or_changetool, Number(XCF_Copy)),
+ "copy element"},
+ {"Edit", e_xpm, toolaction(exec_or_changetool, Number(XCF_Edit)),
+ "edit element"},
+ {"Delete", d2_xpm, toolaction(exec_or_changetool, Number(XCF_Delete)),
+ "delete element"},
+ {"RotP", cw_xpm, toolaction(rotatetool, Number(15)),
+ "rotate 15 degrees clockwise"},
+ {"RotN", ccw_xpm, toolaction(rotatetool, Number(-15)),
+ "rotate 15 degrees counterclockwise"},
+ {"HFlip", fx_xpm, toolaction(exec_or_changetool, Number(XCF_Flip_X)),
+ "flip horizontal"},
+ {"VFlip", fy_xpm, toolaction(exec_or_changetool, Number(XCF_Flip_Y)),
+ "flip vertical"},
+ {"Push", pu2_xpm, toolaction(exec_or_changetool, Number(XCF_Push)),
+ "push (edit object)"},
+ {"Pop", po2_xpm, toolaction(popobject, Number(0)),
+ "pop (return from object edit)"},
+ {"Make", mk_xpm, toolaction(selectsave, NULL),
+ "make an object from selected elements"},
+ {"Join", pz_xpm, toolaction(join, NULL),
+ "join elements into polygon or path"},
+ {"Unjoin", uj_xpm, toolaction(unjoin, NULL),
+ "separate path into elements"},
+ {"Colors", co_xpm, toolaction(color_popup, NULL),
+ "set color"},
+ {"Border", bd_xpm, toolaction(border_popup, NULL),
+ "set border and line properties"},
+ {"Fills", fi_xpm, toolaction(fill_popup, NULL),
+ "set fill properties"},
+ {"Parameters", pm_xpm, toolaction(param_popup, NULL),
+ "parameterize properties"},
+ {"Library",li_xpm, toolaction(changecat, NULL),
+ "go to next library"},
+ {"Libdir", yp_xpm, toolaction(startcatalog, Number(LIBLIB)),
+ "go to library directory"},
+ {"Pagedir",pl_xpm, toolaction(startcatalog, Number(PAGELIB)),
+ "go to page directory"},
+ {"ZoomI", z4_xpm, toolaction(zoominrefresh, NULL),
+ "zoom in"},
+ {"ZoomO", z5_xpm, toolaction(zoomoutrefresh, NULL),
+ "zoom out"},
+ {"Help", i_xpm, toolaction(starthelp, NULL),
+ "pop up help window"},
+};
+
+short toolbuttons = sizeof(ToolBar) / sizeof(toolbarstruct);
+#endif
+
+#undef submenu
+#undef action
+#undef setaction
+#undef toolaction
+#undef noaction
+#undef offset
+
+/*-------------------------------------------------------------------------*/
diff --git a/missing b/missing
new file mode 100755
index 0000000..0a7fb5a
--- /dev/null
+++ b/missing
@@ -0,0 +1,283 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing 0.3 - GNU automake"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+ # We have makeinfo, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ tar)
+ shift
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ fi
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar ${1+"$@"} && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar ${1+"$@"} && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..d71d3ba
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2011/04/10 21:15:05 tim Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/netlist.c b/netlist.c
new file mode 100644
index 0000000..4e04473
--- /dev/null
+++ b/netlist.c
@@ -0,0 +1,6615 @@
+/*----------------------------------------------------------------------*/
+/* netlist.c --- xcircuit routines specific to schematic capture and */
+/* netlist generation */
+/*----------------------------------------------------------------------*/
+/* Copyright (c) 2004 Tim Edwards, Johns Hopkins University, */
+/* MultiGiG, Inc., and Open Circuit Design, Inc. */
+/* Copyright (c) 2005 Tim Edwards, MultiGiG, Inc. */
+/* */
+/* Written April 1998 to January 2004 */
+/* Original version for Pcb netlisting 3/20/98 by Chow Seong Hwai, */
+/* Leeds University, U.K. */
+/* */
+/* Greatly modified 4/2/04 to handle bus notation; net identifier */
+/* changed from a listing by net to two listings, by polygon and by */
+/* label, with nets and subnets identifiers attached to each element, */
+/* rather than vice versa. */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h> /* For preventing multiple file inclusions, use stat() */
+#include <sys/stat.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+#endif
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+#ifdef HAVE_PYTHON
+extern PyObject *PyGetStringParts(stringpart *);
+#endif
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+extern Tcl_Obj *TclGetStringParts(stringpart *);
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Externally declared global variables */
+/*----------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern int *appcolors;
+
+/*----------------------------------------------------------------------*/
+
+extern char _STR[150];
+extern char _STR2[250];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern Boolean load_in_progress;
+
+LabellistPtr global_labels;
+
+typedef struct _flatindex *fidxptr;
+
+typedef struct _flatindex {
+ char *devname;
+ u_int index;
+ fidxptr next;
+} flatindex; /* count for labeling devices in a flattened file */
+
+flatindex *flatrecord = NULL;
+
+static char *spice_devname = "X"; /* SPICE subcircuit device name */
+Boolean spice_end = True; /* whether or not to write a .end statement */
+ino_t *included_files = NULL; /* Files included with "%F" escape */
+
+#define EndPoint(n) (((n == 1) ? 1 : (int)(n - 1)))
+#define NextPoint(n) (((n == 1) ? 0 : 1))
+
+/* For bus matching: whether to match by number of nets, by */
+/* exact match of sub-bus numbers, or an exact match of net IDs. */
+
+#define MATCH_EXACT 0
+#define MATCH_SUBNETS 1
+#define MATCH_SIZE 2
+#define MATCH_OVERLAP 3
+
+/*----------------------------------------------------------------------*/
+/* Check whether two line segments attach to or cross each other */
+/* Return 1 if attached, 0 if not (INLINE code) */
+/* int onsegment(XPoint *a, XPoint *b, XPoint *x) {} */
+/*----------------------------------------------------------------------*/
+
+#define ONDIST 4 /* "slack" in algorithm for almost-touching lines */
+#define onsegment(a, b, x) (finddist(a, b, x) <= ONDIST)
+
+/*--------------------------------------------------------------*/
+/* d36a: Base 36 to string conversion */
+/*--------------------------------------------------------------*/
+
+char *d36a(int number)
+{
+ static char bconv[10];
+ int i, locn, rem;
+
+
+ bconv[9] = '\0';
+ i = 8;
+ locn = number;
+ while ((locn > 0) && (i >= 0)) {
+ rem = locn % 36;
+ locn /= 36;
+ bconv[i--] = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
+ }
+ return &bconv[i + 1];
+}
+
+/*--------------------------------------------------------------*/
+/* Translate a pin name to a position relative to an object's */
+/* point of origin. This is used by the ASG module to find */
+/* the placement of pins based on names from a netlist. */
+/* */
+/* returns 0 on success and fills x_ret and y_ret with the */
+/* pin position coordinates. Returns -1 if the pin name did */
+/* not match any label names in the object. */
+/*--------------------------------------------------------------*/
+
+int NameToPinLocation(objinstptr thisinst, char *pinname, int *x_ret, int *y_ret)
+{
+ objectptr thisobj = thisinst->thisobject;
+ genericptr *pgen;
+ labelptr plab;
+
+ if (thisobj->schemtype == SECONDARY)
+ thisobj = thisobj->symschem;
+
+ for (pgen = thisobj->plist; pgen < thisobj->plist + thisobj->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plab = TOLABEL(pgen);
+ if (plab->pin != False && plab->pin != INFO) {
+ if (!textcomp(plab->string, pinname, thisinst)) {
+ *x_ret = (int)plab->position.x;
+ *y_ret = (int)plab->position.y;
+ return 0;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+/*--------------------------------------------------------------*/
+/* Translate a point position back to the calling object's */
+/* coordinate system. */
+/* Original value is passed in "thispoint"; Translated value */
+/* is put in "refpoint". */
+/*--------------------------------------------------------------*/
+
+void ReferencePosition(objinstptr thisinst, XPoint *thispoint, XPoint *refpoint)
+{
+ /* objectptr thisobj = thisinst->thisobject; (jdk) */
+ Matrix locctm;
+
+ /* Translate pin position back to originating object */
+
+ UResetCTM(&locctm);
+ UPreMultCTM(&locctm, thisinst->position, thisinst->scale,
+ thisinst->rotation);
+ UTransformbyCTM(&locctm, thispoint, refpoint, 1);
+}
+
+/*--------------------------------------------------------------*/
+/* Variant of NameToPinLocation(): Given a port number, find */
+/* the pin associated with that port. */
+/*--------------------------------------------------------------*/
+
+labelptr PortToLabel(objinstptr thisinst, int portno)
+{
+ labelptr plab;
+ objectptr thisobj = thisinst->thisobject;
+ PortlistPtr ports;
+
+ if ((thisobj->schemtype == SYMBOL) && (thisobj->symschem != NULL))
+ ports = thisobj->symschem->ports;
+ else
+ ports = thisobj->ports;
+
+ for (; ports != NULL; ports = ports->next) {
+ if (ports->portid == portno) {
+ plab = NetToLabel(ports->netid, thisobj); /* in the symbol! */
+ return plab;
+ }
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* This function is the same as PortToLocalPosition() but */
+/* returns the point in the coordinate system of the parent. */
+/*--------------------------------------------------------------*/
+
+Boolean PortToPosition(objinstptr thisinst, int portno, XPoint *refpoint)
+{
+ labelptr plab = PortToLabel(thisinst, portno);
+ if (plab)
+ ReferencePosition(thisinst, &(plab->position), refpoint);
+
+ return (plab != NULL) ? TRUE : FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get the hierarchy of the page stack and return as a string */
+/*----------------------------------------------------------------------*/
+
+Boolean getnexthier(pushlistptr stack, char **hierstr, objinstptr callinst,
+ Boolean canonical)
+{
+ objectptr topobj, thisobj;
+ CalllistPtr calls;
+ /* char numstr[12]; (jdk) */
+ int hierlen, devlen;
+ char *devstr;
+
+ if (!stack) return False;
+
+ /* Recurse so we build up the prefix string from top down */
+ if (stack->next != NULL) {
+ if (getnexthier(stack->next, hierstr, stack->thisinst, canonical) == False)
+ return False;
+ }
+ else {
+ topobj = stack->thisinst->thisobject;
+
+ if (topobj->schemtype != PRIMARY && topobj->symschem != NULL)
+ topobj = topobj->symschem;
+
+ if (topobj->calls == NULL) {
+ if (topobj->schemtype == FUNDAMENTAL) {
+ /* Top level is a fundamental symbol */
+ return True;
+ }
+ else if ((updatenets(stack->thisinst, FALSE) <= 0) || (topobj->calls == NULL)) {
+ Wprintf("Error in generating netlists!");
+ return False;
+ }
+ }
+ }
+
+ thisobj = stack->thisinst->thisobject;
+
+ /* When we have "traveled" through both a symbol and its */
+ /* associated schematic, only append the prefix for the */
+ /* first one encountered. */
+
+/*
+ if (thisobj->symschem != NULL && stack->next != NULL &&
+ thisobj->symschem == stack->next->thisinst->thisobject)
+ return True;
+*/
+
+ if ((thisobj->calls == NULL) && (thisobj->schemtype != PRIMARY)
+ && (thisobj->symschem != NULL))
+ thisobj = thisobj->symschem;
+
+ /* Check for resolved device indices and generate them if necessary */
+
+ for (calls = thisobj->calls; calls != NULL; calls = calls->next)
+ if (calls->callinst == callinst)
+ if (calls->devindex == -1) {
+ cleartraversed(thisobj);
+ resolve_indices(thisobj, FALSE);
+ break;
+ }
+
+ /* Add this level of the hierarchy to the prefix string */
+
+ for (calls = thisobj->calls; calls != NULL; calls = calls->next) {
+ if (calls->callinst == callinst) {
+ devlen = (canonical || calls->devname == NULL) ?
+ strlen(callinst->thisobject->name) : strlen(calls->devname);
+ devstr = d36a(calls->devindex);
+ devlen += strlen(devstr) + 1;
+ if (*hierstr == NULL) {
+ *hierstr = malloc(devlen);
+ hierlen = 0;
+ }
+ else {
+ hierlen = strlen(*hierstr) + 2;
+ *hierstr = realloc(*hierstr, hierlen + devlen);
+ }
+ if (canonical)
+ sprintf(*hierstr + hierlen, "%s%s(%s)",
+ ((hierlen > 0) ? "/" : ""),
+ callinst->thisobject->name, devstr);
+ else
+ sprintf(*hierstr + hierlen, "%s%s%s",
+ ((hierlen > 0) ? "/" : ""),
+ (calls->devname == NULL) ? callinst->thisobject->name
+ : calls->devname, devstr);
+ break;
+ }
+ }
+ return True;
+}
+
+/*----------------------------------------------------------------------*/
+
+char *GetHierarchy(pushlistptr *stackptr, Boolean canonical)
+{
+ Boolean pushed_top = FALSE;
+ char *snew = NULL;
+
+ if ((*stackptr) && ((*stackptr)->thisinst != areawin->topinstance)) {
+ pushed_top = TRUE;
+ push_stack(stackptr, areawin->topinstance, NULL);
+ }
+
+ getnexthier(*stackptr, &snew, NULL, canonical);
+
+ if (pushed_top) pop_stack(stackptr);
+
+ return snew;
+}
+
+/*----------------------------------------------------------------------*/
+/* Invalidate a netlist. The invalidation must be referred to the */
+/* master schematic, if the object is a secondary schematic. */
+/*----------------------------------------------------------------------*/
+
+void invalidate_netlist(objectptr thisobject)
+{
+ if (thisobject->schemtype != NONETWORK) {
+ if (thisobject->schemtype == SECONDARY)
+ thisobject->symschem->valid = False;
+ else
+ thisobject->valid = False;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Check if the selected items are relevant to the netlist. */
+/* Only invalidate the current netlist if they are. */
+/*--------------------------------------------------------------*/
+
+void select_invalidate_netlist()
+{
+ int i;
+ Boolean netcheck = FALSE;
+
+ for (i = 0; i < areawin->selects; i++) {
+ genericptr gptr = SELTOGENERIC(areawin->selectlist + i);
+ switch (gptr->type) {
+ case POLYGON:
+ if (!nonnetwork(TOPOLY(&gptr)))
+ netcheck = TRUE;
+ break;
+ case LABEL:
+ if ((TOLABEL(&gptr))->pin == LOCAL || (TOLABEL(&gptr))->pin == GLOBAL)
+ netcheck = TRUE;
+ break;
+ case OBJINST:
+ if ((TOOBJINST(&gptr))->thisobject->schemtype != NONETWORK)
+ netcheck = TRUE;
+ break;
+ }
+ }
+ if (netcheck) invalidate_netlist(topobject);
+}
+
+/*------------------------------------------------------------------*/
+/* Check proximity of two points (within roundoff tolerance ONDIST) */
+/*------------------------------------------------------------------*/
+
+Boolean proximity(XPoint *point1, XPoint *point2)
+{
+ int dx, dy;
+
+ dx = point1->x - point2->x;
+ dy = point1->y - point2->y;
+
+ if ((abs(dx) < ONDIST) && (abs(dy) < ONDIST)) return True;
+ else return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* createnets(): Generate netlist structures */
+/* */
+/* Result is the creation of three linked lists inside each object in */
+/* the circuit hierarchy: */
+/* */
+/* 1) the netlist: assigns a number to each network of polygons and */
+/* pin labels on the object. */
+/* 2) the ports: a list of every network which is connected from */
+/* objects above this one in the hierarchy. */
+/* 3) the calls: a list of calls made from the object to all sub- */
+/* circuits. Each calls indicates the object and/or */
+/* instance being called, and a port list which must match */
+/* the ports of the object being called (the port lists */
+/* are not reflexive, as the caller does not have to call */
+/* all of the instance's ports, but the instance must have */
+/* a port defined for every connection being called). */
+/* (see structure definitions in xcircuit.h). */
+/*----------------------------------------------------------------------*/
+
+void createnets(objinstptr thisinst, Boolean quiet)
+{
+ objectptr thisobject = thisinst->thisobject;
+
+ if (!setobjecttype(thisobject)) {
+
+ /* New in 3.3.32: Generating a netlist from a symbol is */
+ /* okay if the symbol has an associated netlist. */
+
+ if (thisobject->schemtype == SYMBOL && thisobject->symschem != NULL)
+ thisobject = thisobject->symschem;
+ else {
+ if (!quiet)
+ Wprintf("Error: attempt to generate netlist for a symbol.");
+ return;
+ }
+ }
+
+
+ /* Wprintf("Generating netlists"); */ /* Diagnostic */
+ gennetlist(thisinst);
+ gencalls(thisobject);
+ cleartraversed(thisobject);
+ resolve_devnames(thisobject);
+ /* Wprintf("Finished netlists"); */
+
+}
+
+/*----------------------------------------------------------------------*/
+/* Free all memory associated with the netlists. */
+/*----------------------------------------------------------------------*/
+
+void destroynets(objectptr thisobject)
+{
+ objectptr pschem;
+
+ pschem = (thisobject->schemtype == SECONDARY) ? thisobject->symschem :
+ thisobject;
+
+ freetemplabels(pschem);
+ freenets(pschem);
+ freeglobals();
+}
+
+/*----------------------------------------------------------------------*/
+/* Polygon types which are ignored when considering if a polygon */
+/* belongs to a circuit network: */
+/* Closed polygons (boxes) */
+/* Bounding box polygons */
+/* Filled polygons */
+/* Dashed and dotted line-style polygons */
+/*----------------------------------------------------------------------*/
+
+Boolean nonnetwork(polyptr cpoly)
+{
+ if (!(cpoly->style & UNCLOSED)) return True;
+ if (cpoly->style & (DASHED | DOTTED | FILLSOLID | BBOX))
+ return True;
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Return the largest (most negative) net number in the global netlist */
+/*----------------------------------------------------------------------*/
+
+int globalmax()
+{
+ LabellistPtr gl;
+ int bidx, sbus;
+ buslist *lbus;
+ int smin = 0;
+
+ for (gl = global_labels; gl != NULL; gl = gl->next) {
+ if (!(gl->subnets)) {
+ if (gl->net.id < smin)
+ smin = gl->net.id;
+ }
+ else {
+ for (bidx = 0; bidx < gl->subnets; bidx++) {
+ lbus = gl->net.list + bidx;
+ sbus = lbus->netid;
+ if (sbus < smin)
+ smin = sbus;
+ }
+ }
+ }
+ return smin;
+}
+
+/*----------------------------------------------------------------------*/
+/* Return the largest net number in an object's netlist */
+/*----------------------------------------------------------------------*/
+
+int netmax(objectptr cschem)
+{
+ PolylistPtr gp;
+ LabellistPtr gl;
+ int bidx, sbus;
+ buslist *lbus;
+ int smax = 0;
+
+ for (gp = cschem->polygons; gp != NULL; gp = gp->next) {
+ if (!(gp->subnets)) {
+ if (gp->net.id > smax)
+ smax = gp->net.id;
+ }
+ else {
+ for (bidx = 0; bidx < gp->subnets; bidx++) {
+ lbus = gp->net.list + bidx;
+ sbus = lbus->netid;
+ if (sbus > smax)
+ smax = sbus;
+ }
+ }
+ }
+ for (gl = cschem->labels; gl != NULL; gl = gl->next) {
+ if (!(gl->subnets)) {
+ if (gl->net.id > smax)
+ smax = gl->net.id;
+ }
+ else {
+ for (bidx = 0; bidx < gl->subnets; bidx++) {
+ lbus = gl->net.list + bidx;
+ sbus = lbus->netid;
+ if (sbus > smax)
+ smax = sbus;
+ }
+ }
+ }
+ return smax;
+}
+
+/*----------------------------------------------------------------------*/
+/* Resolve nets and pins for the indicated object */
+/* */
+/* When encountering object instances, call gennetlist() on the object */
+/* if it does not have a valid netlist, then recursively call */
+/* gennetlist(). Ignore "info" labels, which are not part of the */
+/* network. */
+/* */
+/*----------------------------------------------------------------------*/
+
+void gennetlist(objinstptr thisinst)
+{
+ genericptr *cgen;
+ labelptr olabel, clab;
+ polyptr cpoly, tpoly;
+ objectptr thisobject, callobj, cschem, pschem;
+ objinstptr cinst, labinst;
+ int old_parts; /* netid, tmpid, sub_bus, (jdk) */
+ stringpart *cstr;
+ Boolean visited;
+
+ XPoint *tpt, *tpt2, *endpt, *endpt2;
+ int i, j, n, nextnet, lbus;
+ buslist *sbus;
+ PolylistPtr plist;
+ LabellistPtr lseek;
+ Genericlist *netlist, *tmplist, *buspins, *resolved_net, newlist;
+
+ newlist.subnets = 0;
+ newlist.net.id = -1;
+
+ /* Determine the type of object being netlisted */
+ thisobject = thisinst->thisobject;
+ setobjecttype(thisobject);
+
+ if (thisobject->schemtype == NONETWORK) return;
+
+ /* Has this object been visited before? */
+ visited = ((thisobject->labels != NULL) || (thisobject->polygons != NULL)) ?
+ TRUE : FALSE;
+
+ if (!visited && (thisobject->schemtype == SYMBOL)
+ && (thisobject->symschem != NULL)) {
+
+ /* Make sure that schematics are netlisted before their symbols */
+
+ if ((thisobject->symschem->polygons == NULL) &&
+ (thisobject->symschem->labels == NULL)) {
+ n = is_page(thisobject->symschem);
+ if (n == -1) {
+ Fprintf(stderr, "Error: associated schematic is not a page!\n");
+ return;
+ }
+ else
+ gennetlist(xobjs.pagelist[n]->pageinst);
+ }
+
+ /* Sanity check on symbols with schematics: Are there any pins? */
+
+ for (i = 0; i < thisobject->parts; i++) {
+ cgen = thisobject->plist + i;
+ if (IS_LABEL(*cgen)) {
+ clab = TOLABEL(cgen);
+ if (clab->pin != False && clab->pin != INFO)
+ break;
+ }
+ }
+ if (i == thisobject->parts)
+ Fprintf(stderr, "Warning: Symbol %s has no pins!\n", thisobject->name);
+ }
+
+ /* If this is a secondary schematic, run on the primary (master) */
+ pschem = (thisobject->schemtype == SECONDARY) ? thisobject->symschem :
+ thisobject;
+
+ nextnet = netmax(pschem) + 1;
+
+ /* We start the loop for schematics but will modify the loop */
+ /* variable to execute just once in the case of a symbol. */
+ /* It's just not worth the trouble to turn this into a */
+ /* separate subroutine. . . */
+
+ for (j = 0; j < xobjs.pages; j++) {
+ if (pschem->schemtype != PRIMARY) {
+ j = xobjs.pages;
+ cinst = thisinst;
+ cschem = thisobject;
+ }
+ else {
+ cinst = xobjs.pagelist[j]->pageinst;
+ if ((cinst == NULL) ||
+ ((cinst->thisobject != pschem) &&
+ ((cinst->thisobject->schemtype != SECONDARY) ||
+ (cinst->thisobject->symschem != pschem)))) continue;
+ cschem = cinst->thisobject;
+ }
+
+ /* Determine the existing number of parts. We do not want to */
+ /* search over elements that we create in this routine. */
+
+ old_parts = cschem->parts;
+
+ /* Part 1: Recursion */
+ /* Schematic pages and symbols acting as their own schematics are the */
+ /* two types on which we recurse to find all sub-schematics. */
+
+ if ((!visited) && (cschem->schemtype == PRIMARY ||
+ cschem->schemtype == SECONDARY ||
+ (cschem->schemtype == SYMBOL && cschem->symschem == NULL))) {
+
+ for (i = 0; i < old_parts; i++) {
+ cgen = cschem->plist + i;
+ if (IS_OBJINST(*cgen)) {
+ objinstptr geninst, callinst;
+ geninst = TOOBJINST(cgen);
+
+ if (geninst->thisobject->symschem != NULL) {
+ callobj = geninst->thisobject->symschem;
+ n = is_page(callobj);
+ if (n == -1) {
+ Fprintf(stderr, "Error: associated schematic is not a page!\n");
+ continue;
+ }
+ else
+ callinst = xobjs.pagelist[n]->pageinst;
+ }
+ else {
+ callobj = geninst->thisobject;
+ callinst = geninst;
+ }
+
+ /* object on its own schematic */
+ if (callobj == pschem) continue;
+
+ gennetlist(callinst);
+
+ /* Also generate netlist for pins in the corresponding symbol */
+ if (geninst->thisobject->symschem != NULL)
+ gennetlist(geninst);
+ }
+ }
+ }
+
+ /* Part 2: Match pin labels to nets, and add to list of globals */
+ /* if appropriate. We do all pins first, before ennumerating */
+ /* polygons, so that buses can be handled correctly, generating */
+ /* overlapping subnets. */
+
+ for (i = 0; i < old_parts; i++) {
+ cgen = cschem->plist + i;
+ if (IS_LABEL(*cgen)) {
+ clab = TOLABEL(cgen);
+ if (clab->pin != False && clab->pin != INFO) {
+
+ /* Check if the label has a non-default parameter. */
+ /* If so, we want to record the instance along */
+ /* the other netlist information about the pin. */
+
+ labinst = NULL;
+ for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart)
+ if (cstr->type == PARAM_START)
+ if (match_instance_param(cinst, cstr->data.string) != NULL) {
+ labinst = cinst;
+ break;
+ }
+
+ /* If we have netlisted this object before, and the */
+ /* label is already in the netlist, then ignore it. */
+ /* This only happens for labels without instanced */
+ /* parameter values. */
+
+ if (visited && (labinst == NULL)) {
+ for (lseek = pschem->labels; lseek != NULL; lseek = lseek->next)
+ if ((lseek->label == clab) && (lseek->cinst == NULL))
+ break;
+ if (lseek != NULL) continue;
+ }
+ else if (visited)
+ netlist = NULL;
+ else
+ /* Note any overlapping labels. */
+ netlist = pointtonet(cschem, cinst, &clab->position);
+
+ if (pschem->symschem != NULL && pschem->schemtype == SYMBOL) {
+
+ /* For symbols: Check that this pin has a */
+ /* corresponding pin in the schematic. The schematic */
+ /* is netlisted before the symbol, so the netlist */
+ /* should be there. */
+
+ tmplist = pintonet(pschem->symschem, cinst, clab);
+
+ /* There is always the possibility that the symbol */
+ /* pin does not correspond to anything in the */
+ /* schematic. If so, it gets its own unique net */
+ /* number. HOWEVER, this situation usually indicates */
+ /* an error in the schematic, so output a warning */
+ /* message. */
+
+ if (tmplist == NULL) {
+ char *snew = NULL;
+ snew = textprint(clab->string, NULL),
+ Fprintf(stderr, "Warning: Pin \"%s\" in symbol %s has no "
+ "connection in schematic %s\n",
+ snew, pschem->name,
+ pschem->symschem->name);
+ free(snew);
+ newlist.net.id = nextnet++;
+ tmplist = &newlist;
+ }
+ }
+ else {
+ /* For schematics: Relate the pin to a network */
+ tmplist = pintonet(pschem, cinst, clab);
+
+ /* If only part of a bus has been identified, generate */
+ /* the net ID's of the parts that haven't been. */
+
+ if ((tmplist != NULL) && (tmplist->subnets > 0)) {
+ for (lbus = 0; lbus < tmplist->subnets; lbus++) {
+ sbus = tmplist->net.list + lbus;
+ if (sbus->netid == 0)
+ sbus->netid = nextnet++;
+ }
+ }
+ }
+
+ if (clab->pin == LOCAL) {
+ if (tmplist != NULL) {
+ addpin(cschem, labinst, clab, tmplist);
+ if (netlist != NULL)
+ mergenets(pschem, netlist, tmplist);
+ }
+ else {
+ if (netlist == NULL) {
+ netlist = &newlist;
+ netlist->net.id = nextnet++;
+ buspins = break_up_bus(clab, cinst, netlist);
+ if (buspins != NULL) {
+ buslist *sbus = buspins->net.list + buspins->subnets - 1;
+ nextnet = sbus->netid + 1;
+ netlist = addpin(cschem, labinst, clab, buspins);
+ }
+ else {
+ tmplist = addpin(cschem, labinst, clab, netlist);
+ netlist = tmplist;
+ }
+ }
+ else {
+ tmplist = addpin(cschem, labinst, clab, netlist);
+ netlist = tmplist;
+ }
+ }
+ }
+ else if (clab->pin == GLOBAL) {
+ if (tmplist == NULL) {
+ tmplist = &newlist;
+ tmplist->net.id = globalmax() - 1;
+ }
+ addglobalpin(cschem, cinst, clab, tmplist);
+ addpin(cschem, labinst, clab, tmplist);
+ if (netlist != NULL)
+ mergenets(pschem, netlist, tmplist);
+ }
+ }
+ }
+ }
+
+ /* Part 3: Polygon enumeration */
+ /* Assign network numbers to all polygons in the object. */
+ /* (Ignore symbols, as we only consider pins on symbols) */
+ /* Where multiple pins occur at a point (bus notation), */
+ /* polygons will be duplicated in each network. */
+
+ if ((!visited) && (cschem->schemtype == PRIMARY ||
+ cschem->schemtype == SECONDARY ||
+ (cschem->schemtype == SYMBOL && cschem->symschem == NULL))) {
+
+ for (i = 0; i < old_parts; i++) {
+ cgen = cschem->plist + i;
+ if (IS_POLYGON(*cgen)) {
+ cpoly = TOPOLY(cgen);
+
+ /* Ignore non-network (closed, bbox, filled) polygons */
+ if (nonnetwork(cpoly)) continue;
+
+ resolved_net = (Genericlist *)NULL;
+
+ /* Check for attachment of each segment of this polygon */
+ /* to position of every recorded pin label. */
+
+ for (lseek = pschem->labels; lseek != NULL; lseek = lseek->next) {
+ if (lseek->cschem != cschem) continue;
+ else if ((lseek->cinst != NULL) && (lseek->cinst != cinst))
+ continue;
+ olabel = lseek->label;
+ tmplist = (Genericlist *)lseek;
+ for (endpt = cpoly->points; endpt < cpoly->points
+ + EndPoint(cpoly->number); endpt++) {
+ endpt2 = endpt + NextPoint(cpoly->number);
+ if (onsegment(endpt, endpt2, &olabel->position)) {
+
+ if (resolved_net != NULL) {
+ if (mergenets(pschem, resolved_net, tmplist))
+ resolved_net = tmplist;
+ }
+ if (resolved_net == NULL) {
+ addpoly(cschem, cpoly, tmplist);
+ resolved_net = tmplist;
+ }
+ }
+ }
+ /* if we've encountered a unique instance, then con- */
+ /* tinue past all other instances using this label. */
+ if (lseek->cinst != NULL)
+ while (lseek->next && (lseek->next->label == lseek->label))
+ lseek = lseek->next;
+ }
+
+ /* Check for attachment of each segment of this polygon */
+ /* to endpoints of every recorded network polygon. */
+
+ for (plist = pschem->polygons; plist != NULL; plist = plist->next) {
+ if (plist->cschem != cschem) continue;
+ else if ((tpoly = plist->poly) == cpoly) continue;
+ tpt = tpoly->points;
+ tpt2 = tpoly->points + tpoly->number - 1;
+ tmplist = (Genericlist *)plist;
+
+ for (endpt = cpoly->points; endpt < cpoly->points
+ + EndPoint(cpoly->number); endpt++) {
+ endpt2 = endpt + NextPoint(cpoly->number);
+
+ if (onsegment(endpt, endpt2, tpt) ||
+ onsegment(endpt, endpt2, tpt2)) {
+
+ /* Nets previously counted distinct have */
+ /* been connected together by this polygon. */
+ if (resolved_net != NULL) {
+ if (mergenets(pschem, resolved_net, tmplist))
+ resolved_net = tmplist;
+ }
+ if (resolved_net == NULL) {
+ addpoly(cschem, cpoly, tmplist);
+ resolved_net = tmplist;
+ }
+ }
+ }
+
+ /* Check for attachment of the endpoints of this polygon */
+ /* to each segment of every recorded network polygon. */
+
+ endpt = cpoly->points;
+ endpt2 = cpoly->points + cpoly->number - 1;
+ for (tpt = tpoly->points; tpt < tpoly->points
+ + EndPoint(tpoly->number); tpt++) {
+ tpt2 = tpt + NextPoint(tpoly->number);
+
+ if (onsegment(tpt, tpt2, endpt) ||
+ onsegment(tpt, tpt2, endpt2)) {
+
+ /* Nets previously counted distinct have */
+ /* been connected together by this polygon. */
+ if (resolved_net != 0) {
+ if (mergenets(pschem, resolved_net, tmplist))
+ resolved_net = tmplist;
+ }
+ if (resolved_net == 0) {
+ addpoly(cschem, cpoly, tmplist);
+ resolved_net = tmplist;
+ }
+ }
+ }
+ }
+ if (resolved_net == 0) {
+
+ /* This polygon belongs to an unvisited */
+ /* network. Give this polygon a new net */
+ /* number and add to the net list. */
+
+ newlist.net.id = nextnet++;
+ addpoly(cschem, cpoly, &newlist);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Search a sibling of object instance "cinst" for connections */
+/* between the two. Recurse through the schematic hierarchy of */
+/* the sibling object. */
+/*--------------------------------------------------------------*/
+
+void search_on_siblings(objinstptr cinst, objinstptr isib, pushlistptr schemtop,
+ short llx, short lly, short urx, short ury)
+{
+ XPoint *tmppts, sbbox[2];
+ int i;
+ labelptr olabel;
+ polyptr tpoly;
+ PolylistPtr pseek;
+ LabellistPtr lseek;
+
+ genericptr *iseek;
+ objinstptr subsibinst;
+ pushlistptr psearch, newlist;
+ objectptr sibling = isib->thisobject;
+
+ tmppts = (XPoint *)malloc(sizeof(XPoint));
+
+ /* If the sibling is a symbol or fundamental or trivial object, then */
+ /* we just look at pin labels from the parts list and return. */
+
+ if (sibling->symschem != NULL || sibling->schemtype == FUNDAMENTAL
+ || sibling->schemtype == TRIVIAL) {
+ for (lseek = sibling->labels; lseek != NULL; lseek = lseek->next) {
+ olabel = lseek->label;
+
+ tmppts = (XPoint *)realloc(tmppts, sizeof(XPoint));
+ UTransformPoints(&(olabel->position), tmppts, 1,
+ isib->position, isib->scale, isib->rotation);
+
+ /* Transform all the way up to the level above cinst */
+ for (psearch = schemtop; psearch != NULL; psearch = psearch->next) {
+ subsibinst = psearch->thisinst;
+ UTransformPoints(tmppts, tmppts, 1, subsibinst->position,
+ subsibinst->scale, subsibinst->rotation);
+ }
+ searchconnect(tmppts, 1, cinst, lseek->subnets);
+ }
+ }
+
+ /* If the sibling is a schematic, we look at connections to pins and */
+ /* polygons, and recursively search subschematics of the sibling. */
+
+ else {
+
+ /* Look for pins connecting to pins in the object */
+
+ for (lseek = sibling->labels; lseek != NULL; lseek = lseek->next) {
+ olabel = lseek->label;
+ tmppts = (XPoint *)realloc(tmppts, sizeof(XPoint));
+ UTransformPoints(&(olabel->position), tmppts, 1,
+ isib->position, isib->scale, isib->rotation);
+
+ /* Transform all the way up to the level above cinst */
+ for (psearch = schemtop; psearch != NULL; psearch = psearch->next) {
+ subsibinst = psearch->thisinst;
+ UTransformPoints(tmppts, tmppts, 1, subsibinst->position,
+ subsibinst->scale, subsibinst->rotation);
+ }
+ searchconnect(tmppts, 1, cinst, lseek->subnets);
+ }
+
+ /* Look for polygon ends connecting into the object */
+
+ for (pseek = sibling->polygons; pseek != NULL; pseek = pseek->next) {
+ tpoly = pseek->poly;
+ tmppts = (XPoint *)realloc(tmppts, tpoly->number * sizeof(XPoint));
+ UTransformPoints(tpoly->points, tmppts, tpoly->number,
+ isib->position, isib->scale, isib->rotation);
+
+ /* Transform all the way up to the level above cinst */
+ for (psearch = schemtop; psearch != NULL; psearch = psearch->next) {
+ subsibinst = psearch->thisinst;
+ UTransformPoints(tmppts, tmppts, tpoly->number, subsibinst->position,
+ subsibinst->scale, subsibinst->rotation);
+ }
+ searchconnect(tmppts, tpoly->number, cinst, pseek->subnets);
+ }
+
+ /* Recursively search all schematic children of the sibling */
+
+ for (i = 0; i < sibling->parts; i++) {
+ iseek = sibling->plist + i;
+ if (IS_OBJINST(*iseek)) {
+
+ /* objinstptr iinst = (objinstptr)iseek; (jdk) */
+
+ /* Don't search this instance unless the bounding box */
+ /* overlaps the bounding box of the calling object. */
+
+ calcinstbbox(iseek, &sbbox[0].x, &sbbox[0].y, &sbbox[1].x, &sbbox[1].y);
+ for (psearch = schemtop; psearch != NULL; psearch = psearch->next) {
+ subsibinst = psearch->thisinst;
+ UTransformPoints(sbbox, sbbox, 2, subsibinst->position,
+ subsibinst->scale, subsibinst->rotation);
+ }
+ if ((llx > sbbox[1].x) || (urx < sbbox[0].x) || (lly > sbbox[1].y)
+ || (ury < sbbox[0].y))
+ continue;
+
+ subsibinst = TOOBJINST(iseek);
+
+ /* push stack */
+ newlist = (pushlistptr)malloc(sizeof(pushlist));
+ newlist->thisinst = isib;
+ newlist->next = schemtop;
+ schemtop = newlist;
+
+ search_on_siblings(cinst, subsibinst, schemtop, llx, lly, urx, ury);
+
+ /* pop stack */
+
+ newlist = schemtop;
+ schemtop = schemtop->next;
+ free(newlist);
+ }
+ }
+ }
+ free(tmppts);
+}
+
+/*--------------------------------------------------------------*/
+/* Generate ports from pin labels for all objects: */
+/* For each pin-label in the subcircuit or symbol, generate */
+/* a port in the object or instance's object. */
+/* Translate the pin position to the level above and search */
+/* for & link in any connecting nets. */
+/* */
+/* Generate calls to object instances. */
+/* Pick up any other nets which might be formed by */
+/* juxtaposition of object instances on different levels of the */
+/* schematic hierarchy (e.g., pin-to-pin connections). */
+/*--------------------------------------------------------------*/
+
+void gencalls(objectptr thisobject)
+{
+ genericptr *cgen, *iseek;
+ Matrix locctm;
+ objinstptr cinst, isib, callinst;
+ objectptr callobj, callsymb, cschem, pschem;
+ XPoint xpos;
+ short ibllx, iblly, iburx, ibury, sbllx, sblly, sburx, sbury;
+ int i, j, k; /* , lbus; (jdk) */
+ /* buslist *sbus; (jdk) */
+ labelptr olabel;
+ polyptr tpoly;
+ PolylistPtr pseek;
+ /* CalllistPtr cseek; (jdk) */
+ LabellistPtr lseek;
+ Genericlist *netfrom, *netto; /* , *othernet; (jdk) */
+
+ /* The netlist is always kept in the master schematic */
+ pschem = (thisobject->schemtype == SECONDARY) ? thisobject->symschem :
+ thisobject;
+
+ pschem->traversed = True; /* This object has been dealt with */
+ pschem->valid = True; /* This object has a valid netlist */
+
+ /* We start the loop for schematics but will modify the loop */
+ /* variable to execute just once in the case of a symbol. */
+ /* (see gennetlist(), where the same thing is done) */
+
+ for (j = 0; j < xobjs.pages; j++) {
+ if (pschem->schemtype != PRIMARY) {
+ j = xobjs.pages;
+ cschem = thisobject;
+ }
+ else {
+ cinst = xobjs.pagelist[j]->pageinst;
+ if ((cinst == NULL) ||
+ ((cinst->thisobject != pschem) &&
+ ((cinst->thisobject->schemtype != SECONDARY) ||
+ (cinst->thisobject->symschem != pschem)))) continue;
+ cschem = cinst->thisobject;
+ }
+
+ for (i = 0; i < cschem->parts; i++) {
+ cgen = cschem->plist + i;
+ if (IS_OBJINST(*cgen)) {
+ callinst = TOOBJINST(cgen);
+
+ /* Determine where the hierarchy continues downward */
+
+ if (callinst->thisobject->symschem != NULL)
+ callobj = callinst->thisobject->symschem;
+ else
+ callobj = callinst->thisobject;
+
+ /* Ignore any object on its own schematic */
+
+ if (callobj == pschem) continue;
+
+ callsymb = callinst->thisobject;
+
+ /* Note: callobj is the next schematic in the hierarchy. */
+ /* callsymb is the next visible object in the hierarchy, */
+ /* which may be either a schematic or a symbol. */
+
+ /*-------------------------------------------------------------*/
+ /* For object instances which are their own schematics (i.e., */
+ /* have netlist elements), don't rely on any pin list but make */
+ /* a survey of how polygons connect into the object. */
+ /*-------------------------------------------------------------*/
+
+ if (callsymb->symschem == NULL
+ && callobj->schemtype != FUNDAMENTAL
+ && callobj->schemtype != TRIVIAL) {
+
+ /* Fprintf(stdout, "*** Analyzing connections from %s"
+ " to instance of %s\n", cschem->name,
+ callinst->thisobject->name); */
+
+ /* Look for pins connecting to pins in the object */
+
+ for (lseek = pschem->labels; lseek != NULL; lseek = lseek->next) {
+ if (lseek->cschem != cschem) continue;
+ else if ((lseek->cinst != NULL) && (lseek->cinst != callinst))
+ continue;
+ olabel = lseek->label;
+ searchconnect(&(olabel->position), 1, callinst, lseek->subnets);
+ /* if we've encountered a unique instance, then con- */
+ /* tinue past all other instances using this label. */
+ if (lseek->cinst != NULL)
+ while (lseek->next && (lseek->next->label == lseek->label))
+ lseek = lseek->next;
+ }
+
+ /* Look for polygon ends connecting into the object */
+
+ for (pseek = pschem->polygons; pseek != NULL; pseek = pseek->next) {
+ if (pseek->cschem != cschem) continue;
+ tpoly = pseek->poly;
+ searchconnect(tpoly->points, tpoly->number, callinst, pseek->subnets);
+ }
+
+ /* For each call to a schematic or symbol which is NOT the */
+ /* one under consideration, see if it touches or overlaps */
+ /* the object under consideration. Search for connections */
+ /* between the two objects. */
+
+ calcinstbbox(cgen, &ibllx, &iblly, &iburx, &ibury);
+
+ /* Only need to look forward from the current position. */
+ for (k = i + 1; k < cschem->parts; k++) {
+
+ iseek = cschem->plist + k;
+ if (IS_OBJINST(*iseek)) {
+ calcinstbbox(iseek, &sbllx, &sblly, &sburx, &sbury);
+
+ /* Check intersection of the two object instances; */
+ /* don't do a search if they are disjoint. */
+
+ if ((ibllx <= sburx) && (iburx >= sbllx) &&
+ (iblly <= sbury) && (ibury >= sblly)) {
+ isib = TOOBJINST(iseek);
+ search_on_siblings(callinst, isib, NULL,
+ ibllx, iblly, iburx, ibury);
+ }
+ }
+ }
+ }
+
+ /*----------------------------------------------------------*/
+ /* Recursively call gencalls() on the schematic. */
+ /*----------------------------------------------------------*/
+
+ if (callobj->traversed == False)
+ gencalls(callobj);
+
+ /*----------------------------------------------------------*/
+ /* Create a call to the object callsymb from object cschem */
+ /*----------------------------------------------------------*/
+
+ addcall(cschem, callobj, callinst);
+
+ /*----------------------------------------------------------*/
+ /* Search again on symbol pins to generate calls to ports. */
+ /*----------------------------------------------------------*/
+
+ UResetCTM(&locctm);
+ UPreMultCTM(&locctm, callinst->position, callinst->scale,
+ callinst->rotation);
+
+ for (lseek = callsymb->labels; lseek != NULL; lseek = lseek->next) {
+ /* LabellistPtr slab; (jdk) */
+ /* labelptr slabel; (jdk) */
+
+ if (lseek->cschem != callsymb) continue;
+ else if ((lseek->cinst != NULL) && (lseek->cinst != callinst))
+ continue;
+
+ olabel = lseek->label;
+ netto = (Genericlist *)lseek;
+
+ /* Translate pin position back to object cschem */
+ UTransformbyCTM(&locctm, &(olabel->position), &xpos, 1);
+
+ /* What net in the calling object connects to this point? */
+ netfrom = pointtonet(cschem, callinst, &xpos);
+
+ /* If there's no net, we make one */
+ if (netfrom == NULL)
+ netfrom = make_tmp_pin(cschem, callinst, &xpos, netto);
+
+ /* Generate a port call for a global signal if the */
+ /* global label appears in the symbol (9/29/04). This */
+ /* is a change from previous behavior, which was to not */
+ /* make the call. */
+
+ if ((netto->subnets == 0) && (netto->net.id < 0))
+ mergenets(pschem, netfrom, netto);
+
+ /* Attempt to generate a port in the object. */
+ addport(callobj, netto);
+
+ /* Generate the call to the port */
+ if (addportcall(pschem, netfrom, netto) == FALSE) {
+
+ // If object is "dot" then copy the bus from the
+ // net to the dot. The dot takes on whatever
+ // dimension the bus is.
+
+ if (strstr(callobj->name, "::dot") != NULL) {
+ copy_bus(netto, netfrom);
+ }
+ else {
+ Fprintf(stderr, "Error: attempt to connect bus size "
+ "%d in %s to bus size %d in %s\n",
+ netfrom->subnets, cschem->name,
+ netto->subnets, callobj->name);
+ }
+ }
+
+ /* if we've encountered a unique instance, then continue */
+ /* past all other instances using this label. */
+ if (lseek->cinst != NULL)
+ while (lseek->next && (lseek->next->label == lseek->label))
+ lseek = lseek->next;
+ }
+
+ /*----------------------------------------------------------*/
+ /* If after all that, no ports were called, then remove the */
+ /* call to this object instance. However, we should check */
+ /* for info labels, because the device may produce output */
+ /* for the netlist even if it has no declared ports. This */
+ /* is irrespective of the presence of pin labels---if the */
+ /* symbol is "trivial", the netlist connections are */
+ /* resolved in the level of the hierarchy above, and there */
+ /* may be no ports, but the call list must retain the call */
+ /* to ensure that the netlist output is generated. */
+ /*----------------------------------------------------------*/
+
+ if (pschem->calls->ports == NULL) {
+
+ for (k = 0; k < callsymb->parts; k++) {
+ genericptr *pgen;
+ labelptr plab;
+
+ pgen = callsymb->plist + k;
+ if (IS_LABEL(*pgen)) {
+ plab = TOLABEL(pgen);
+ if (plab->pin == INFO)
+ break;
+ }
+ }
+ if (k == callsymb->parts) /* No info labels: */
+ removecall(pschem, pschem->calls); /* Remove the call */
+ }
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate a net number down in the calling hierarchy */
+/*----------------------------------------------------------------------*/
+
+int translatedown(int rnet, int portid, objectptr nextobj)
+{
+ PortlistPtr nport;
+ int downnet = 0;
+
+ for (nport = nextobj->ports; nport != NULL; nport = nport->next) {
+ if (nport->portid == portid) {
+ downnet = nport->netid;
+ break;
+ }
+ }
+ return downnet;
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate a netlist up in the calling hierarchy */
+/* */
+/* This routine creates a new netlist header which needs to be freed */
+/* by the calling routine. */
+/* */
+/* Note that if the entire netlist cannot be translated up, then the */
+/* routine returns NULL. This could be modified to return the part of */
+/* the network that can be translated up. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *translateup(Genericlist *rlist, objectptr thisobj,
+ objectptr nextobj, objinstptr nextinst)
+{
+ PortlistPtr nport;
+ CalllistPtr ccall;
+ int portid = 0;
+ int upnet = 0;
+ int rnet, lbus;
+ buslist *sbus;
+ Genericlist *tmplist;
+
+ tmplist = (Genericlist *)malloc(sizeof(Genericlist));
+ tmplist->subnets = 0;
+ tmplist->net.id = 0;
+ copy_bus(tmplist, rlist);
+
+ for (lbus = 0;; ) {
+ if (rlist->subnets == 0)
+ rnet = rlist->net.id;
+ else {
+ sbus = rlist->net.list + lbus;
+ rnet = sbus->netid;
+ }
+ for (nport = nextobj->ports; nport != NULL; nport = nport->next) {
+ if (nport->netid == rnet) {
+ portid = nport->portid;
+ break;
+ }
+ }
+
+ upnet = 0;
+ for (ccall = thisobj->calls; ccall != NULL; ccall = ccall->next) {
+ if (ccall->callinst == nextinst) {
+ for (nport = ccall->ports; nport != NULL; nport = nport->next) {
+ if (nport->portid == portid) {
+ upnet = nport->netid;
+ break;
+ }
+ }
+ if (nport != NULL) break;
+ }
+ }
+ if (upnet == 0) {
+ freegenlist(tmplist);
+ return NULL;
+ }
+ else {
+ if (tmplist->subnets == 0) {
+ tmplist->net.id = upnet;
+ }
+ else {
+ sbus = tmplist->net.list + lbus;
+ sbus->netid = upnet;
+ sbus->subnetid = getsubnet(upnet, thisobj);
+ }
+ }
+ if (++lbus >= rlist->subnets) break;
+ }
+ return tmplist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Check whether the indicated polygon is already resolved into the */
+/* netlist of the object hierarchy described by seltop. */
+/* Return the netlist if resolved, NULL otherwise. The netlist */
+/* returned is referred (translated) upward through the calling */
+/* hierarchy to the topmost object containing that net or those nets. */
+/* This topmost object is returned in parameter topobj. */
+/* Note that the netlist returned does not necessarily correspond to */
+/* any object in the top level. It is allocated and must be freed by */
+/* the calling routine. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *is_resolved(genericptr *rgen, pushlistptr seltop, objectptr *topobj)
+{
+ objectptr thisobj = seltop->thisinst->thisobject;
+ objectptr pschem;
+ PolylistPtr pseek;
+ LabellistPtr lseek;
+ Genericlist *rlist = NULL, *newlist;
+
+ pschem = (thisobj->schemtype == SECONDARY) ? thisobj->symschem : thisobj;
+
+ /* Recursively call self, since we have to back out from the bottom of */
+ /* the stack. */
+
+ if (seltop->next != NULL) {
+ rlist = is_resolved(rgen, seltop->next, topobj);
+
+ /* Translate network ID up the hierarchy to the topmost object in which */
+ /* the network exists. */
+
+ if (rlist != NULL) {
+ newlist = translateup(rlist, pschem, seltop->next->thisinst->thisobject,
+ seltop->next->thisinst);
+ if (newlist == NULL)
+ /* Net does not exist upwards of this object. Pass net ID */
+ /* upward with "topobj" unchanged. */
+ return rlist;
+ else {
+ freegenlist(rlist);
+ rlist = newlist;
+ }
+ }
+ }
+ else {
+
+ /* Find the net ID for the listed object, which should be in the object */
+ /* on the bottom of the pushlist stack. */
+
+ if (IS_POLYGON(*rgen)) {
+ for (pseek = pschem->polygons; pseek != NULL; pseek = pseek->next) {
+ if (pseek->poly == TOPOLY(rgen)) {
+ rlist = (Genericlist *)pseek;
+ break;
+ }
+ }
+ }
+ else if (IS_LABEL(*rgen)) {
+ for (lseek = pschem->labels; lseek != NULL; lseek = lseek->next) {
+ if (lseek->label == TOLABEL(rgen)) {
+ rlist = (Genericlist *)lseek;
+ break;
+ }
+ }
+ }
+
+ if (rlist != NULL) {
+ /* Make a copy of the netlist header from this element */
+ newlist = (Genericlist *)malloc(sizeof(Genericlist));
+ newlist->subnets = 0;
+ copy_bus(newlist, rlist);
+ rlist = newlist;
+ }
+ }
+
+ /* done: (jdk) */
+ *topobj = (rlist == NULL) ? NULL : seltop->thisinst->thisobject;
+ return rlist;
+}
+
+/*--------------------------------------------------------------*/
+/* Highlight all the polygons and pin labels in a network */
+/* (recursively, downward). Pin labels are drawn only on the */
+/* topmost schematic object. */
+/* Returns true if some part of the hierarchy declared a net to */
+/* be highlighted. */
+/* mode = 1 highlight, mode = 0 erase */
+/*--------------------------------------------------------------*/
+
+Boolean highlightnet(objectptr cschem, objinstptr cinst, int netid, u_char mode)
+{
+ CalllistPtr calls;
+ PortlistPtr ports;
+ PolylistPtr plist;
+ LabellistPtr llist;
+ polyptr cpoly;
+ labelptr clabel;
+ objinstptr ccinst;
+ int netto, locnetid, lbus;
+ int curcolor = AUXCOLOR;
+ Boolean rval = FALSE;
+ objectptr pschem;
+
+ XcSetFunction(GXcopy);
+ XSetForeground(dpy, areawin->gc, curcolor);
+
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ for (plist = pschem->polygons; plist != NULL; plist = plist->next) {
+ if (plist->cschem != cschem) continue;
+ cpoly = plist->poly;
+ for (lbus = 0;;) {
+ if (plist->subnets == 0)
+ locnetid = plist->net.id;
+ else
+ locnetid = (plist->net.list + lbus)->netid;
+ if (locnetid == netid) {
+ /* Fprintf(stdout, " >> Found polygon belonging to net %d at (%d, %d)\n",
+ locnetid, cpoly->points[0].x, cpoly->points[0].y); */
+ if (mode == 0 && cpoly->color != curcolor) {
+ curcolor = cpoly->color;
+ XTopSetForeground(curcolor);
+ }
+ UDrawPolygon(cpoly, xobjs.pagelist[areawin->page]->wirewidth);
+ break;
+ }
+ if (++lbus >= plist->subnets) break;
+ }
+ }
+
+ /* Highlight labels if they belong to the top-level object */
+
+ if (cschem == topobject) {
+ for (llist = pschem->labels; llist != NULL; llist = llist->next) {
+ if (llist->cschem != cschem) continue;
+ else if ((llist->cinst != NULL) && (llist->cinst != cinst)) continue;
+ clabel = llist->label;
+ for (lbus = 0;;) {
+ if (llist->subnets == 0)
+ locnetid = llist->net.id;
+ else
+ locnetid = (llist->net.list + lbus)->netid;
+ if (locnetid == netid) {
+ if (clabel->string->type == FONT_NAME) { /* don't draw temp labels */
+ if ((mode == 0) && (clabel->color != curcolor)) {
+ curcolor = clabel->color;
+ UDrawString(clabel, curcolor, cinst);
+ }
+ else
+ UDrawString(clabel, DOFORALL, cinst);
+ /* Fprintf(stdout, " >> Found label belonging to net "
+ "%d at (%d, %d)\n",
+ locnetid, clabel->position.x,
+ clabel->position.y); */
+
+ }
+ break;
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ /* if we've encountered a unique instance, then continue */
+ /* past all other instances using this label. */
+ if (llist->cinst != NULL)
+ while (llist->next && (llist->next->label == llist->label))
+ llist = llist->next;
+ }
+
+ /* Highlight all pins connecting this net to symbols */
+
+ }
+
+ /* Connectivity recursion */
+
+ for (calls = pschem->calls; calls != NULL; calls = calls->next) {
+ if (calls->cschem != cschem) continue;
+ for (ports = calls->ports; ports != NULL; ports = ports->next) {
+ if (ports->netid == netid) {
+ ccinst = calls->callinst;
+
+ /* Recurse only on objects for which network polygons are visible */
+ /* from the calling object: i.e., non-trivial, non-fundamental */
+ /* objects acting as their own schematics. */
+
+ UPushCTM();
+ UPreMultCTM(DCTM, ccinst->position, ccinst->scale, ccinst->rotation);
+
+ if (ccinst->thisobject->symschem == NULL &&
+ ccinst->thisobject->schemtype != FUNDAMENTAL &&
+ ccinst->thisobject->schemtype != TRIVIAL) {
+
+ netto = translatedown(netid, ports->portid, calls->callobj);
+
+ /* Fprintf(stdout, " > Calling object %s at (%d, %d)\n",
+ calls->callobj->name, ccinst->position.x, ccinst->position.y); */
+ /* Fprintf(stdout, " > Net translation from %d to %d (port %d)\n",
+ netid, netto, ports->portid); */
+
+ if (highlightnet(calls->callobj, calls->callinst, netto, mode))
+ rval = TRUE;
+ }
+ else {
+ /* Otherwise (symbols, fundamental, trivial, etc., objects), we */
+ /* highlight the pin position of the port. */
+ if ((clabel = PortToLabel(ccinst, ports->portid)))
+ UDrawXDown(clabel);
+ }
+ UPopCTM();
+ }
+ }
+ }
+ return rval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Highlight whatever nets are listed in the current object instance, */
+/* if any. */
+/*----------------------------------------------------------------------*/
+
+void highlightnetlist(objectptr nettop, objinstptr cinst, u_char mode)
+{
+ int lbus, netid;
+ buslist *sbus;
+ Genericlist *netlist = cinst->thisobject->highlight.netlist;
+ objinstptr nextinst = cinst->thisobject->highlight.thisinst;
+
+ if (netlist == NULL) return;
+
+ for (lbus = 0;; ) {
+ if (netlist->subnets == 0)
+ netid = netlist->net.id;
+ else {
+ sbus = netlist->net.list + lbus;
+ netid = sbus->netid;
+ }
+ highlightnet(nettop, nextinst, netid, mode);
+ if (++lbus >= netlist->subnets) break;
+ }
+
+ /* If we are erasing, remove the netlist entry from the object */
+ if (mode == (u_char)0) {
+ freegenlist(netlist);
+ cinst->thisobject->highlight.netlist = NULL;
+ cinst->thisobject->highlight.thisinst = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Push the matrix stack for each object (instance) until the indicated */
+/* object is reached. This works similarly to highlightnet() above, */
+/* but makes calls according to the hierarchy described by the */
+/* pushlistptr parameter. */
+/* Returns the number of stack objects to pop after we're done. */
+/*----------------------------------------------------------------------*/
+
+int pushnetwork(pushlistptr seltop, objectptr nettop)
+{
+ pushlistptr cursel = seltop;
+ objinstptr sinst;
+ int rno = 0;
+
+ while ((cursel->thisinst->thisobject != nettop) && (cursel->next != NULL)) {
+ cursel = cursel->next;
+ sinst = cursel->thisinst;
+ UPushCTM();
+ UPreMultCTM(DCTM, sinst->position, sinst->scale, sinst->rotation);
+ rno++;
+ }
+
+ if (cursel->thisinst->thisobject != nettop) {
+ Fprintf(stderr, "Error: object does not exist in calling stack!\n");
+ rno = 0;
+ }
+
+ return rno;
+}
+
+/*----------------------------------------------------------------------*/
+/* Determine if two netlists match. If "mode" is MATCH_EXACT, the */
+/* net numbers and subnet numbers must all be the same. If */
+/* MATCH_SUBNETS, then the subnet numbers must be the same. If */
+/* MATCH_SIZE, then they need only have the same number of subnets. */
+/*----------------------------------------------------------------------*/
+
+Boolean match_buses(Genericlist *list1, Genericlist *list2, int mode)
+{
+ int i;
+ buslist *bus1, *bus2;
+
+ if (list1->subnets != list2->subnets) {
+ // A wire (no subnets) matches a bus of 1 subnet. All others
+ // are non-matching.
+
+ if (list1->subnets != 0 && list2->subnets != 0)
+ return FALSE;
+ else if (list1->subnets != 1 && list2->subnets != 1)
+ return FALSE;
+ }
+
+ if (mode == MATCH_SIZE) return TRUE;
+
+ if (list1->subnets == 0) {
+ if (mode == MATCH_SUBNETS) return TRUE;
+ if (list2->subnets != 0) {
+ bus2 = list2->net.list + 0;
+ if (list1->net.id != bus2->netid) return FALSE;
+ }
+ else if (list1->net.id != list2->net.id) return FALSE;
+ }
+ else if (list2->subnets == 0) {
+ if (mode == MATCH_SUBNETS) return TRUE;
+ bus1 = list1->net.list + 0;
+ if (bus1->netid != list2->net.id) return FALSE;
+ }
+ else {
+ for (i = 0; i < list1->subnets; i++) {
+ bus1 = list1->net.list + i;
+ bus2 = list2->net.list + i;
+ /* A subnetid of < 0 indicates an unassigned bus */
+ if ((bus1->subnetid != -1) && (bus1->subnetid != bus2->subnetid))
+ return FALSE;
+ }
+ if (mode == MATCH_SUBNETS) return TRUE;
+
+ for (i = 0; i < list1->subnets; i++) {
+ bus1 = list1->net.list + i;
+ bus2 = list2->net.list + i;
+ if (bus1->netid != bus2->netid)
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Copy the netlist structure from one netlist element to another */
+/*----------------------------------------------------------------------*/
+
+void copy_bus(Genericlist *dest, Genericlist *source)
+{
+ buslist *sbus, *dbus;
+ int i;
+
+ if (dest->subnets > 0)
+ free(dest->net.list);
+
+ dest->subnets = source->subnets;
+ if (source->subnets == 0)
+ dest->net.id = source->net.id;
+ else {
+ dest->net.list = (buslist *)malloc(dest->subnets * sizeof(buslist));
+ for (i = 0; i < dest->subnets; i++) {
+ sbus = source->net.list + i;
+ dbus = dest->net.list + i;
+ dbus->netid = sbus->netid;
+ dbus->subnetid = sbus->subnetid;
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Create a new "temporary" label object for a pin */
+/* This type of label is never drawn, so it doesn't */
+/* need font info. It is identified as "temporary" by */
+/* this lack of a leading font record. */
+/*------------------------------------------------------*/
+
+Genericlist *new_tmp_pin(objectptr cschem, XPoint *pinpt, char *pinstring,
+ char *prefix, Genericlist *netlist)
+{
+ labelptr *newlabel;
+ stringpart *strptr;
+
+ if (pinpt == NULL) {
+ Fprintf(stderr, "NULL label location!\n");
+ return NULL;
+ }
+
+ NEW_LABEL(newlabel, cschem);
+ labeldefaults(*newlabel, LOCAL, pinpt->x, pinpt->y);
+ (*newlabel)->justify = 0;
+ (*newlabel)->color = DEFAULTCOLOR;
+ strptr = (*newlabel)->string;
+ strptr->type = TEXT_STRING;
+ if (pinstring != NULL) {
+ strptr->data.string = (char *)malloc(strlen(pinstring));
+ strcpy(strptr->data.string, pinstring);
+ }
+ else {
+ strptr->data.string = textprintnet(prefix, NULL, netlist);
+ }
+
+ /* Add label to object's netlist and return a pointer to the */
+ /* netlist entry. */
+
+ return (addpin(cschem, NULL, *newlabel, netlist));
+}
+
+/*------------------------------------------------------*/
+/* Create a label for use in the list of global nets. */
+/* This label is like a temporary label (new_tmp_pin) */
+/* except that it is not represented in any object. */
+/* The string contains the verbatim contents of any */
+/* parameter substitutions in the original label. */
+/*------------------------------------------------------*/
+
+labelptr new_global_pin(labelptr clabel, objinstptr cinst)
+{
+ labelptr newlabel;
+
+ newlabel = (labelptr) malloc(sizeof(label));
+ newlabel->type = LABEL;
+ labeldefaults(newlabel, GLOBAL, 0, 0);
+ newlabel->justify = 0;
+ newlabel->color = DEFAULTCOLOR;
+ free(newlabel->string);
+ newlabel->string = stringcopyall(clabel->string, cinst);
+
+ /* Add label to the global netlist and return a pointer to */
+ /* the netlist entry. */
+
+ return newlabel;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a temporary I/O pin (becomes part of netlist and also part of */
+/* the object itself). */
+/*----------------------------------------------------------------------*/
+
+Genericlist *make_tmp_pin(objectptr cschem, objinstptr cinst, XPoint *pinpt,
+ Genericlist *sublist)
+{
+ LabellistPtr lseek;
+ objectptr pschem;
+ char *pinstring = NULL;
+ /* buslist *sbus; (jdk) */
+ /* int lbus; (jdk) */
+ Genericlist *netlist, *tmplist, newlist;
+
+ newlist.subnets = 0;
+ newlist.net.id = 0;
+
+ /* Primary schematic (contains the netlist) */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ /* Determine a netlist for this pin */
+
+ netlist = pointtonet(cschem, cinst, pinpt);
+ if (netlist == NULL) {
+ newlist.net.id = netmax(pschem) + 1;
+ netlist = &newlist;
+ }
+
+ /* If there is any other pin at this location, don't make another */
+ /* one. If there is already a temporary pin associated with the */
+ /* net, use its name. */
+
+ else {
+ for (lseek = pschem->labels; lseek != NULL; lseek = lseek->next) {
+ if (lseek->cschem != cschem) continue;
+ else if ((lseek->cinst != NULL) && (lseek->cinst != cinst)) continue;
+ tmplist = (Genericlist *)lseek;
+ if (match_buses(netlist, tmplist, MATCH_EXACT)) {
+ if (proximity(&(lseek->label->position), pinpt))
+ return (Genericlist *)lseek;
+ else if (lseek->label->string->type == TEXT_STRING)
+ pinstring = lseek->label->string->data.string;
+ }
+ /* if we've encountered a unique instance, then continue past */
+ /* all other instances using this label. */
+ if (lseek->cinst != NULL)
+ while (lseek->next && (lseek->next->label == lseek->label))
+ lseek = lseek->next;
+ }
+ }
+ return (new_tmp_pin(cschem, pinpt, pinstring, "ext", netlist));
+}
+
+/*--------------------------------------------------------------*/
+/* Search for connections into a non-symbol subcircuit, based */
+/* on various combinations of polygon and pin label overlaps. */
+/*--------------------------------------------------------------*/
+
+int searchconnect(XPoint *points, int number, objinstptr cinst, int subnets)
+{
+ XPoint *tmppts, *tpt, *tpt2, *endpt, *endpt2, *pinpt, opinpt;
+ objinstptr tinst;
+ genericptr *cgen;
+ polyptr tpoly;
+ labelptr tlab;
+ objectptr tobj, cobj = cinst->thisobject;
+ LabellistPtr tseek;
+ PolylistPtr pseek;
+ int i; /* , lbus, sub_bus; (jdk) */
+ int found = 0;
+
+ /* Generate temporary polygon in the coordinate system of */
+ /* the object instance in question */
+
+ tmppts = (XPoint *)malloc(number * sizeof(XPoint));
+ InvTransformPoints(points, tmppts, number,
+ cinst->position, cinst->scale, cinst->rotation);
+ /* Fprintf(stdout, "Info: translated polygon w.r.t. object %s\n", */
+ /* cinst->thisobject->name); */
+
+ /* Recursion on all appropriate sub-schematics. */
+ /* (Use parts list, not call list, as call list may not have created yet) */
+
+ for (i = 0; i < cobj->parts; i++) {
+ cgen = cobj->plist + i;
+ if (IS_OBJINST(*cgen)) {
+ tinst = TOOBJINST(cgen);
+ if (tinst->thisobject->symschem == NULL) {
+ tobj = tinst->thisobject;
+ if (tobj->schemtype != FUNDAMENTAL && tobj->schemtype != TRIVIAL)
+ found += searchconnect(tmppts, number, tinst, subnets);
+ }
+ }
+ }
+
+ for (endpt = tmppts; endpt < tmppts + EndPoint(number); endpt++) {
+ endpt2 = endpt + NextPoint(number);
+ for (i = 0; i < cobj->parts; i++) {
+ cgen = cobj->plist + i;
+ if (!IS_OBJINST(*cgen)) continue;
+ tinst = TOOBJINST(cgen);
+
+ /* Look at the object only (symbol, or schematic if it has no symbol) */
+ tobj = tinst->thisobject;
+
+ /* Search for connections to pin labels */
+
+ for (tseek = tobj->labels; tseek != NULL; tseek = tseek->next) {
+ tlab = tseek->label;
+ UTransformPoints(&(tlab->position), &opinpt, 1, tinst->position,
+ tinst->scale, tinst->rotation);
+ if (onsegment(endpt2, endpt, &opinpt)) {
+ /* Fprintf(stdout, "%s connects to pin %s of %s in %s\n", */
+ /* ((number > 1) ? "Polygon" : "Pin"), */
+ /* tlab->string + 2, tinst->thisobject->name, */
+ /* cinst->thisobject->name); */
+ make_tmp_pin(cobj, cinst, &opinpt, (Genericlist *)tseek);
+ found += (tseek->subnets == 0) ? 1 : tseek->subnets;
+ break;
+ }
+ }
+ }
+
+ for (pseek = cobj->polygons; pseek != NULL; pseek = pseek->next) {
+ tpoly = pseek->poly;
+
+ /* Search for connections from segments passed to this */
+ /* function to endpoints of polygons in the netlist. */
+
+ pinpt = NULL;
+ tpt = tpoly->points;
+ tpt2 = tpoly->points + tpoly->number - 1;
+ if (onsegment(endpt2, endpt, tpt)) pinpt = tpt;
+ if (onsegment(endpt2, endpt, tpt2)) pinpt = tpt2;
+
+ /* Create new pinlabel (only if there is not one already there) */
+
+ if (pinpt != NULL) {
+ make_tmp_pin(cobj, cinst, pinpt, (Genericlist *)pseek);
+ found += (pseek->subnets == 0) ? 1 : pseek->subnets;
+ }
+ }
+ }
+
+ endpt = tmppts;
+ endpt2 = tmppts + EndPoint(number) - 1;
+
+ /* Search for connections from endpoints passed to this */
+ /* function to segments of polygons in the netlist. */
+
+ for (pseek = cobj->polygons; pseek != NULL; pseek = pseek->next) {
+
+ tpoly = pseek->poly;
+ for (tpt = tpoly->points; tpt < tpoly->points
+ + EndPoint(tpoly->number); tpt++) {
+ tpt2 = tpt + NextPoint(tpoly->number);
+
+ pinpt = NULL;
+ if (onsegment(tpt2, tpt, endpt)) pinpt = endpt;
+ if (onsegment(tpt2, tpt, endpt2)) pinpt = endpt2;
+
+ /* Create new pinlabel (only if there is not one already there) */
+
+ if (pinpt != NULL) {
+ make_tmp_pin(cobj, cinst, pinpt, (Genericlist *)pseek);
+ found += (pseek->subnets == 0) ? 1 : pseek->subnets;
+ }
+ }
+ }
+ free(tmppts);
+ return(found);
+}
+
+/*----------------------------------------------------------------------*/
+/* Associate polygon with given netlist and add to the object's list */
+/* of network polygons (i.e., wires). */
+/*----------------------------------------------------------------------*/
+
+Genericlist *addpoly(objectptr cschem, polyptr poly, Genericlist *netlist)
+{
+ PolylistPtr newpoly;
+ objectptr pschem;
+ /* buslist *sbus; (jdk) */
+ /* int lbus, sub_bus; (jdk) */
+
+ /* Netlist is in the master schematic */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ /* If this polygon is already in the list, then add an extra subnet */
+ /* if necessary. */
+
+ for (newpoly = pschem->polygons; newpoly != NULL; newpoly = newpoly->next) {
+ if (newpoly->poly == poly) {
+ if (!match_buses((Genericlist *)newpoly, netlist, MATCH_EXACT)) {
+ Fprintf(stderr, "addpoly: Error in bus assignment\n");
+ return NULL;
+ }
+ return (Genericlist *)newpoly;
+ }
+ }
+
+ /* Create a new entry and link to polygon list of this object */
+
+ newpoly = (PolylistPtr) malloc(sizeof(Polylist));
+ newpoly->cschem = cschem;
+ newpoly->poly = poly;
+ newpoly->subnets = 0;
+ copy_bus((Genericlist *)newpoly, netlist);
+ newpoly->next = pschem->polygons;
+ pschem->polygons = newpoly;
+
+ return (Genericlist *)newpoly;
+}
+
+/*-------------------------------------------------------------------------*/
+
+long zsign(long a, long b)
+{
+ if (a > b) return 1;
+ else if (a < b) return -1;
+ else return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Promote a single net to a bus. The bus size will be equal to the */
+/* value "subnets". */
+/*----------------------------------------------------------------------*/
+
+void promote_net(objectptr cschem, Genericlist *netfrom, int subnets)
+{
+ Genericlist *netref = NULL;
+ CalllistPtr calls;
+ PortlistPtr ports;
+ PolylistPtr plist;
+ LabellistPtr llist;
+ int netid, firstid, lbus; /* curid, (jdk) */
+ buslist *sbus;
+ Boolean foundlabel;
+
+ /* If no promotion is required, don't do anything */
+ if (netfrom->subnets == subnets) return;
+
+ /* It "netfrom" is already a bus, but of different size than */
+ /* subnets, then it cannot be changed. */
+
+ if (netfrom->subnets != 0) {
+ Fprintf(stderr, "Attempt to change the size of a bus!\n");
+ return;
+ }
+
+ netid = netfrom->net.id;
+
+ /* If "subnets" is 1, then "netfrom" can be promoted regardless. */
+ /* Otherwise, if the "netfrom" net is used in any calls, then it */
+ /* cannot be promoted. */
+
+ if (subnets > 1) {
+ for (calls = cschem->calls; calls != NULL; calls = calls->next)
+ for (ports = calls->ports; ports != NULL; ports = ports->next)
+ if (ports->netid == netid) {
+ Fprintf(stderr, "Cannot promote net to bus: Net already connected"
+ " to single-wire port\n");
+ return;
+ }
+ firstid = netmax(cschem) + 1;
+ }
+
+ for (plist = cschem->polygons; plist != NULL; plist = plist->next)
+ if ((plist->subnets == 0) && (plist->net.id == netid)) {
+ plist->subnets = subnets;
+ plist->net.list = (buslist *)malloc(subnets * sizeof(buslist));
+ for (lbus = 0; lbus < subnets; lbus++) {
+ sbus = plist->net.list + lbus;
+ sbus->netid = (lbus == 0) ? netid : firstid + lbus;
+ sbus->subnetid = lbus; /* By default, number from zero */
+ }
+ netref = (Genericlist *)plist;
+ }
+
+ /* It's possible for a label without bus notation to be attached */
+ /* to this net. */
+
+ foundlabel = FALSE;
+ for (llist = cschem->labels; llist != NULL; llist = llist->next)
+ if ((llist->subnets == 0) && (llist->net.id == netid)) {
+ llist->subnets = subnets;
+ llist->net.list = (buslist *)malloc(subnets * sizeof(buslist));
+ for (lbus = 0; lbus < subnets; lbus++) {
+ sbus = llist->net.list + lbus;
+ sbus->netid = (lbus == 0) ? netid : firstid + lbus;
+ sbus->subnetid = lbus; /* By default, number from zero */
+ }
+ netref = (Genericlist *)llist;
+ foundlabel = TRUE;
+ }
+
+ /* We need to create a temp label associated with this net to */
+ /* encompass the promoted bus size. If this bus is later attached */
+ /* to a known bus, that bus name will be canonical. If no bus name */
+ /* is ever assigned to the bus, this temp one will be used. */
+
+ if (!foundlabel) {
+ XPoint *pinpos;
+ pinpos = NetToPosition(netid, cschem);
+ new_tmp_pin(cschem, pinpos, NULL, "int", netref);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Change any part of the netlist "testlist" that matches the net IDs */
+/* of "orignet" to the net IDs of "newnet". It is assumed that the */
+/* lengths and sub-bus numbers of "orignet" and "newnet" match. */
+/*----------------------------------------------------------------------*/
+
+Boolean mergenetlist(objectptr cschem, Genericlist *testlist,
+ Genericlist *orignet, Genericlist *newnet)
+{
+ int obus, onetid, osub, nsub, nnetid, tbus;
+ buslist *sbus;
+ Boolean rval = FALSE;
+
+ for (obus = 0;;) {
+ if (orignet->subnets == 0) {
+ onetid = orignet->net.id;
+ osub = -1;
+ }
+ else {
+ sbus = orignet->net.list + obus;
+ onetid = sbus->netid;
+ osub = sbus->subnetid;
+ }
+
+ if (newnet->subnets == 0) {
+ nnetid = newnet->net.id;
+ nsub = -1;
+ }
+ else {
+ sbus = newnet->net.list + obus;
+ nnetid = sbus->netid;
+ nsub = sbus->subnetid;
+ }
+
+ if (testlist->subnets == 0) {
+ if (testlist->net.id == onetid) {
+ rval = TRUE;
+ if (orignet->subnets == 0) {
+ testlist->net.id = nnetid;
+ return TRUE;
+ }
+ else {
+ /* Promote testlist to a bus subnet of size 1 */
+ testlist->subnets = 1;
+ testlist->net.list = (buslist *)malloc(sizeof(buslist));
+ sbus = testlist->net.list;
+ sbus->netid = nnetid;
+ sbus->subnetid = nsub;
+ return rval;
+ }
+ }
+ }
+
+ for (tbus = 0; tbus < testlist->subnets; tbus++) {
+ /* If the sub-bus numbers match, then change the net */
+ /* ID to the new net number. If the sub-bus is */
+ /* unnamed (has no associated bus-notation label), */
+ /* then it can take on the net and subnet numbers. */
+
+ sbus = testlist->net.list + tbus;
+
+ if (sbus->netid == onetid) {
+ if (sbus->subnetid == osub) {
+ sbus->netid = nnetid;
+ sbus->subnetid = nsub;
+ rval = TRUE;
+ }
+ else {
+ labelptr blab = NetToLabel(nnetid, cschem);
+ if (blab == NULL) {
+ Fprintf(stderr, "Warning: isolated subnet?\n");
+ sbus->netid = nnetid;
+ /* Keep subnetid---but, does newnet need to be promoted? */
+ return TRUE;
+ }
+ else if (blab->string->type != FONT_NAME) {
+ sbus->netid = nnetid;
+ sbus->subnetid = nsub;
+ rval = TRUE;
+ Fprintf(stderr, "Warning: Unexpected subnet value in mergenetlist!\n");
+ }
+ }
+ }
+ }
+ if (++obus >= orignet->subnets) break;
+ }
+ return rval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Combine two networks in an object's linked-list Netlist */
+/* Parameters: cschem - pointer to object containing netlist */
+/* orignet - original netlist to be changed */
+/* newnet - new netlist to be changed to */
+/* */
+/* Attempts to merge different subnets in a bus are thwarted. */
+/*----------------------------------------------------------------------*/
+
+Boolean netmerge(objectptr cschem, Genericlist *orignet, Genericlist *newnet)
+{
+ PolylistPtr plist;
+ LabellistPtr llist;
+ CalllistPtr calls;
+ PortlistPtr ports;
+ Genericlist savenet;
+ int i, net;
+ buslist *obus, *nbus;
+ Boolean rval;
+
+ /* Trivial case; do nothing */
+ if (match_buses(orignet, newnet, MATCH_EXACT)) return TRUE;
+
+ /* Disallow an attempt to convert a global net to a local net: */
+ /* The global net ID always dominates! */
+
+ if ((orignet->subnets == 0) && (newnet->subnets == 0) &&
+ (orignet->net.id < 0) && (newnet->net.id > 0)) {
+ int globnet = orignet->net.id;
+ orignet->net.id = newnet->net.id;
+ newnet->net.id = globnet;
+ }
+
+ /* Check that the lists of changes are compatible. It appears to be */
+ /* okay to have non-matching buses (although they should not be */
+ /* merged), as this is a valid style in which buses do not have taps */
+ /* but the sub-buses are explicitly called out with labels. In such */
+ /* case, the polygons of different sub-buses touch, and this routine */
+ /* rejects them as being incompatible. */
+
+ if (!match_buses(orignet, newnet, MATCH_SUBNETS)) {
+ if (match_buses(orignet, newnet, MATCH_SIZE)) {
+ labelptr nlab;
+ /* If only the subnet numbers don't match up, check if */
+ /* "orignet" has a temp label. */
+ nbus = orignet->net.list;
+ if ((nlab = NetToLabel(nbus->netid, cschem)) != NULL) {
+ if (nlab->string->type != FONT_NAME)
+ goto can_merge;
+ }
+ }
+ else
+ Fprintf(stderr, "netmerge warning: non-matching bus subnets touching.\n");
+ return FALSE;
+ }
+
+can_merge:
+
+ /* If orignet is a bus size 1 and newnet is a wire, then promote */
+ /* newnet to a bus size 1. */
+
+ if (orignet->subnets == 1 && newnet->subnets == 0) {
+ net = newnet->net.id;
+ newnet->subnets = 1;
+ newnet->net.list = (buslist *)malloc(sizeof(buslist));
+ obus = orignet->net.list;
+ nbus = newnet->net.list;
+ nbus->subnetid = obus->subnetid;
+ nbus->netid = net;
+ }
+
+ /* Make a copy of the net so we don't overwrite it */
+ savenet.subnets = 0;
+ copy_bus(&savenet, orignet);
+
+ rval = FALSE;
+ for (plist = cschem->polygons; plist != NULL; plist = plist->next)
+ if (mergenetlist(cschem, (Genericlist *)plist, &savenet, newnet))
+ rval = TRUE;
+
+ for (llist = cschem->labels; llist != NULL; llist = llist->next)
+ if (mergenetlist(cschem, (Genericlist *)llist, &savenet, newnet)) {
+ int pinnet;
+ char *newtext;
+ rval = TRUE;
+
+ /* Because nets that have been merged away may be re-used later, */
+ /* change the name of any temporary labels to the new net number */
+
+ if (llist->label->string->type != FONT_NAME) {
+ newtext = llist->label->string->data.string;
+ if (sscanf(newtext + 3, "%d", &pinnet) == 1) {
+ if (pinnet == savenet.net.id) {
+ *(newtext + 3) = '\0';
+ llist->label->string->data.string = textprintnet(newtext,
+ NULL, newnet);
+ free(newtext);
+ }
+ }
+ }
+ }
+
+ if (rval) {
+
+ /* Reflect the net change in the object's call list, if it has one. */
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ for (ports = calls->ports; ports != NULL; ports = ports->next) {
+ if (newnet->subnets == 0) {
+ if (ports->netid == savenet.net.id)
+ ports->netid = newnet->net.id;
+ }
+ else {
+ for (i = 0; i < newnet->subnets; i++) {
+ obus = savenet.net.list + i;
+ nbus = newnet->net.list + i;
+ if (ports->netid == obus->netid)
+ ports->netid = nbus->netid;
+ }
+ }
+ }
+ }
+ }
+
+ /* Free the copy of the bus that we made, if we made one */
+ if (savenet.subnets > 0) free(savenet.net.list);
+
+ return rval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrapper to netmerge() to make sure change is made both to the symbol */
+/* and schematic, if both exist. */
+/*----------------------------------------------------------------------*/
+
+Boolean mergenets(objectptr cschem, Genericlist *orignet, Genericlist *newnet)
+{
+ Boolean merged;
+
+ if (cschem->symschem != NULL)
+ merged = netmerge(cschem->symschem, orignet, newnet);
+ if (netmerge(cschem, orignet, newnet))
+ merged = TRUE;
+
+ return merged;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove a call to an object instance from the call list of cschem */
+/*----------------------------------------------------------------------*/
+
+void removecall(objectptr cschem, CalllistPtr dontcallme)
+{
+ CalllistPtr lastcall, seeklist;
+ PortlistPtr ports, savelist;
+
+ /* find the instance call before this one and link it to the one following */
+
+ lastcall = NULL;
+ for (seeklist = cschem->calls; seeklist != NULL; seeklist = seeklist->next) {
+ if (seeklist == dontcallme)
+ break;
+ lastcall = seeklist;
+ }
+
+ if (seeklist == NULL) {
+ Fprintf(stderr, "Error in removecall(): Call does not exist!\n");
+ return;
+ }
+
+ if (lastcall == NULL)
+ cschem->calls = dontcallme->next;
+ else
+ lastcall->next = dontcallme->next;
+
+ ports = dontcallme->ports;
+ while (ports != NULL) {
+ savelist = ports;
+ ports = ports->next;
+ free (savelist);
+ }
+ free(dontcallme);
+}
+
+/*----------------------------------------------------------------------*/
+/* Add a pin label to the netlist */
+/* If cschem == NULL, add the pin to the list of global pins. */
+/* The new label entry in the netlist gets a copy of the netlist */
+/* "netlist". */
+/*----------------------------------------------------------------------*/
+
+Genericlist *addpin(objectptr cschem, objinstptr cinst, labelptr pin,
+ Genericlist *netlist)
+{
+ LabellistPtr srchlab, newlabel, lastlabel = NULL;
+ objectptr pschem;
+ /* buslist *sbus; (jdk) */
+ /* int lbus, sub_bus; (jdk) */
+
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ for (srchlab = pschem->labels; srchlab != NULL; srchlab = srchlab->next) {
+ if (srchlab->label == pin) {
+ if (!match_buses(netlist, (Genericlist *)srchlab, MATCH_EXACT)) {
+ if (srchlab->cinst == cinst) {
+ Fprintf(stderr, "addpin: Error in bus assignment\n");
+ return NULL;
+ }
+ }
+ else if (srchlab->cinst == NULL)
+ return (Genericlist *)srchlab;
+ break; /* Stop at the first record for this label */
+ }
+ lastlabel = srchlab;
+ }
+
+ /* Create a new entry and link to label list of the object */
+
+ newlabel = (LabellistPtr) malloc(sizeof(Labellist));
+ newlabel->cschem = cschem;
+ newlabel->cinst = cinst;
+ newlabel->label = pin;
+ newlabel->subnets = 0;
+ copy_bus((Genericlist *)newlabel, netlist);
+
+ /* Always put the specific (instanced) cases in front of */
+ /* generic cases for the same label. */
+
+ /* Generic case---make it the last record for this label */
+ if ((cinst == NULL) && (lastlabel != NULL)) {
+ while ((srchlab != NULL) && (srchlab->label == pin)) {
+ lastlabel = srchlab;
+ srchlab = srchlab->next;
+ }
+ }
+ if (lastlabel != NULL) {
+ newlabel->next = srchlab;
+ lastlabel->next = newlabel;
+ }
+ else {
+ newlabel->next = pschem->labels;
+ pschem->labels = newlabel;
+ }
+ return (Genericlist *)newlabel;
+}
+
+/*----------------------------------------------------------------------*/
+/* Add a pin label to the list of global net names. */
+/* The new label entry in the netlist gets a copy of the netlist */
+/* "netlist" and a copy of label "pin" containing the *instance* value */
+/* of the text. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *addglobalpin(objectptr cschem, objinstptr cinst, labelptr pin,
+ Genericlist *netlist)
+{
+ LabellistPtr srchlab, newlabel, lastlabel = NULL;
+
+ if (cinst == NULL) {
+ Fprintf(stderr, "Error: Global pin does not have an associated instance!\n");
+ return NULL;
+ }
+
+ for (srchlab = global_labels; srchlab != NULL; srchlab = srchlab->next) {
+ if (srchlab->label == pin) {
+ if (!match_buses(netlist, (Genericlist *)srchlab, MATCH_EXACT)) {
+ if (srchlab->cinst == cinst) {
+ Fprintf(stderr, "addglobalpin: Error in bus assignment\n");
+ return NULL;
+ }
+ }
+ else if (srchlab->cinst == NULL)
+ return (Genericlist *)srchlab;
+ break; /* Stop at the first record for this label */
+ }
+ lastlabel = srchlab;
+ }
+
+ /* Create a new entry and link to label list of the object */
+
+ newlabel = (LabellistPtr) malloc(sizeof(Labellist));
+ newlabel->cschem = cschem;
+ newlabel->cinst = cinst;
+ newlabel->label = new_global_pin(pin, cinst);
+ newlabel->subnets = 0;
+ copy_bus((Genericlist *)newlabel, netlist);
+
+ if (lastlabel != NULL) {
+ newlabel->next = srchlab;
+ lastlabel->next = newlabel;
+ }
+ else {
+ newlabel->next = global_labels;
+ global_labels = newlabel;
+ }
+ return (Genericlist *)newlabel;
+}
+
+/*----------------------------------------------------------------------*/
+/* Allocate memory for the new call list element */
+/* Define the values for the new call list element */
+/* Insert new call into call list */
+/* The new call is at the beginning of the list. */
+/*----------------------------------------------------------------------*/
+
+void addcall(objectptr cschem, objectptr callobj, objinstptr callinst)
+{
+ CalllistPtr newcall;
+ objectptr pschem;
+
+ /* Netlist is on the master schematic */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ newcall = (CalllistPtr) malloc(sizeof(Calllist));
+ newcall->cschem = cschem;
+ newcall->callobj = callobj;
+ newcall->callinst = callinst;
+ newcall->devindex = -1;
+ newcall->devname = NULL;
+ newcall->ports = NULL;
+ newcall->next = pschem->calls;
+ pschem->calls = newcall;
+}
+
+/*----------------------------------------------------------------------*/
+/* Add a port to the object cschem which connects net "netto" to */
+/* the calling object. One port is created for each net ID in "netto" */
+/* (which may be a bus). The port contains the net ID in the called */
+/* object. The port may already exist, in which case this routine does */
+/* nothing. */
+/*----------------------------------------------------------------------*/
+
+void addport(objectptr cschem, Genericlist *netto)
+{
+ PortlistPtr newport, seekport;
+ int portid = 0, netid, lbus;
+ buslist *sbus;
+ Boolean duplicate;
+
+ for (lbus = 0;;) {
+
+ if (netto->subnets == 0)
+ netid = netto->net.id;
+ else {
+ sbus = netto->net.list + lbus;
+ netid = sbus->netid;
+ }
+
+ /* If a port already exists for this net, don't add another one! */
+
+ duplicate = FALSE;
+ for (seekport = cschem->ports; seekport != NULL; seekport = seekport->next) {
+ if (seekport->netid != netid) {
+ if (seekport->portid > portid)
+ portid = seekport->portid;
+ }
+ else
+ duplicate = TRUE;
+ }
+
+ if (!duplicate) {
+ portid++;
+
+ newport = (PortlistPtr)malloc(sizeof(Portlist));
+ newport->netid = netid;
+ newport->portid = portid;
+
+ if (cschem->ports != NULL)
+ newport->next = cschem->ports;
+ else
+ newport->next = NULL;
+
+ cschem->ports = newport;
+ }
+ if (++lbus >= netto->subnets) break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Add a specific port connection from object cschem into the instance */
+/* cinst. This equates a net number in the calling object cschem */
+/* (netfrom) to a net number in the object instance being called */
+/* (netto). */
+/* */
+/* If we attempt to connect a bus of one size to a port of a different */
+/* size, return FALSE. Otherwise, add the call and return TRUE. */
+/*----------------------------------------------------------------------*/
+
+Boolean addportcall(objectptr cschem, Genericlist *netfrom, Genericlist *netto)
+{
+ CalllistPtr ccall;
+ PortlistPtr seekport, sp, newport;
+ objectptr instobj;
+ objinstptr cinst;
+ int lbus, netid_from, netid_to;
+ buslist *sbus, *tbus;
+ Boolean duplicate;
+
+ /* The call that we need to add a port to is the first on */
+ /* the list for cschem, as created by addcall(). */
+ ccall = cschem->calls;
+ instobj = ccall->callobj;
+ cinst = ccall->callinst;
+
+ if (netfrom->subnets != netto->subnets) {
+ if (netfrom->subnets == 0) {
+ /* It is possible that "netfrom" is an unlabeled polygon that */
+ /* is implicitly declared a bus by its connection to this */
+ /* port. If so, we promote "netfrom" to a bus but set the */
+ /* subnet entries to negative values, since we don't know what */
+ /* they are yet. */
+ promote_net(cschem, netfrom, netto->subnets);
+ }
+
+ /* Only other allowable condition is a bus size 1 connecting into */
+ /* a single-wire port. However, one should consider promotion of */
+ /* the pin in the target object to a bus on a per-instance basis. */
+ /* This has not yet been done. . . */
+
+ else if ((netfrom->subnets != 1) || (netto->subnets != 0)) {
+ /* Let the caller report error information, because it knows more */
+ return FALSE;
+ }
+ }
+
+ for (lbus = 0;;) {
+ buslist bsingf, bsingo;
+ Genericlist subnet_from, subnet_other;
+
+ if (netfrom->subnets == 0) {
+ netid_from = netfrom->net.id;
+
+ subnet_from.subnets = 0;
+ subnet_from.net.id = netid_from;
+
+ subnet_other.subnets = 0;
+ }
+ else {
+ sbus = netfrom->net.list + lbus;
+ netid_from = sbus->netid;
+
+ subnet_from.subnets = 1;
+ subnet_from.net.list = &bsingf;
+ bsingf.netid = netid_from;
+ bsingf.subnetid = sbus->subnetid;
+
+ bsingo.subnetid = lbus;
+ subnet_other.subnets = 1;
+ subnet_other.net.list = &bsingo;
+ }
+ if (netto->subnets == 0) {
+ netid_to = netto->net.id;
+ }
+ else {
+ tbus = netto->net.list + lbus;
+ netid_to = tbus->netid;
+ }
+
+ /* Check the ports of the instance's object for the one matching */
+ /* the "netto" net ID. */
+
+ duplicate = FALSE;
+ for (seekport = instobj->ports; seekport != NULL;
+ seekport = seekport->next) {
+ if (seekport->netid == netid_to) {
+
+ /* If there is already an entry for this port, then */
+ /* we may need to merge nets in cschem. */
+
+ for (sp = ccall->ports; sp != NULL; sp = sp->next)
+ if (sp->portid == seekport->portid) {
+ if (sp->netid != netid_from) {
+ if (netfrom->subnets == 0)
+ subnet_other.net.id = sp->netid;
+ else {
+ bsingo.netid = sp->netid;
+ bsingo.subnetid = getsubnet(bsingo.netid, cschem);
+ }
+ if (!mergenets(cschem, &subnet_other, &subnet_from)) {
+ /* Upon failure, see if we can merge the other */
+ /* direction. */
+ if (!mergenets(cschem, &subnet_from, &subnet_other))
+ continue;
+ else {
+ if (subnet_from.subnets == 0)
+ subnet_from.net.id = subnet_other.net.id;
+ else {
+ bsingf.netid = bsingo.netid;
+ bsingf.subnetid = bsingo.subnetid;
+ }
+ }
+ }
+ }
+ duplicate = TRUE;
+ }
+
+ if (!duplicate) {
+ newport = (PortlistPtr)malloc(sizeof(Portlist));
+ newport->netid = netid_from;
+ newport->portid = seekport->portid;
+ newport->next = ccall->ports;
+ ccall->ports = newport;
+ }
+ break;
+ }
+ }
+ if (++lbus >= netfrom->subnets) break;
+ }
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the net ID corresponding to the indicated port ID in the */
+/* indicated object. */
+/*----------------------------------------------------------------------*/
+
+int porttonet(objectptr cschem, int portno)
+{
+ PortlistPtr plist;
+
+ for (plist = cschem->ports; plist != NULL; plist = plist->next) {
+ if (plist->portid == portno)
+ return plist->netid;
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Traverse netlist and return netid of polygon or pin on which the */
+/* indicated point is located. */
+/* If point is not on any polygon or does not match any pin position, */
+/* return NULL. */
+/* Labels which have a non-NULL "cinst" record are instance-dependent */
+/* and must match parameter "cinst". */
+/* */
+/* This routine checks to see if more than one net crosses the point */
+/* of interest, and merges the nets if found. */
+/* (the method has been removed and must be reinstated, presumably) */
+/*----------------------------------------------------------------------*/
+
+Genericlist *pointtonet(objectptr cschem, objinstptr cinst, XPoint *testpoint)
+{
+ XPoint *tpt, *tpt2;
+ PolylistPtr ppoly;
+ LabellistPtr plab;
+ Genericlist *preturn;
+ objectptr pschem; /* primary schematic */
+
+ /* cschem is the object containing the point. However, if the object */
+ /* is a secondary schematic, the netlist is located in the master. */
+
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ for (plab = pschem->labels; plab != NULL; plab = plab->next) {
+ if (plab->cschem != cschem) continue;
+ else if ((plab->cinst != NULL) && (plab->cinst != cinst)) continue;
+ tpt = &(plab->label->position);
+ if (proximity(tpt, testpoint))
+ return (Genericlist *)plab;
+
+ /* if we've encountered a unique instance, then continue past */
+ /* all other instances using this label. */
+
+ if (plab->cinst != NULL)
+ while (plab->next && (plab->next->label == plab->label))
+ plab = plab->next;
+ }
+
+ /* Check against polygons. We use this part of the routine to see */
+ /* if there are crossing wires on top of a port. If so, they are */
+ /* merged together. */
+
+ preturn = (Genericlist *)NULL;
+ for (ppoly = pschem->polygons; ppoly != NULL; ppoly = ppoly->next) {
+ if (ppoly->cschem != cschem) continue;
+ for (tpt = ppoly->poly->points; tpt < ppoly->poly->points
+ + EndPoint(ppoly->poly->number); tpt++) {
+ tpt2 = tpt + NextPoint(ppoly->poly->number);
+
+ if (onsegment(tpt, tpt2, testpoint)) {
+ if (preturn == (Genericlist *)NULL)
+ preturn = (Genericlist *)ppoly;
+ else
+ mergenets(pschem, (Genericlist *)ppoly, preturn);
+ }
+ }
+ }
+
+ return preturn;
+}
+
+/*----------------------------------------------------------------------*/
+/* localpin keeps track of temporary pin labels when flattening the */
+/* hierarchy without destroying the original pin names. */
+/*----------------------------------------------------------------------*/
+
+void makelocalpins(objectptr cschem, CalllistPtr clist, char *prefix)
+{
+ NetnamePtr netnames;
+ PortlistPtr ports, plist;
+ stringpart *locpin;
+ int locnet, callnet;
+ objectptr callobj = clist->callobj;
+
+ /* Copy all net names which are passed from above through ports */
+
+ for (ports = clist->ports; ports != NULL; ports = ports->next) {
+ callnet = ports->netid;
+ for (plist = callobj->ports; plist != NULL; plist = plist->next) {
+ if (plist->portid == ports->portid) {
+ locnet = plist->netid;
+ locpin = nettopin(callnet, cschem, prefix);
+ break;
+ }
+ }
+
+ for (netnames = callobj->netnames; netnames != NULL; netnames = netnames->next)
+ if (netnames->netid == locnet)
+ break;
+
+ if (netnames == NULL) {
+ netnames = (NetnamePtr)malloc(sizeof(Netname));
+ netnames->netid = locnet;
+ netnames->localpin = stringcopy(locpin);
+ netnames->next = callobj->netnames;
+ callobj->netnames = netnames;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the first point associated with the net "netid" in the object */
+/* cschem. */
+/*----------------------------------------------------------------------*/
+
+XPoint *NetToPosition(int netid, objectptr cschem)
+{
+ PolylistPtr plist;
+ LabellistPtr llist;
+ buslist *sbus;
+ int lbus, locnetid; /* sub_bus, (jdk) */
+
+ plist = cschem->polygons;
+ for (; plist != NULL; plist = plist->next) {
+ for (lbus = 0;;) {
+ if (plist->subnets == 0) {
+ locnetid = plist->net.id;
+ }
+ else {
+ sbus = plist->net.list + lbus;
+ locnetid = sbus->netid;
+ }
+ if (locnetid == netid) {
+ return plist->poly->points;
+ }
+ if (++lbus >= plist->subnets) break;
+ }
+ }
+
+ llist = (netid < 0) ? global_labels : cschem->labels;
+ for (; llist != NULL; llist = llist->next) {
+ for (lbus = 0;;) {
+ if (llist->subnets == 0) {
+ locnetid = llist->net.id;
+ }
+ else {
+ sbus = llist->net.list + lbus;
+ locnetid = sbus->netid;
+ }
+ if (locnetid == netid) {
+ return (&(llist->label->position));
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find a label element for the given net number. In a symbol, this */
+/* will be the label representing the pin (or the first one found, if */
+/* the pin has multiple labels). If no label is found, return NULL. */
+/* Preferably choose a non-temporary label, if one exists */
+/*----------------------------------------------------------------------*/
+
+labelptr NetToLabel(int netid, objectptr cschem)
+{
+ LabellistPtr llist;
+ labelptr standby = NULL;
+ buslist *sbus;
+ int lbus, locnetid;
+
+ llist = (netid < 0) ? global_labels : cschem->labels;
+
+ for (; llist != NULL; llist = llist->next) {
+ for (lbus = 0;;) {
+ if (llist->subnets == 0) {
+ locnetid = llist->net.id;
+ }
+ else {
+ sbus = llist->net.list + lbus;
+ locnetid = sbus->netid;
+ }
+ if (locnetid == netid) {
+ if (llist->label->string->type == FONT_NAME)
+ return llist->label;
+ else if (standby == NULL)
+ standby = llist->label;
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+ return standby;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* Find the subnet number of the given net. This routine should be */
+/* used only as a last resort in case the subnet number is not */
+/* available; it has to look through the polygon and label lists in */
+/* detail to find the specified net ID. */
+/*----------------------------------------------------------------------*/
+
+int getsubnet(int netid, objectptr cschem)
+{
+ PolylistPtr plist;
+ LabellistPtr llist;
+ buslist *sbus;
+ int lbus, sub_bus, locnetid;
+
+ plist = cschem->polygons;
+ for (; plist != NULL; plist = plist->next) {
+ for (lbus = 0;;) {
+ if (plist->subnets == 0) {
+ locnetid = plist->net.id;
+ sub_bus = -1;
+ }
+ else {
+ sbus = plist->net.list + lbus;
+ locnetid = sbus->netid;
+ sub_bus = sbus->subnetid;
+ }
+ if (locnetid == netid) {
+ return sub_bus;
+ }
+ if (++lbus >= plist->subnets) break;
+ }
+ }
+
+ llist = (netid < 0) ? global_labels : cschem->labels;
+ for (; llist != NULL; llist = llist->next) {
+ for (lbus = 0;;) {
+ if (llist->subnets == 0) {
+ locnetid = llist->net.id;
+ sub_bus = -1;
+ }
+ else {
+ sbus = llist->net.list + lbus;
+ locnetid = sbus->netid;
+ sub_bus = sbus->subnetid;
+ }
+ if (locnetid == netid) {
+ return sub_bus;
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find a pin name for the given net number */
+/* Either take the last pin name with the net, or generate a new pin, */
+/* assigning it a net number for a string. */
+/* prefix = NULL indicates spice netlist, but is also used for PCB-type */
+/* netlists because the calling hierarchy is generated elsewhere. */
+/*----------------------------------------------------------------------*/
+
+stringpart *nettopin(int netid, objectptr cschem, char *prefix)
+{
+ NetnamePtr netname;
+ labelptr pinlab;
+ LabellistPtr netlabel;
+ char *newtext, *snew = NULL;
+ XPoint *pinpos;
+ int locnetid; /* lbus, (jdk) */
+ /* buslist *sbus; (jdk) */
+ Genericlist newnet;
+ static stringpart *newstring = NULL;
+
+ /* prefix is NULL for hierarchical (spice) netlists and for */
+ /* internal netlist manipulation. */
+
+ if (prefix == NULL) {
+ pinlab = NetToLabel(netid, cschem);
+ if (pinlab != NULL) {
+
+ /* If this is a "temp label", regenerate the name according to */
+ /* the actual net number, if it does not match. This prevents */
+ /* unrelated temp labels from getting the same name. */
+
+ if (pinlab->string->type != FONT_NAME) {
+ if (sscanf(pinlab->string->data.string + 3, "%d", &locnetid) == 1) {
+ if (locnetid != netid) {
+ newtext = pinlab->string->data.string;
+ newtext[3] = '\0';
+ newnet.subnets = 0;
+ newnet.net.id = netid;
+ pinlab->string->data.string = textprintnet(newtext, NULL, &newnet);
+ free(newtext);
+ }
+ }
+ }
+ return pinlab->string;
+ }
+ else {
+ /* If there's no label associated with this network, make one */
+ /* called "intn" where n is the net number (netid). This is a */
+ /* temp label (denoted by lack of a font specifier). */
+
+ newnet.subnets = 0;
+ newnet.net.id = netid;
+ pinpos = NetToPosition(netid, cschem);
+ netlabel = (LabellistPtr)new_tmp_pin(cschem, pinpos, NULL, "int", &newnet);
+ return (netlabel) ? netlabel->label->string : NULL;
+ }
+ }
+
+ /* Flattened (e.g., sim) netlists */
+
+ for (netname = cschem->netnames; netname != NULL; netname = netname->next) {
+ if (netname->netid == netid) {
+ if (netname->localpin != NULL)
+ return netname->localpin;
+ break;
+ }
+ }
+
+ /* Generate the string for the local instantiation of this pin */
+ /* If this node does not have a pin, create one using the current */
+ /* hierarchy prefix as the string. */
+
+ pinlab = NetToLabel(netid, cschem);
+ if (pinlab != NULL) {
+ stringpart *tmpstring = pinlab->string;
+ snew = textprint(tmpstring, NULL);
+ }
+ else {
+ snew = (char *)malloc(12);
+ sprintf(snew, "int%d", netid);
+ }
+
+ if (netid < 0) {
+ newtext = snew;
+ }
+ else {
+ newtext = (char *)malloc(1 + strlen(snew) + strlen(prefix));
+ sprintf(newtext, "%s%s", prefix, snew);
+ free(snew);
+ }
+
+ /* "newstring" is allocated only once and should not be free'd */
+ /* by the calling routine. */
+
+ if (newstring == NULL) {
+ newstring = (stringpart *)malloc(sizeof(stringpart));
+ newstring->nextpart = NULL;
+ newstring->type = TEXT_STRING;
+ }
+ else {
+ free(newstring->data.string);
+ }
+ newstring->data.string = newtext;
+ return newstring;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the net which connects to the given pin label */
+/* Return NULL (no net) if no match was found. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *pintonet(objectptr cschem, objinstptr cinst, labelptr testpin)
+{
+ LabellistPtr seeklabel;
+ int lbus, matched;
+ buslist *sbus, *tbus;
+ Genericlist netlist, *tmplist;
+
+ /* check against local pins, if this pin is declared local */
+
+ seeklabel = (testpin->pin == GLOBAL) ? global_labels : cschem->labels;
+
+ netlist.subnets = 0;
+ for (; seeklabel != NULL; seeklabel = seeklabel->next)
+ if (!stringcomprelaxed(seeklabel->label->string, testpin->string, cinst))
+ {
+ /* Quick simple case: no bus */
+ if (seeklabel->subnets == 0)
+ return (Genericlist *)seeklabel;
+
+ tmplist = break_up_bus(testpin, cinst, (Genericlist *)seeklabel);
+
+ /* It is necessary to be able to put together a netlist from */
+ /* partial sources none of which may be complete. */
+
+ if (tmplist != NULL) {
+ if (netlist.subnets == 0) copy_bus(&netlist, tmplist);
+ matched = 0;
+ for (lbus = 0; lbus < tmplist->subnets; lbus++) {
+ sbus = netlist.net.list + lbus;
+ tbus = tmplist->net.list + lbus;
+ if (sbus->netid == 0)
+ sbus->netid = tbus->netid; /* copy forward */
+ else if (tbus->netid == 0)
+ tbus->netid = sbus->netid; /* copy back */
+ if (sbus->netid != 0)
+ matched++;
+ }
+ if (matched == netlist.subnets) {
+ free(netlist.net.list);
+ return tmplist;
+ }
+ }
+ }
+
+ if (netlist.subnets != 0) {
+ free(netlist.net.list);
+ return tmplist; /* Returns list with partial entries */
+ }
+ return NULL; /* No matches found */
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Automatic Schematic Generation stuff--- */
+/* Blow away all polygons in the schematic and replace them with a */
+/* simple rat's-nest (point-to-point). */
+/* */
+/* This routine is more of a proof-of-concept than a useful routine, */
+/* intended to be called only from the Tcl console. It is intended to */
+/* reveal most of the issues related to automatic schematic generation, */
+/* in which the netlist, or a portion of it, can be redrawn as objects */
+/* are moved around to maintain the relationships present in the */
+/* calls structure. */
+/*----------------------------------------------------------------------*/
+
+void ratsnest(objinstptr thisinst)
+{
+ CalllistPtr calls;
+ PortlistPtr ports;
+ PolylistPtr plist;
+ LabellistPtr llist;
+ objectptr pschem, cschem;
+ objinstptr cinst;
+ polyptr ppoly, *newpoly;
+ buslist *sbus;
+ int i, netid, points, sub_bus, lbus;
+ XPoint portpos;
+ Boolean result;
+
+ cschem = thisinst->thisobject;
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ /* Go through the netlist and remove all polygons. Remove */
+ /* the polygons from the object as well as from the netlist. */
+
+ for (plist = pschem->polygons; plist != NULL; plist = plist->next) {
+ ppoly = plist->poly;
+ ppoly->type += REMOVE_TAG; /* tag for removal */
+ }
+ freepolylist(&pschem->polygons);
+
+ /* for each schematic (PRIMARY or SECONDARY), remove the tagged */
+ /* elements. */
+
+ for (i = 0; i < xobjs.pages; i++) {
+ cinst = xobjs.pagelist[i]->pageinst;
+ if (cinst && (cinst->thisobject->schemtype == SECONDARY) &&
+ (cinst->thisobject->symschem == pschem)) {
+ delete_tagged(cinst);
+ }
+ else if (cinst == thisinst)
+ delete_tagged(cinst);
+ }
+
+ /* Now, for each net ID in the label list, run through the calls and */
+ /* find all points in the calls connecting to that net. Link */
+ /* them with as many polygons as needed. These polygons are point- */
+ /* to-point lines, turning the schematic representation into a */
+ /* "rat's-nest". */
+
+ for (llist = pschem->labels; llist != NULL; llist = llist->next) {
+ for (lbus = 0;;) {
+ if (llist->subnets == 0) {
+ netid = llist->net.id;
+ sub_bus = -1;
+ }
+ else {
+ sbus = llist->net.list + lbus;
+ netid = sbus->netid;
+ sub_bus = sbus->subnetid;
+ }
+
+ points = 0;
+ for (calls = pschem->calls; calls != NULL; calls = calls->next) {
+
+ /* Determine schematic object from the object called. Start a */
+ /* new polygon any time we switch schematic pages. */
+
+ if (calls->cschem != cschem)
+ points = 0;
+ cschem = calls->cschem;
+
+ for (ports = calls->ports; ports != NULL; ports = ports->next) {
+ if (ports->netid == netid) {
+
+ /* Find the location of this port in the coordinates of cschem */
+
+ result = PortToPosition(calls->callinst, ports->portid, &portpos);
+ if (result == True) {
+ points++;
+ if (points == 1) {
+ NEW_POLY(newpoly, cschem);
+ polydefaults(*newpoly, 1, portpos.x, portpos.y);
+ (*newpoly)->style |= UNCLOSED;
+ (*newpoly)->color = xc_getlayoutcolor(RATSNESTCOLOR);
+ addpoly(cschem, *newpoly, (Genericlist *)llist);
+ }
+ else
+ poly_add_point(*newpoly, &portpos);
+ }
+ else {
+ Fprintf(stderr, "Error: Cannot find pin connection in symbol!\n");
+ /* Deal with error condition? */
+ }
+ }
+ }
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+
+ /* Now, move all the labels to reconnect to their networks */
+
+ /* (to be done) */
+
+ /* Refresh the screen */
+ drawarea(NULL, NULL, NULL);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Find a net or netlist in object cschem with the indicated name. */
+/* */
+/* This is the same routine as above, but finds the net with the given */
+/* name, or all nets which are a subset of the given name, if the name */
+/* is the name of a bus. Return NULL if no match was found. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *nametonet(objectptr cschem, objinstptr cinst, char *netname)
+{
+ LabellistPtr seeklabel;
+ stringpart newstring;
+
+ /* Build a simple xcircuit string from "netname" (nothing malloc'd) */
+ newstring.type = TEXT_STRING;
+ newstring.nextpart = NULL;
+ newstring.data.string = netname;
+
+ /* Check against local networks */
+
+ for (seeklabel = cschem->labels; seeklabel != NULL; seeklabel = seeklabel->next)
+ if (!stringcomprelaxed(seeklabel->label->string, &newstring, cinst))
+ return (Genericlist *)seeklabel;
+
+ /* Check against global networks */
+
+ for (seeklabel = global_labels; seeklabel != NULL; seeklabel = seeklabel->next)
+ if (!stringcomprelaxed(seeklabel->label->string, &newstring, cinst))
+ return (Genericlist *)seeklabel;
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Check if two parts may have the same component index. This is true */
+/* for parts with parameterized pins, such as those in the "quadparts" */
+/* library. Compare the names of the ports in each instance. If none */
+/* match, then these are unique subparts of a single component, and we */
+/* should return FALSE. Otherwise, return TRUE. */
+/*----------------------------------------------------------------------*/
+
+Boolean samepart(CalllistPtr clist1, CalllistPtr clist2)
+{
+ PortlistPtr port;
+ labelptr plab;
+ char *pinname1, *pinname2;
+ Boolean rvalue;
+
+ if (clist1->callobj != clist2->callobj) return FALSE;
+
+ rvalue = FALSE;
+ for (port = clist1->ports; port != NULL; port = port->next) {
+ plab = PortToLabel(clist1->callinst, port->portid);
+ pinname1 = textprint(plab->string, clist1->callinst);
+ pinname2 = textprint(plab->string, clist2->callinst);
+ if (!strcmp(pinname1, pinname2)) rvalue = TRUE;
+ free(pinname1);
+ free(pinname2);
+ }
+ return rvalue;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate an index number for a device in a flat netlist format. */
+/* We ignore any values given to "index" (this is a to-do item, since */
+/* many schematics are only a single level of hierarchy, so it makes */
+/* sense to keep designated indices when possible), but do generate */
+/* independent index numbering for different device classes. */
+/*----------------------------------------------------------------------*/
+
+u_int devflatindex(char *devname)
+{
+ flatindex *fp = flatrecord;
+ while (fp != NULL) {
+ if (!strcmp(devname, fp->devname)) {
+ return ++fp->index;
+ }
+ fp = fp->next;
+ }
+ fp = (flatindex *)malloc(sizeof(flatindex));
+ fp->next = flatrecord;
+ flatrecord = fp;
+ fp->index = 1;
+ fp->devname = devname;
+ return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free the list of per-class flat device indices */
+/*----------------------------------------------------------------------*/
+
+void freeflatindex()
+{
+ flatindex *fpnext, *fp = flatrecord;
+ while (fp != NULL) {
+ fpnext = fp->next;
+ free(fp);
+ fp = fpnext;
+ }
+ flatrecord = NULL;
+}
+
+/*---------------------------------------------------------*/
+/* Convert a number (up to 99999) to its base-36 equivalent */
+/*---------------------------------------------------------*/
+
+int convert_to_b36(int number)
+{
+ int b36idx, tmpidx;
+
+ tmpidx = number;
+ b36idx = (tmpidx / 10000) * 1679616;
+ tmpidx %= 10000;
+ b36idx += (tmpidx / 1000) * 46656;
+ tmpidx %= 1000;
+ b36idx += (tmpidx / 100) * 1296;
+ tmpidx %= 100;
+ b36idx += ((tmpidx / 10) * 36) + (tmpidx % 10);
+
+ return b36idx;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate an index number for this device. Count all devices having */
+/* the same device name (as printed in the netlist) in the calls of */
+/* the calling object (cfrom) */
+/* */
+/* Update (9/29/04): Remove any leading whitespace from the device */
+/* name to prevent treating, for example, "J?" and " J?" as separate */
+/* device types. */
+/* */
+/* Update (7/28/05): To allow SPICE device indices to include all */
+/* alphanumerics, we parse in base-36, and count in the subset of */
+/* base-36 that can be interpreted as decimal (1-9, 36-45, etc.) */
+/*----------------------------------------------------------------------*/
+
+u_int devindex(objectptr cfrom, CalllistPtr clist)
+{
+ CalllistPtr cptr, listfrom = cfrom->calls;
+ objectptr devobj = clist->callobj;
+ u_int *occupied, total, objindex, i, b36idx;
+ char *devname, *cname;
+ /* oparamptr ops; (jdk) */
+
+ if (listfrom == NULL) return (u_int)0;
+ if (clist->devindex >= 0) return clist->devindex;
+
+ devname = (clist->devname == NULL) ? devobj->name : clist->devname;
+ while (isspace(*devname)) devname++;
+
+ /* Count total number of devices */
+ for (cptr = listfrom, total = 0; cptr != NULL; cptr = cptr->next, total++);
+ occupied = (u_int *)malloc(total * sizeof(u_int));
+ objindex = 1;
+
+ for (cptr = listfrom, total = 0; cptr != NULL; cptr = cptr->next, total++) {
+ occupied[total] = 0;
+ if (cptr == clist) continue;
+ cname = (cptr->devname == NULL) ? cptr->callobj->name : cptr->devname;
+ while (isspace(*cname)) cname++;
+ if (!strcmp(cname, devname)) {
+ occupied[total] = cptr->devindex;
+ if (cptr->devindex == objindex) objindex++;
+ }
+ }
+
+ b36idx = convert_to_b36(objindex);
+ for (; objindex <= total; objindex++) {
+ b36idx = convert_to_b36(objindex);
+ for (i = 0; i < total; i++)
+ if (occupied[i] == b36idx)
+ break;
+ if (i == total)
+ break;
+ }
+ free(occupied);
+
+ clist->devindex = b36idx;
+ return objindex;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create and return an ordered list of info labels for the schematic */
+/* page cschem. A linked label list is returned, combining info labels */
+/* from all schematic pages related to cschem (master and slave pages). */
+/* It is the responsibility of the calling routine to free the linked */
+/* list. */
+/*----------------------------------------------------------------------*/
+
+LabellistPtr geninfolist(objectptr cschem, objinstptr cinst, char *mode)
+{
+ int locpos, j; /* i, (jdk) */
+ int vmax;
+ genericptr *pgen;
+ labelptr plabel;
+ LabellistPtr newllist, listtop, srchlist;
+ u_char *strt;
+ stringpart *strptr;
+
+ listtop = NULL;
+ vmax = 0;
+
+ for (pgen = cschem->plist; pgen < cschem->plist + cschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plabel = TOLABEL(pgen);
+ if ((plabel->pin == INFO) && !textncomp(plabel->string, mode, cinst)) {
+
+ if (mode[0] == '\0') {
+ strptr = findtextinstring(":", &locpos, plabel->string, cinst);
+ locpos--;
+ }
+ else
+ strptr = findstringpart(strlen(mode), &locpos, plabel->string, cinst);
+
+ if (locpos < 0)
+ continue; /* null after netlist type designator */
+
+ strt = strptr->data.string + locpos + 1;
+
+ if (*strt != ':') {
+ if (sscanf(strt, "%d", &j) != 1) continue;
+
+ /* Consider only positive-valued numbers. Negative */
+ /* indices are handled by "writenet" by merging the */
+ /* minus character into the mode name. */
+
+ if (j < 0) continue;
+ if (j >= vmax) vmax = j + 1;
+ }
+ else
+ j = ++vmax;
+
+ newllist = (LabellistPtr)malloc(sizeof(Labellist));
+ newllist->label = plabel;
+ newllist->cschem = cschem;
+ newllist->cinst = cinst;
+ newllist->net.id = j; /* use this to find the ordering */
+ newllist->subnets = 0; /* so free() doesn't screw up */
+
+ /* Order the linked list */
+
+ if ((listtop == NULL) || (listtop->net.id >= j)) {
+ newllist->next = listtop;
+ listtop = newllist;
+ }
+ else {
+ for (srchlist = listtop; srchlist != NULL; srchlist = srchlist->next) {
+ if ((srchlist->next != NULL) && (srchlist->next->net.id >= j)) {
+ newllist->next = srchlist->next;
+ srchlist->next = newllist;
+ break;
+ }
+ else if (srchlist->next == NULL) {
+ srchlist->next = newllist;
+ newllist->next = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+ return listtop;
+}
+
+/*----------------------------------------------------------------------*/
+/* Trivial default pin name lookup. Parse an object's pin labels for */
+/* pin names. Return the text of the nth pin name, as counted by the */
+/* position in the object's parts list. If there are fewer than (n+1) */
+/* pin labels in the object, return NULL. Otherwise, return the pin */
+/* name in a malloc'd character string which the caller must free. */
+/*----------------------------------------------------------------------*/
+
+char *defaultpininfo(objinstptr cinst, int pidx)
+{
+ genericptr *pgen;
+ labelptr plabel;
+ objectptr cschem = cinst->thisobject;
+ int count = 0;
+ char *stxt;
+
+ for (pgen = cschem->plist; pgen < cschem->plist + cschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plabel = TOLABEL(pgen);
+ if (plabel->pin == LOCAL) {
+ if (count == pidx) {
+ stxt = textprint(plabel->string, cinst);
+ return stxt;
+ }
+ count++;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Parse an object's info labels for pin names. This is *not* a */
+/* netlist function. The nth pin name is returned, or NULL if not */
+/* found. Return value is a malloc'd string which the caller must */
+/* free. */
+/*----------------------------------------------------------------------*/
+
+char *parsepininfo(objinstptr cinst, char *mode, int pidx)
+{
+ genericptr *pgen;
+ labelptr plabel;
+ u_char *strt, *fnsh;
+ int slen, i, locpos;
+ objectptr cschem = cinst->thisobject;
+ stringpart *strptr;
+ char *sout;
+ int count = 0;
+
+ for (pgen = cschem->plist; pgen < cschem->plist + cschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plabel = TOLABEL(pgen);
+ if (plabel->pin == INFO) {
+ slen = stringlength(plabel->string, True, cinst);
+ for (i = 1; i < slen; i++) {
+ strptr = findstringpart(i, &locpos, plabel->string, cinst);
+ if (locpos >= 0 && *(strptr->data.string + locpos) == ':') break;
+ }
+ /* Currently we are not checking against "mode". . .*/
+ /* interpret all characters after the colon */
+
+ for (++i; i < slen; i++) {
+ strptr = findstringpart(i, &locpos, plabel->string, cinst);
+ if (locpos >= 0) {
+
+ /* Do for all text characters */
+ strt = strptr->data.string + locpos;
+ if (*strt == '%') {
+ strt++;
+ i++;
+ if (*strt == 'p') { /* Pin found! */
+ if (count == pidx) { /* Get pin text */
+ strt++;
+ fnsh = strt + 1;
+ while (*fnsh != ' ' && *fnsh != '\0') fnsh++;
+ sout = malloc(fnsh - strt + 1);
+ strncpy(sout, strt, fnsh - strt);
+ return sout;
+ }
+ count++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Look for information labels in the object parts list. Parse the */
+/* information labels and print results to specified output device. */
+/* (This is not very robust to errors---needs work!) */
+/* */
+/* If "autonumber" is true, then the parsed info label is used to */
+/* auto-number devices. */
+/*----------------------------------------------------------------------*/
+
+char *parseinfo(objectptr cfrom, objectptr cthis, CalllistPtr clist,
+ char *prefix, char *mode, Boolean autonumber, Boolean no_output)
+{
+ /* genericptr *pgen; (jdk) */
+ stringpart *strptr, *ppin, *optr;
+ char *snew, *sout = NULL;
+ u_char *strt, *fnsh;
+ PortlistPtr ports;
+ oparamptr ops, instops;
+ int portid, locpos, i, k, subnet, slen; /* j, (jdk) */
+ char *key = NULL;
+ u_int newindex;
+ Boolean is_flat = False, is_symbol = False, is_iso = False, is_quoted;
+ Boolean do_update = True, include_once = False;
+ char *locmode, *b36str, *sptr;
+ LabellistPtr infolist, infoptr;
+ FILE *finclude;
+
+ /* For flat netlists, prefix the mode with the word "flat". */
+ /* As of 3/8/07, this includes the ".sim" format, which */
+ /* should be called as mode "flatsim". */
+
+ locmode = mode;
+ if (locmode && (!strncmp(mode, "flat", 4) || !strncmp(mode, "pseu", 4))) {
+ locmode += 4;
+ is_flat = True;
+ }
+
+ /* mode == "" is passed when running resolve_devindex() and indicates */
+ /* that the routine should be used to assign devindex to calls whose */
+ /* devices have been manually assigned numbers. The preferred method */
+ /* is to assign these values through the "index" parameter. Use of */
+ /* parseinfo() ensures that objects that have no "index" parameter */
+ /* but have valid info-labels for SPICE or PCB output will be */
+ /* assigned the correct device index. */
+ /* Sept. 3, 2006---The use of the prepended "@" character on */
+ /* parameter names means that I can replace the cryptic "idx" with */
+ /* the more obvious "index", which previously conflicted with the */
+ /* PostScript command of the same name. Parameters "index" and "idx" */
+ /* are treated interchangeably by the netlister. */
+
+ if (locmode[0] == '\0')
+ do_update = False;
+
+ /* 1st pass: look for valid labels; see if more than one applies. */
+ /* If so, order them correctly. Labels may not be numbered in */
+ /* sequence, and may begin with zero. We allow a lot of flexibility */
+ /* but the general expectation is that sequences start at 0 or 1 and */
+ /* increase by consecutive integers. */
+
+ infolist = geninfolist(cthis, clist->callinst, locmode);
+
+ /* Now parse each label in sequence and output the result to */
+ /* the return string. */
+
+ sout = (char *)malloc(1);
+ *sout = '\0';
+
+ for (infoptr = infolist; infoptr != NULL; infoptr = infoptr->next) {
+ objectptr pschem, cschem = infoptr->cschem;
+ labelptr plabel = infoptr->label;
+ objinstptr cinst = infoptr->cinst;
+
+ /* move to colon character */
+ slen = stringlength(plabel->string, True, cinst);
+ for (i = 1; i < slen; i++) {
+ strptr = findstringpart(i, &locpos, plabel->string, cinst);
+ if (locpos >= 0 && *(strptr->data.string + locpos) == ':') break;
+ }
+
+ /* interpret all characters after the colon */
+ for (++i; i < slen; i++) {
+ strptr = findstringpart(i, &locpos, plabel->string, cinst);
+ if (locpos >= 0) {
+
+ /* Do for all text characters */
+ strt = strptr->data.string + locpos;
+ if (*strt == '%') {
+ is_quoted = False;
+ strt++;
+ i++;
+ switch(*strt) {
+ case '%':
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "%");
+ break;
+ case 'r':
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "\n");
+ break;
+ case 't':
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "\t");
+ break;
+ case 'i':
+ if (clist->devname == NULL)
+ clist->devname = strdup(sout);
+ if (do_update) {
+ if (is_flat)
+ newindex = devflatindex(clist->devname);
+ else
+ newindex = devindex(cfrom, clist);
+ b36str = d36a(newindex);
+ sout = (char *)realloc(sout, strlen(sout) + strlen(b36str) + 1);
+ sprintf(sout + strlen(sout), "%s", b36str);
+ }
+ break;
+ case 'N':
+ sout = (char *)realloc(sout, strlen(sout)
+ + strlen(cschem->name) + 1);
+ strcat(sout, cschem->name);
+ break;
+ case 'n':
+ sptr = strstr(cschem->name, "::");
+ if (sptr == NULL)
+ sptr = cschem->name;
+ else
+ sptr += 2;
+ sout = (char *)realloc(sout, strlen(sout)
+ + strlen(sptr) + 1);
+ strcat(sout, sptr);
+ break;
+ case 'x':
+ sout = (char *)realloc(sout, strlen(sout) + 7);
+ sprintf(sout + strlen(sout), "%d",
+ cinst->position.x);
+ break;
+ case 'y':
+ sout = (char *)realloc(sout, strlen(sout) + 7);
+ sprintf(sout + strlen(sout), "%d",
+ cinst->position.y);
+ break;
+ case 'F':
+ if (no_output) break;
+ include_once = True;
+ /* drop through */
+ case 'f':
+ if (no_output) break;
+
+ /* Followed by a filename to include verbatim into */
+ /* the output. Filename either has no spaces or */
+ /* is in quotes. */
+
+ /* Use textprint to catch any embedded parameters */
+
+ snew = textprint(strptr, cinst);
+ strt = snew;
+ while (*strt != '\0') {
+ if (*strt == '%') {
+ if (include_once && *(strt + 1) == 'F')
+ break;
+ else if (!include_once && *(strt + 1) == 'f')
+ break;
+ }
+ strt++;
+ }
+
+ if (*strt == '\0') {
+ /* No filename; print verbatim */
+ free(snew);
+ include_once = False;
+ break;
+ }
+
+ strt += 2;
+ if (*strt == '"') strt++;
+ if (*strt == '"' || *strt == '\0') break;
+ fnsh = strt + 1;
+ while (*fnsh != '\0' && !isspace(*fnsh) && *fnsh != '"')
+ fnsh++;
+ strncpy(_STR, strt, (int)(fnsh - strt));
+ _STR[(int)(fnsh - strt)] = '\0';
+ free(snew);
+ i = slen;
+
+ /* Do variable and tilde expansion on the filename */
+ xc_tilde_expand(_STR, 149);
+ xc_variable_expand(_STR, 149);
+
+ /* Check if this file has been included already */
+ if (include_once) {
+ if (check_included(_STR)) {
+ include_once = False;
+ break;
+ }
+ append_included(_STR);
+ }
+
+ /* Open the indicated file and dump to the output */
+ finclude = fopen(_STR, "r");
+ if (finclude != NULL) {
+ char *sptr = sout;
+ int nlen;
+ int stlen = strlen(sout);
+ while (fgets(_STR, 149, finclude)) {
+ nlen = strlen(_STR);
+ sout = (char *)realloc(sout, stlen + nlen + 1);
+ sptr = sout + stlen;
+ strcpy(sptr, _STR);
+ stlen += nlen;
+ }
+ fclose(finclude);
+ }
+ else {
+ Wprintf("No file named %s found", _STR);
+ }
+ include_once = False;
+ break;
+
+ case 'p':
+ /* Pin name either has no spaces or is in quotes */
+ strt++;
+ if (*strt == '"') {
+ is_quoted = True;
+ strt++;
+ i++;
+ }
+ if (*strt == '"' || *strt == '\0') break;
+ fnsh = strt + 1;
+ while (*fnsh != '\0' && !isspace(*fnsh) && *fnsh != '"')
+ fnsh++;
+ strncpy(_STR, strt, (int)(fnsh - strt));
+ _STR[(int)(fnsh - strt)] = '\0';
+ i += (fnsh - strt);
+ /* if (is_quoted || *fnsh == '\0') i++; */
+ if (is_quoted) i++;
+
+ /* Find the port which corresponds to this pin name */
+ /* in the called object (cschem). If this is a */
+ /* linked symbol/schematic, then the port list will */
+ /* be in the schematic view, not in the symbol view */
+
+ pschem = cschem;
+ if (cschem->ports == NULL && cschem->symschem != NULL &&
+ cschem->symschem->ports != NULL)
+ pschem = cschem->symschem;
+
+ for (ports = pschem->ports; ports != NULL;
+ ports = ports->next) {
+ ppin = nettopin(ports->netid, pschem, NULL);
+ if (!textcomp(ppin, _STR, NULL)) {
+ portid = ports->portid;
+ break;
+ }
+ }
+ if (ports != NULL) {
+
+ /* Find the matching port in the calling object instance */
+
+ for (ports = clist->ports; ports != NULL;
+ ports = ports->next)
+ if (ports->portid == portid) break;
+
+ if (ports != NULL) {
+
+ ppin = nettopin(ports->netid, cfrom, prefix);
+ subnet = getsubnet(ports->netid, cfrom);
+ snew = textprintsubnet(ppin, cinst, subnet);
+ sout = (char *)realloc(sout, strlen(sout) +
+ strlen(snew) + 1);
+ strcat(sout, snew);
+ free(snew);
+ break;
+ }
+ else {
+ Fprintf(stderr, "Error: called non-existant port\n");
+ }
+ }
+ else {
+ Wprintf("No pin named %s in device %s", _STR, cschem->name);
+ }
+ break;
+ case 'v':
+ /* Parameter name either has no spaces or is in quotes */
+ strt++;
+ if (*strt == '"') {
+ is_quoted = True;
+ strt++;
+ i++;
+ }
+ if (*strt == '"' || *strt == '\0') break;
+ fnsh = strt + 1;
+ while (*fnsh != '\0' && !isspace(*fnsh) && *fnsh != '"')
+ fnsh++;
+ strncpy(_STR, strt, (int)(fnsh - strt));
+ _STR[(int)(fnsh - strt)] = '\0';
+ i += (fnsh - strt);
+ /* if (is_quoted || *fnsh == '\0') i++; */
+ if (is_quoted) i++;
+
+ /* Compare this name against the parameter keys */
+ ops = match_param(cschem, _STR);
+
+ /* For backwards compatibility, also try matching against */
+ /* the parameter default value (method used before */
+ /* implementing parameters as key:value pairs). */
+
+ if (ops == NULL) {
+ for (ops = cschem->params; ops != NULL; ops = ops->next) {
+ if (ops->type == XC_STRING) {
+ if (!textcomp(ops->parameter.string, _STR, NULL)) {
+ /* substitute the parameter or default */
+ instops = find_param(cinst, ops->key);
+ optr = instops->parameter.string;
+ if (stringlength(optr, True, cinst) > 0) {
+ snew = textprint(optr, cinst);
+ sout = (char *)realloc(sout, strlen(sout)
+ + strlen(snew) + 1);
+ strcat(sout, snew);
+ free(snew);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (ops == NULL) {
+ Wprintf("No parameter named %s in device %s",
+ _STR, cschem->name);
+ }
+ break;
+
+ default:
+ /* Presence of ".ends" statement forces xcircuit */
+ /* not to write ".end" at the end of the netlist. */
+
+ if (*strt == '.')
+ if (!strncmp(strt + 1, "ends", 4))
+ spice_end = FALSE;
+
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ *(sout + strlen(sout) - 1) = *strt;
+ *(sout + strlen(sout)) = '\0';
+ }
+ }
+ else {
+ if (key != NULL)
+ if (clist->devname == NULL)
+ clist->devname = strdup(sout);
+
+ /* Parameters with unresolved question marks are treated */
+ /* like a "%i" string. */
+
+ if ((key != NULL) && !textncomp(strptr, "?", cinst)) {
+ if (do_update || autonumber) {
+ if (is_flat || (cfrom == NULL))
+ newindex = devflatindex(clist->devname);
+ else
+ newindex = devindex(cfrom, clist);
+ k = strlen(sout);
+ b36str = d36a(newindex);
+ sout = (char *)realloc(sout, strlen(sout) + strlen(b36str) + 1);
+ sprintf(sout + k, "%s", b36str);
+ }
+
+ /* When called with autonumber = TRUE, generate a parameter */
+ /* instance, replacing the question mark with the new index */
+ /* number. */
+
+ if (autonumber) {
+ copyparams(cinst, cinst);
+ ops = match_instance_param(cinst, key);
+ optr = ops->parameter.string;
+ if (!textncomp(optr, "?", cinst)) {
+ optr->data.string = (char *)realloc(optr->data.string,
+ strlen(sout + k) + 1);
+ strcpy(optr->data.string, sout + k);
+ }
+ else Wprintf("Error while auto-numbering parameters");
+ resolveparams(cinst);
+ }
+ }
+ else {
+ /* A "?" default parameter that has a (different) */
+ /* instance value becomes the device number. */
+ int stlen;
+ if ((key != NULL) && (clist->devindex < 0)) {
+ ops = match_param(cschem, key);
+ if (ops->type == XC_STRING) {
+ CalllistPtr plist;
+ if (!textcomp(ops->parameter.string, "?", NULL)) {
+ if (is_flat) {
+ /* Ignore the value and generate one instead */
+ newindex = devflatindex(clist->devname);
+ b36str = d36a(newindex);
+ k = strlen(sout);
+ sout = (char *)realloc(sout, strlen(sout)
+ + strlen(b36str) + 1);
+ sprintf(sout + k, "%s", b36str);
+ continue; /* go on to next stringpart */
+ }
+ else if (cfrom != NULL) {
+
+ /* Interpret parameter string as a component */
+ /* number so we can check for duplicates. Assume */
+ /* a base-36 number, which includes all alphabet */
+ /* characters. This will disambiguate, e.g., "1" */
+ /* and "1R", but flag case-sensitivity, e.g., */
+ /* "1R" and "1r". Thanks to Carsten Thomas for */
+ /* pointing out the problem with assuming */
+ /* numerical component values. */
+
+ char *endptr;
+ newindex = (u_int) strtol(strt, &endptr, 36);
+ if (*endptr != '\0') {
+ Fprintf(stderr, "Warning: Use of non-alphanumeric"
+ " characters in component number \"%s\"\n", strt);
+ }
+ clist->devindex = newindex;
+ for (plist = cfrom->calls; plist; plist = plist->next) {
+ if ((plist == clist) ||
+ (plist->callobj != clist->callobj)) continue;
+
+ /* Two parts have been named the same. Flag */
+ /* it, but don't try to do anything about it. */
+ /* 11/22/06---additionally check part numbers, */
+ /* in case the symbol is a component sub-part. */
+
+ if (plist->devindex == newindex) {
+ if (samepart(plist, clist)) {
+ Fprintf(stderr, "Warning: duplicate part number"
+ " %s%s and %s%s\n", sout, strt, sout, strt);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ stlen = strlen(sout);
+ sout = (char *)realloc(sout, stlen + 2);
+
+ /* By convention, greek "mu" becomes ASCII "u", NOT "m", */
+ /* otherwise we get, e.g., millifarads instead of microfarads */
+
+ if ((is_symbol && (*strt == 'm')) || (is_iso && (*strt == 0265)))
+ *(sout + stlen) = 'u';
+ else
+ *(sout + stlen) = *strt;
+ *(sout + stlen + 1) = '\0';
+ }
+ }
+ }
+
+ /* Some label controls are interpreted. Most are ignored */
+ else {
+ switch(strptr->type) {
+ case PARAM_START:
+ key = strptr->data.string;
+ break;
+ case PARAM_END:
+ key = NULL;
+ break;
+ case RETURN:
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "\n");
+ break;
+ case TABFORWARD:
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "\t");
+ break;
+ case FONT_NAME:
+ is_symbol = issymbolfont(strptr->data.font);
+ is_iso = isisolatin1(strptr->data.font);
+ break;
+ }
+ }
+ }
+
+ /* Insert a newline between multiple valid info labels */
+ if (infoptr->next != NULL) {
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "\n");
+ }
+ }
+ freelabellist(&infoptr);
+
+ if (*sout == '\0') {
+ free(sout);
+ return NULL;
+ }
+ return sout;
+}
+
+/*----------------------------------------------------------------------*/
+/* Write a low-level device */
+/*----------------------------------------------------------------------*/
+
+int writedevice(FILE *fp, char *mode, objectptr cfrom, CalllistPtr clist,
+ char *prefix)
+{
+ char *sout;
+ objectptr cthis;
+
+ if (clist == NULL) {
+ if (fp != NULL) fprintf(fp, "error: null device\n");
+ return -1;
+ }
+
+ /* Devices are always symbols. If the call indicates a schematic */
+ /* and a separate associated symbol, then we want the symbol. */
+ /* If we're writing a flat netlist, then return -1 to indicate that */
+ /* the symbol instance needs to be flattened. */
+
+ cthis = clist->callobj;
+ if (clist->callobj->schemtype == PRIMARY || clist->callobj->schemtype ==
+ SECONDARY)
+ if (clist->callobj->symschem != NULL) {
+ if (!strncmp(mode, "flat", 4))
+ return -1;
+ else
+ cthis = clist->callobj->symschem;
+ }
+
+ /* Look for information labels in the object parts list. */
+
+ if ((sout = parseinfo(cfrom, cthis, clist, prefix, mode, FALSE, FALSE)) != NULL) {
+ if (fp != NULL) {
+ fputs(sout, fp);
+ fprintf(fp, "\n");
+ }
+ free(sout);
+ return 0;
+ }
+
+ /* Information labels do not necessarily exist. */
+ return -1;
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Translate a hierarchical net name into an object and instance. */
+/* Return TRUE if found, FALSE if not. If found, object and instance */
+/* are returned in the argument pointers. */
+/*----------------------------------------------------------------------*/
+
+Boolean HierNameToObject(objinstptr cinst, char *hiername, pushlistptr *stack)
+{
+ CalllistPtr calls;
+ char *nexttoken, *hptr, *pptr;
+ objectptr cschem, curobj, newobj;
+ objinstptr newinst;
+ int devindex, devlen;
+ /* pushlistptr stackentry; (jdk) */
+
+ cschem = cinst->thisobject;
+ curobj = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ if (curobj->calls == NULL) {
+ if ((updatenets(cinst, FALSE) <= 0) || (curobj->calls == NULL)) {
+ Wprintf("Error in generating netlists!");
+ return False;
+ }
+ }
+
+ hptr = hiername;
+ while (hptr != NULL) {
+ nexttoken = strchr(hptr, '/');
+ if (nexttoken != NULL) *nexttoken = '\0';
+ pptr = strrchr(hptr, '(');
+ if (pptr != NULL) {
+ if (sscanf(pptr + 1, "%d", &devindex) == 0) {
+ pptr = NULL;
+ devindex = 0;
+ }
+ else
+ *pptr = '\0';
+ }
+ else devindex = -1;
+
+ /* check to make sure that the netlist and device indices have been generated */
+ for (calls = curobj->calls; calls != NULL; calls = calls->next) {
+ if (calls->devindex == -1) {
+ cleartraversed(curobj);
+ resolve_indices(curobj, FALSE);
+ }
+ }
+
+ /* hptr is now the object name, and devindex is the instance's call index */
+ /* find the object corresponding to the name. */
+
+ newobj = NameToObject(hptr, &newinst, TRUE);
+
+ if (newobj == NULL) {
+
+ /* Try device names (for netlist output) instead of object names */
+
+ for (calls = curobj->calls; calls != NULL; calls = calls->next) {
+ if (calls->devname != NULL) {
+ devlen = strlen(calls->devname);
+ if (!strncmp(hptr, calls->devname, devlen)) {
+ if (devindex == -1) {
+ if (sscanf(hptr + devlen, "%d", &devindex) == 0)
+ devindex = 0;
+ }
+ if (calls->devindex == devindex) {
+ newobj = calls->callinst->thisobject;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (calls = curobj->calls; calls != NULL; calls = calls->next)
+ if ((calls->callobj == newobj) && (calls->devindex == devindex))
+ break;
+ }
+ if (newobj == NULL || calls == NULL) {
+ Fprintf(stderr, "object %s in hierarchy not found in schematic.\n", hptr);
+ free_stack(stack);
+ return FALSE;
+ }
+
+ /* Diagnostic information */
+ /* fprintf(stderr, "object %s(%d) = %s\n", newobj->name, devindex, hptr); */
+
+ curobj = calls->callobj;
+ push_stack(stack, calls->callinst, NULL);
+
+ if (pptr != NULL) *pptr = '(';
+ if (nexttoken == NULL) break;
+ *nexttoken = '/';
+ hptr = nexttoken + 1;
+ }
+ return TRUE;
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Save netlist into a flattened sim or spice file */
+/*----------------------------------------------------------------------*/
+
+void writeflat(objectptr cschem, CalllistPtr cfrom, char *prefix, FILE *fp, char *mode)
+{
+ CalllistPtr calls = cschem->calls;
+ char *newprefix = (char *)malloc(sizeof(char));
+
+ /* reset device indexes */
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next)
+ calls->devindex = -1;
+
+ /* The naming convention for nodes below the top level uses a */
+ /* slash-separated list of hierarchical names. Thus the call to */
+ /* the hierarchical resolve_indices(). Indices used by bottom-most */
+ /* symbols (e.g., flattened spice) will be generated by a separate */
+ /* routine devflatindex(), unrelated to what is generated here, */
+ /* which only affects the hierarchical naming of nodes. */
+
+ resolve_indices(cschem, FALSE);
+
+ /* write all the subcircuits */
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+
+ makelocalpins(cschem, calls, prefix);
+ if (writedevice(fp, mode, cschem, calls, prefix) < 0) {
+ sprintf(_STR, "%s_%u", calls->callobj->name,
+ devindex(cschem, calls));
+ newprefix = (char *)realloc(newprefix, sizeof(char) * (strlen(prefix)
+ + strlen(_STR) + 2));
+ sprintf(newprefix, "%s%s/", prefix, _STR);
+ /* Allow cross-referenced parameters between symbols and schematics */
+ /* by substituting into a schematic from its corresponding symbol */
+ opsubstitute(calls->callobj, calls->callinst);
+ /* psubstitute(calls->callinst); */
+ writeflat(calls->callobj, calls, newprefix, fp, mode);
+ }
+ clearlocalpins(calls->callobj);
+ }
+ free(newprefix);
+}
+
+/*----------------------------------------------------------------------*/
+/* Topmost call to write a flattened netlist */
+/*----------------------------------------------------------------------*/
+
+void topflat(objectptr cschem, objinstptr thisinst, CalllistPtr cfrom,
+ char *prefix, FILE *fp, char *mode)
+{
+ char *locmode, *stsave = NULL;
+ int modlen;
+ Calllist loccalls;
+
+ /* Set up local call list for parsing info labels in the top-level schematic */
+ loccalls.cschem = NULL;
+ loccalls.callobj = cschem;
+ loccalls.callinst = thisinst;
+ loccalls.devindex = -1;
+ loccalls.ports = NULL;
+ loccalls.next = NULL;
+
+ modlen = strlen(mode);
+ locmode = malloc(2 + modlen);
+ strcpy(locmode, mode);
+ locmode[modlen + 1] = '\0';
+
+ /* "<mode>@" lines go in front */
+
+ locmode[modlen] = '@';
+ if (fp != NULL) stsave = parseinfo(NULL, cschem, &loccalls, NULL, locmode, FALSE,
+ FALSE);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ free(stsave);
+ stsave = NULL;
+ }
+
+ writeflat(cschem, cfrom, prefix, fp, mode);
+ freeflatindex();
+
+ /* Check for negative-numbered info labels, indicated output that */
+ /* should be processed after everything else. */
+
+ locmode[modlen] = '-';
+ stsave = parseinfo(NULL, cschem, &loccalls, NULL, locmode, FALSE, FALSE);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ free(stsave);
+ stsave = NULL;
+ }
+ free(locmode);
+}
+
+/*----------------------------------------------------------------------*/
+/* Write out the list of global nets and their pin names */
+/*----------------------------------------------------------------------*/
+
+void writeglobals(objectptr cschem, FILE *fp)
+{
+ LabellistPtr llist;
+ labelptr gpin;
+ char *snew;
+
+ if (fp == NULL) return;
+
+ for (llist = global_labels; llist != NULL; llist = llist->next) {
+ gpin = llist->label;
+ snew = textprint(gpin->string, NULL);
+ fprintf(fp, ".GLOBAL %s\n", snew); /* hspice format */
+ /* fprintf(fp, "%s = %d\n", snew, -gptr->netid); */ /* generic format */
+ free(snew);
+ }
+ fprintf(fp, "\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* Write a SPICE subcircuit entry. */
+/*----------------------------------------------------------------------*/
+
+void writesubcircuit(FILE *fp, objectptr cschem)
+{
+ PortlistPtr ports;
+ char *pstring;
+ stringpart *ppin;
+ int netid, length, plen, subnet; /* portid, (jdk) */
+
+ /* Objects which have no ports are not written */
+ if ((cschem->ports != NULL) && (fp != NULL)) {
+
+ fprintf(fp, ".subckt %s", cschem->name);
+ length = 9 + strlen(cschem->name);
+
+ /* List of parameters in subcircuit. */
+ /* Each parameter connects to a net which may have multiple */
+ /* names, so find the net associated with the parameter */
+ /* and convert it back into a pin name in the usual manner */
+ /* using nettopin(). */
+
+ for (ports = cschem->ports; ports != NULL;
+ ports = ports->next) {
+ netid = ports->netid;
+ subnet = getsubnet(netid, cschem);
+ ppin = nettopin(netid, cschem, NULL);
+ pstring = textprintsubnet(ppin, NULL, subnet);
+ plen = strlen(pstring) + 1;
+ if (length + plen > 78) {
+ fprintf(fp, "\n+ "); /* SPICE line break & continuation */
+ length = 0;
+ }
+ else length += plen;
+ fprintf(fp, " %s", pstring);
+ free(pstring);
+ }
+ fprintf(fp, "\n");
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Resolve device names (fill calllist structure member "devname") */
+/*----------------------------------------------------------------------*/
+
+void resolve_devnames(objectptr cschem)
+{
+ CalllistPtr calls;
+ char *stmp;
+ oparamptr ops;
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ calls->callobj->traversed = True;
+ resolve_devnames(calls->callobj);
+ }
+
+ if (calls->devname == NULL) {
+
+ /* Check for "class" parameter. Note that although this */
+ /* parameter may take a different instance value, the */
+ /* device class is determined by the default value. */
+
+ ops = find_param(calls->callinst, "class");
+ if (ops && (ops->type == XC_STRING))
+ calls->devname = textprint(ops->parameter.string, NULL);
+ else {
+ /* The slow way---parse info labels for any device information */
+ if ((stmp = parseinfo(cschem, calls->callinst->thisobject, calls,
+ NULL, "", FALSE, TRUE)) != NULL)
+ free(stmp);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Resolve (hierarchical) component numbering. If "autonumber" is TRUE */
+/* then this routine does auto-numbering. Otherwise, it auto-generates */
+/* device indices internally (in the "calllist" structure) but does not */
+/* copy them into parameter space. */
+/* */
+/* Note: resolve_devindex() only operates on a single object. Use */
+/* resolve_indices() to operate on the entire hierarchy. */
+/*----------------------------------------------------------------------*/
+
+void resolve_devindex(objectptr cschem, Boolean autonumber)
+{
+ CalllistPtr calls;
+ char *stmp, *endptr;
+ char *idxtype[] = {"index", "idx", NULL};
+ oparamptr ops, ips;
+ objinstptr cinst;
+ stringpart *optr;
+ int newindex, j;
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+
+ /* Check if there is an "index" parameter set to "?" in */
+ /* the object with no existing instance value. */
+
+ for (j = 0; idxtype[j] != NULL; j++)
+ if ((ops = match_param(calls->callinst->thisobject, idxtype[j])) != NULL)
+ break;
+
+ if (ops && (ops->type == XC_STRING)) {
+ if (!textcomp(ops->parameter.string, "?", NULL)) {
+ cinst = calls->callinst;
+ ips = match_instance_param(cinst, idxtype[j]);
+ if ((autonumber == TRUE) && (ips == NULL)) {
+ copyparams(cinst, cinst);
+ ops = match_instance_param(cinst, idxtype[j]);
+ optr = ops->parameter.string;
+ newindex = devindex(cschem, calls);
+ stmp = d36a(newindex);
+ optr->data.string = (char *)realloc(optr->data.string, strlen(stmp) + 1);
+ sprintf(optr->data.string, "%s", stmp);
+ }
+ else if (calls->devindex < 0) {
+ if (ips != NULL) {
+ optr = ips->parameter.string;
+ if (optr->type != TEXT_STRING) {
+ /* Not a simple string. Dump the text. */
+ char *snew = NULL;
+ snew = textprint(optr, NULL),
+ newindex = (u_int) strtol(snew, &endptr, 36);
+ free(snew);
+ }
+ else {
+ newindex = (u_int) strtol(optr->data.string, &endptr, 36);
+ }
+ if (*endptr != '\0') {
+ /* It is possible to get an instance value that is */
+ /* the same as the default, although this normally */
+ /* doesn't happen. If it does, quietly remove the */
+ /* unneeded instance value. */
+
+ if (!stringcomp(ops->parameter.string, ips->parameter.string))
+ resolveparams(cinst);
+ else
+ Fprintf(stderr, "Warning: Use of non-alphanumeric"
+ " characters in component \"%s%s\" (instance"
+ " of %s)\n", (calls->devname) ? calls->devname
+ : calls->callobj->name, optr->data.string,
+ calls->callobj->name);
+ }
+ else
+ calls->devindex = newindex;
+ }
+ else /* if (autonumber) */
+ devindex(cschem, calls);
+ }
+ }
+ }
+ else {
+ /* The slow way---parse info labels for any index information */
+ if ((stmp = parseinfo(cschem, calls->callinst->thisobject, calls,
+ NULL, "", autonumber, TRUE)) != NULL)
+ free(stmp);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive call to resolve_devindex() through the circuit hierarchy */
+/*----------------------------------------------------------------------*/
+
+void resolve_indices(objectptr cschem, Boolean autonumber) {
+ CalllistPtr calls;
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ calls->callobj->traversed = True;
+ resolve_indices(calls->callobj, autonumber);
+ }
+ }
+ resolve_devindex(cschem, autonumber);
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive call to clear all generated device numbers. */
+/*----------------------------------------------------------------------*/
+
+void clear_indices(objectptr cschem) {
+ CalllistPtr calls;
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ calls->callobj->traversed = True;
+ clear_indices(calls->callobj);
+ }
+ calls->devindex = -1;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive call to clear all device indexes (parameter "index") */
+/*----------------------------------------------------------------------*/
+
+void unnumber(objectptr cschem) {
+ CalllistPtr calls;
+ oparamptr ops, ips;
+ char *idxtype[] = {"index", "idx", NULL};
+ int j;
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ calls->callobj->traversed = True;
+ unnumber(calls->callobj);
+ }
+
+ for (j = 0; idxtype[j] != NULL; j++)
+ if ((ops = match_param(calls->callobj, idxtype[j])) != NULL) break;
+
+ if (ops && (ops->type == XC_STRING)) {
+ if (!textcomp(ops->parameter.string, "?", NULL)) {
+ ips = match_instance_param(calls->callinst, idxtype[j]);
+ if (ips != NULL)
+ free_instance_param(calls->callinst, ips);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Save netlist into a hierarchical file */
+/*----------------------------------------------------------------------*/
+
+void writehierarchy(objectptr cschem, objinstptr thisinst, CalllistPtr cfrom,
+ FILE *fp, char *mode)
+{
+ CalllistPtr calls = cschem->calls;
+ PortlistPtr ports, plist;
+ int pnet, portid, length, plen, subnet, modlen; /* netid, (jdk) */
+ char *locmode = mode, *stsave = NULL, *pstring;
+ stringpart *ppin;
+ Calllist loccalls;
+
+ if (cschem->traversed == True) return;
+
+ /* Set up local call list for parsing info labels in this schematic */
+ loccalls.cschem = NULL;
+ loccalls.callobj = cschem;
+ loccalls.callinst = thisinst;
+ loccalls.devindex = -1;
+ loccalls.ports = NULL;
+ loccalls.next = NULL;
+
+ modlen = strlen(mode);
+ locmode = malloc(2 + modlen);
+ strcpy(locmode, mode);
+ locmode[modlen + 1] = '\0';
+
+ /* "<mode>@" lines go before any subcircuit calls */
+
+ locmode[modlen] = '@';
+ if (fp != NULL) stsave = parseinfo(NULL, cschem, &loccalls, NULL, locmode, FALSE,
+ FALSE);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ free(stsave);
+ stsave = NULL;
+ }
+
+ /* Subcircuits which make no calls or have no devices do not get written */
+
+ if (calls != NULL) {
+
+ /* Make sure that all the subcircuits have been written first */
+
+ for (; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ psubstitute(calls->callinst);
+ writehierarchy(calls->callobj, calls->callinst, calls, fp, mode);
+ calls->callobj->traversed = True;
+ }
+ }
+ if (cschem->schemtype == FUNDAMENTAL) {
+ free(locmode);
+ return;
+ }
+ }
+
+ /* Info-labels on a schematic (if any) get printed out first */
+
+ if ((fp != NULL) && (cschem->calls != NULL)) {
+ stsave = parseinfo(NULL, cschem, &loccalls, NULL, mode, FALSE, FALSE);
+ if (stsave != NULL) {
+
+ /* Check stsave for embedded SPICE subcircuit syntax */
+
+ if (!strcmp(mode, "spice"))
+ if (strstr(stsave, ".subckt ") == NULL)
+ writesubcircuit(fp, cschem);
+
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ free(stsave);
+ stsave = NULL;
+ }
+ else if (cschem->calls != NULL)
+ /* top-level schematics will be ignored because they have no ports */
+ writesubcircuit(fp, cschem);
+ }
+
+ /* Resolve all fixed part assignments (devindex) */
+ resolve_devindex(cschem, FALSE);
+
+ /* If the output file is NULL, then we're done */
+
+ if (fp == NULL) {
+ free(locmode);
+ return;
+ }
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+
+ /* writedevice() is just another call to parseinfo() */
+ if (writedevice(fp, mode, cschem, calls, NULL) < 0) {
+
+ /* If the device did not produce any output in writedevice(), but */
+ /* does not make any calls itself, then it is implicitly a TRIVIAL */
+ /* symbol. */
+
+ if ((calls->callobj->schemtype == TRIVIAL) || (calls->callobj->calls == NULL))
+ continue;
+
+ /* No syntax indicating how to write this call. Use SPICE "X" */
+ /* format and arrange the parameters according to the structure. */
+
+ calls->devname = strdup(spice_devname);
+ fprintf(fp, "X%s", d36a(devindex(cschem, calls)));
+ stsave = calls->callobj->name;
+ length = 6;
+
+ /* The object's definition lists calls in the order of the object's */
+ /* port list. Therefore, use this order to find the port list. */
+ /* This will also deal with the fact that not every port has to be */
+ /* called by the instance (ports may be left disconnected). */
+
+ for (ports = calls->callobj->ports; ports != NULL;
+ ports = ports->next) {
+ portid = ports->portid;
+ for (plist = calls->ports; plist != NULL; plist = plist->next)
+ if (plist->portid == ports->portid)
+ break;
+
+ pnet = (plist == NULL) ? netmax(cschem) + 1 : plist->netid;
+ subnet = getsubnet(pnet, cschem);
+ ppin = nettopin(pnet, cschem, NULL);
+ pstring = textprintsubnet(ppin, NULL, subnet);
+ plen = strlen(pstring) + 1;
+ if (length + plen > 78) {
+ fprintf(fp, "\n+ "); /* SPICE line continuation */
+ length = 0;
+ }
+ else length += plen;
+ fprintf(fp, " %s", pstring);
+ free(pstring);
+ }
+ plen = 1 + strlen(stsave);
+ if (length + plen > 78) fprintf(fp, "\n+ "); /* SPICE line cont. */
+ fprintf(fp, " %s\n", stsave);
+ }
+ }
+
+ /* Check for negative-numbered info labels, indicated output that */
+ /* should be processed after everything else. If we're processing */
+ /* SPICE output but the schematic does not provide a ".ends" */
+ /* statement, then add it to the end of the deck. */
+
+ if (cschem->calls != NULL) {
+ locmode[modlen] = '-';
+ stsave = parseinfo(NULL, cschem, &loccalls, NULL, locmode, FALSE, FALSE);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ if (cfrom != NULL)
+ if (!strcmp(mode, "spice"))
+ if (strstr(stsave, ".ends") == NULL)
+ fprintf(fp, ".ends\n");
+ free(stsave);
+ }
+ else if (cfrom != NULL)
+ fprintf(fp, ".ends\n");
+
+ fprintf(fp, "\n");
+ }
+
+ free(locmode);
+}
+
+/*----------------------------------------------------------------------*/
+/* Create generic netlist in the Tcl interpreter variable space */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+static Tcl_Obj *tclparseinfo(objectptr cschem)
+{
+ genericptr *pgen;
+ labelptr plabel;
+
+ Tcl_Obj *rlist = Tcl_NewListObj(0, NULL);
+
+ for (pgen = cschem->plist; pgen < cschem->plist + cschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plabel = TOLABEL(pgen);
+ if (plabel->pin == INFO) {
+ Tcl_ListObjAppendElement(xcinterp, rlist,
+ TclGetStringParts(plabel->string));
+ }
+ }
+ }
+ return rlist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Write global variables to Tcl list (in key-value pairs which can be */
+/* turned into an array variable using the "array set" command) */
+/* */
+/* Note: argument "cinst" is unused, but it really should be. We */
+/* should not assume that different schematics have the same list of */
+/* globals! */
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *tclglobals(objinstptr cinst)
+{
+ LabellistPtr llist;
+ labelptr gpin;
+ Tcl_Obj *gdict; /*, *netnum; (jdk) */
+ buslist *sbus;
+ int netid, lbus;
+
+ gdict = Tcl_NewListObj(0, NULL);
+ for (llist = global_labels; llist != NULL; llist = llist->next) {
+ gpin = llist->label;
+ Tcl_ListObjAppendElement(xcinterp, gdict, TclGetStringParts(gpin->string));
+ for (lbus = 0;;) {
+ if (llist->subnets == 0) {
+ netid = llist->net.id;
+ }
+ else {
+ sbus = llist->net.list + lbus;
+ netid = sbus->netid;
+ }
+ Tcl_ListObjAppendElement(xcinterp, gdict, Tcl_NewIntObj(netid));
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+ return gdict;
+}
+
+/*----------------------------------------------------------------------*/
+/* Write a generic hierarchical netlist into Tcl list "subcircuits" */
+/*----------------------------------------------------------------------*/
+
+void tclhierarchy(objectptr cschem, objinstptr cinst, CalllistPtr cfrom, Tcl_Obj *cktlist)
+{
+ CalllistPtr calls = cschem->calls;
+ PortlistPtr ports, plist;
+ int netid, pnet, portid; /* , length, plen, i; (jdk) */
+ Tcl_Obj *tclports, *tclcalls, *tclnewcall, *tclnets, *netnum;
+ Tcl_Obj *tcldevs, *tclparams, *subckt, *newdev, *tcllabel, *portnum;
+ oparamptr paramlist; /* , locparam; (jdk) */
+ char *netsdone;
+
+ /* Trivial objects are by definition those that are supposed */
+ /* to be resolved by the netlist generation prior to output */
+ /* and ignored by the output generator. */
+
+ if (cschem->schemtype == TRIVIAL) return;
+
+ /* Make sure that all the subcircuits have been written first */
+
+ for (; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ tclhierarchy(calls->callobj, calls->callinst, calls, cktlist);
+ calls->callobj->traversed = True;
+ }
+ }
+
+ /* Write own subcircuit netlist */
+ subckt = Tcl_NewListObj(0, NULL);
+
+ /* Prepare the list of network cross-references */
+ tclnets = Tcl_NewListObj(0, NULL);
+
+ /* Make list of the nets which have been written so we don't redundantly */
+ /* list any entries (use of calloc() initializes all entries to FALSE). */
+ /* (calloc() replaced by malloc() and bzero() because Tcl doesn't */
+ /* have a calloc() function (2/6/04)) */
+
+ netsdone = (char *)malloc(2 + netmax(cschem));
+#ifdef _MSC_VER
+ memset((void *)netsdone, 0, 2 + netmax(cschem));
+#else
+ bzero((void *)netsdone, 2 + netmax(cschem));
+#endif
+
+ /* Write the name (key value pair) */
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("name", 4));
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj(cschem->name,
+ strlen(cschem->name)));
+
+ /* Write the handle of the object instance (key value pair) */
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("handle", 6));
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewHandleObj(cinst));
+
+ /* Write the list of ports */
+ if ((ports = cschem->ports) != NULL) {
+
+ /* List of ports in subcircuit. */
+ /* Each parameter connects to a net which may have multiple */
+ /* names, so find the net associated with the parameter */
+ /* and convert it back into a pin name in the usual manner */
+ /* using nettopin(). */
+
+ tclports = Tcl_NewListObj(0, NULL);
+ for (; ports != NULL; ports = ports->next) {
+ netid = ports->netid;
+ portid = ports->portid;
+ netnum = Tcl_NewIntObj(netid);
+ portnum = Tcl_NewIntObj(portid);
+ Tcl_ListObjAppendElement(xcinterp, tclports, portnum);
+ Tcl_ListObjAppendElement(xcinterp, tclports, netnum);
+ if ((netid >= 0) && (netsdone[netid] == (char)0))
+ {
+ Tcl_ListObjAppendElement(xcinterp, tclnets, netnum);
+ Tcl_ListObjAppendElement(xcinterp, tclnets,
+ TclGetStringParts(nettopin(netid, cschem, NULL)));
+ /* record this net as having been added to the list */
+ netsdone[netid] = (char)1;
+ }
+ }
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("ports", 5));
+ Tcl_ListObjAppendElement(xcinterp, subckt, tclports);
+ }
+
+ /* Write the list of parameter defaults (key:value pairs) */
+
+ if (cschem->params != NULL) {
+ tclparams = Tcl_NewListObj(0, NULL);
+
+ for (paramlist = cschem->params; paramlist != NULL; paramlist = paramlist->next) {
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewStringObj(paramlist->key, strlen(paramlist->key)));
+ switch(paramlist->type) {
+ case XC_INT:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewIntObj((int)paramlist->parameter.ivalue));
+ break;
+ case XC_FLOAT:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewDoubleObj((double)paramlist->parameter.fvalue));
+ break;
+ case XC_STRING:
+ tcllabel = TclGetStringParts(paramlist->parameter.string);
+ /* Should get rid of last entry, "End Parameter"; not needed */
+ Tcl_ListObjAppendElement(xcinterp, tclparams, tcllabel);
+ break;
+ case XC_EXPR:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ evaluate_raw(cschem, paramlist, cinst, NULL));
+ break;
+ }
+ }
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("parameters", 10));
+ Tcl_ListObjAppendElement(xcinterp, subckt, tclparams);
+ }
+
+ /* Write the list of calls to subcircuits */
+
+ if ((calls = cschem->calls) != NULL) {
+ tclcalls = Tcl_NewListObj(0, NULL);
+ for (; calls != NULL; calls = calls->next) {
+
+ /* Don't write calls to non-functional subcircuits. */
+ if (calls->callobj->schemtype == TRIVIAL) continue;
+
+ tclnewcall = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall, Tcl_NewStringObj("name", 4));
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall,
+ Tcl_NewStringObj(calls->callobj->name,
+ strlen(calls->callobj->name)));
+
+
+ /* Log any local parameter instances */
+ if (calls->callinst->params != NULL) {
+ tclparams = Tcl_NewListObj(0, NULL);
+
+ for (paramlist = calls->callinst->params; paramlist != NULL;
+ paramlist = paramlist->next) {
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewStringObj(paramlist->key, strlen(paramlist->key)));
+ switch(paramlist->type) {
+ case XC_INT:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewIntObj((int)paramlist->parameter.ivalue));
+ break;
+ case XC_FLOAT:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ Tcl_NewDoubleObj((double)paramlist->parameter.fvalue));
+ break;
+ case XC_STRING:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ TclGetStringParts(paramlist->parameter.string));
+ break;
+ case XC_EXPR:
+ Tcl_ListObjAppendElement(xcinterp, tclparams,
+ evaluate_raw(cschem, paramlist, cinst, NULL));
+ break;
+ }
+ }
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall,
+ Tcl_NewStringObj("parameters", 10));
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall, tclparams);
+ }
+
+ /* Called ports are listed by key:value pair (port number: net id) */
+
+ if (calls->callobj->ports != NULL) {
+ tclports = Tcl_NewListObj(0, NULL);
+ for (ports = calls->callobj->ports; ports != NULL;
+ ports = ports->next) {
+ portid = ports->portid;
+ for (plist = calls->ports; plist != NULL; plist = plist->next)
+ if (plist->portid == ports->portid)
+ break;
+
+ pnet = (plist == NULL) ? netmax(cschem) + 1 : plist->netid;
+
+ netnum = Tcl_NewIntObj((int)pnet);
+ portnum = Tcl_NewIntObj(portid);
+ Tcl_ListObjAppendElement(xcinterp, tclports, portnum);
+ Tcl_ListObjAppendElement(xcinterp, tclports, netnum);
+ if ((pnet >= 0) && (netsdone[pnet] == (char)0))
+ {
+ Tcl_ListObjAppendElement(xcinterp, tclnets, netnum);
+ Tcl_ListObjAppendElement(xcinterp, tclnets,
+ TclGetStringParts(nettopin(pnet, cschem, NULL)));
+ /* record this net as having been added to the list */
+ netsdone[pnet] = (char)1;
+ }
+ }
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall,
+ Tcl_NewStringObj("ports", 5));
+ Tcl_ListObjAppendElement(xcinterp, tclnewcall, tclports);
+ }
+ Tcl_ListObjAppendElement(xcinterp, tclcalls, tclnewcall);
+ }
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("calls", 5));
+ Tcl_ListObjAppendElement(xcinterp, subckt, tclcalls);
+ }
+ free(netsdone);
+
+ /* If the object has info labels, write a device list. */
+ /* Check both the schematic and its symbol for info labels. */
+
+ tcldevs = Tcl_NewListObj(0, NULL);
+ if (cschem->symschem != NULL) {
+ newdev = tclparseinfo(cschem->symschem);
+ Tcl_ListObjAppendElement(xcinterp, tcldevs, newdev);
+ }
+ newdev = tclparseinfo(cschem);
+ Tcl_ListObjAppendElement(xcinterp, tcldevs, newdev);
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("devices", 7));
+ Tcl_ListObjAppendElement(xcinterp, subckt, tcldevs);
+
+ /* Write the network cross-reference dictionary */
+ Tcl_ListObjAppendElement(xcinterp, subckt, Tcl_NewStringObj("nets", 4));
+ Tcl_ListObjAppendElement(xcinterp, subckt, tclnets);
+
+ Tcl_ListObjAppendElement(xcinterp, cktlist, subckt);
+}
+
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *tcltoplevel(objinstptr cinst)
+{
+ Tcl_Obj *cktlist;
+ objectptr cschem = cinst->thisobject;
+
+ cktlist = Tcl_NewListObj(0, NULL);
+ cleartraversed(cschem);
+ tclhierarchy(cschem, cinst, NULL, cktlist);
+ return cktlist;
+}
+
+#endif /* TCL_WRAPPER */
+
+/*----------------------------------------------------------------------*/
+/* Create generic netlist in the Python interpreter variable space */
+/*----------------------------------------------------------------------*/
+
+#ifdef HAVE_PYTHON
+
+static PyObject *pyparseinfo(objectptr cschem)
+{
+ genericptr *pgen;
+ labelptr plabel;
+
+ PyObject *rlist = PyList_New(0);
+
+ for (pgen = cschem->plist; pgen < cschem->plist + cschem->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ plabel = TOLABEL(pgen);
+ if (plabel->pin == INFO)
+ PyList_Append(rlist, PyGetStringParts(plabel->string));
+ }
+ }
+ return rlist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Write global variables to Python dictionary */
+/*----------------------------------------------------------------------*/
+
+PyObject *pyglobals(objectptr cschem)
+{
+ LabellistPtr llist;
+ labelptr gpin;
+ PyObject *gdict, *netnum;
+ int netid, lbus;
+ buslist *sbus;
+
+ gdict = PyDict_New();
+ for (llist = global_labels; llist != NULL; llist = llist->next) {
+ gpin = llist->label;
+ for (lbus = 0;;) {
+ if (llist->subnets == 0)
+ netid = llist->net.id;
+ else {
+ sbus = llist->net.list + lbus;
+ netid = sbus->netid;
+ }
+ netnum = PyInt_FromLong((long)(netid));
+ PyDict_SetItem(gdict, netnum, PyGetStringParts(gpin->string));
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+ return gdict;
+}
+
+/*----------------------------------------------------------------------*/
+/* Write a generic hierarchical netlist into Python list "subcircuits" */
+/*----------------------------------------------------------------------*/
+
+void pyhierarchy(objectptr cschem, CalllistPtr cfrom, PyObject *cktlist)
+{
+ CalllistPtr calls = cschem->calls;
+ PortlistPtr ports, plist;
+ int netid, pnet, portid, length, plen, i;
+ PyObject *pyports, *pycalls, *pynewcall, *pynets, *netnum;
+ PyObject *pydevs, *pyparams, *subckt, *newdev, *pylabel;
+ oparamptr paramlist;
+
+ /* Trivial objects are by definition those that are supposed */
+ /* to be resolved by the netlist generation prior to output */
+ /* and ignored by the output generator. */
+
+ if (cschem->schemtype == TRIVIAL) return;
+
+ /* Make sure that all the subcircuits have been written first */
+
+ for (; calls != NULL; calls = calls->next) {
+ if (calls->callobj->traversed == False) {
+ calls->callobj->traversed = True;
+ pyhierarchy(calls->callobj, calls, cktlist);
+ }
+ }
+
+ /* Write own subcircuit netlist */
+ subckt = PyDict_New();
+
+ /* Prepare the dictionary of network cross-references */
+ pynets = PyDict_New();
+
+ /* Write the name */
+ PyDict_SetItem(subckt, PyString_FromString("name"),
+ PyString_FromString(cschem->name));
+
+ /* Write the list of ports */
+ if ((ports = cschem->ports) != NULL) {
+
+ /* List of ports in subcircuit. */
+ /* Each parameter connects to a net which may have multiple */
+ /* names, so find the net associated with the parameter */
+ /* and convert it back into a pin name in the usual manner */
+ /* using nettopin(). */
+
+ pyports = PyList_New(0);
+ for (; ports != NULL; ports = ports->next) {
+ netid = ports->netid;
+ netnum = PyInt_FromLong((long)netid);
+ PyList_Append(pyports, netnum);
+ if (netid >= 0)
+ PyDict_SetItem(pynets, netnum,
+ PyGetStringParts(nettopin(netid, cschem, NULL)));
+ }
+ PyDict_SetItem(subckt, PyString_FromString("ports"), pyports);
+ }
+
+ /* Write the list of parameters */
+
+ if (cschem->params != NULL) {
+ pyparams = PyList_New(0);
+
+ for (paramlist = cschem->params; paramlist != NULL; paramlist = paramlist->next) {
+ if (paramlist->type == XC_INT)
+ PyList_Append(pyparams,
+ PyInt_FromLong((long)paramlist->parameter.ivalue));
+ if (paramlist->type == XC_FLOAT)
+ PyList_Append(pyparams,
+ PyFloat_FromDouble((double)paramlist->parameter.fvalue));
+ else if (paramlist->type == XC_STRING) {
+ pylabel = PyGetStringParts(paramlist->parameter.string);
+ /* Should get rid of last entry, "End Parameter"; not needed */
+ PyList_Append(pyparams, pylabel);
+ }
+ }
+ PyDict_SetItem(subckt, PyString_FromString("parameters"), pyparams);
+ }
+
+ /* Write the list of calls to subcircuits */
+
+ if ((calls = cschem->calls) != NULL) {
+ pycalls = PyList_New(0);
+ for (; calls != NULL; calls = calls->next) {
+
+ /* Don't write calls to non-functional subcircuits. */
+ if (calls->callobj->schemtype == TRIVIAL) continue;
+
+ pynewcall = PyDict_New();
+ PyDict_SetItem(pynewcall, PyString_FromString("name"),
+ PyString_FromString(calls->callobj->name));
+
+ /* Log any local parameter instances */
+ if (calls->callinst->params != NULL) {
+ pyparams = PyList_New(0);
+
+ for (paramlist = cschem->params; paramlist != NULL;
+ paramlist = paramlist->next) {
+ if (paramlist->type == XC_INT)
+ PyList_Append(pyparams,
+ PyInt_FromLong((long)paramlist->parameter.ivalue));
+ else if (paramlist->type == XC_FLOAT)
+ PyList_Append(pyparams,
+ PyFloat_FromDouble((double)paramlist->parameter.fvalue));
+ else if (paramlist->type == XC_STRING)
+ PyList_Append(pyparams,
+ PyGetStringParts(paramlist->parameter.string));
+ }
+ PyDict_SetItem(pynewcall, PyString_FromString("parameters"),
+ pyparams);
+ }
+
+ /* The object's definition lists calls in the order of the object's */
+ /* port list. Therefore, use this order to find the port list. */
+ /* Unconnected ports will be NULL entries in the list (?). */
+
+ if (calls->callobj->ports != NULL) {
+ pyports = PyList_New(0);
+ for (ports = calls->callobj->ports; ports != NULL;
+ ports = ports->next) {
+ portid = ports->portid;
+ for (plist = calls->ports; plist != NULL; plist = plist->next)
+ if (plist->portid == ports->portid)
+ break;
+
+ pnet = (plist == NULL) ? netmax(cschem) + 1 : plist->netid;
+
+ netnum = PyInt_FromLong((long)pnet);
+ PyList_Append(pyports, netnum);
+ if (pnet >= 0)
+ PyDict_SetItem(pynets, netnum,
+ PyGetStringParts(nettopin(pnet, cschem, NULL)));
+ }
+ PyDict_SetItem(pynewcall, PyString_FromString("ports"), pyports);
+ }
+ PyList_Append(pycalls, pynewcall);
+ }
+ PyDict_SetItem(subckt, PyString_FromString("calls"), pycalls);
+ }
+
+ /* If the object has info labels, write a device list. */
+ /* Check both the schematic and its symbol for info labels. */
+
+ pydevs = PyList_New(0);
+ if (cschem->symschem != NULL) {
+ newdev = pyparseinfo(cschem->symschem);
+ PyList_Append(pydevs, newdev);
+ }
+ newdev = pyparseinfo(cschem);
+ PyList_Append(pydevs, newdev);
+ PyDict_SetItem(subckt, PyString_FromString("devices"), pydevs);
+
+ /* Write the network cross-reference dictionary */
+ PyDict_SetItem(subckt, PyString_FromString("nets"), pynets);
+
+ PyList_Append(cktlist, subckt);
+}
+
+/*----------------------------------------------------------------------*/
+
+PyObject *pytoplevel(objectptr cschem)
+{
+ PyObject *cktlist;
+
+ cktlist = PyList_New(0);
+ cleartraversed(cschem);
+ pyhierarchy(cschem, NULL, cktlist);
+ return cktlist;
+}
+
+#endif /* HAVE_PYTHON */
+
+/*----------------------------------------------------------------------*/
+/* Update networks in an object by checking if the network is valid, */
+/* and destroying and recreating the network if necessary. */
+/* */
+/* Run cleartraversed() on all types. The traversed flag allows a */
+/* check for infinite recursion when creating calls. */
+/* */
+/* Returns -1 on discovery of infinite recursion, 0 on failure to */
+/* generate a net, and 1 on success. */
+/*----------------------------------------------------------------------*/
+
+int updatenets(objinstptr uinst, Boolean quiet) {
+ objectptr thisobject;
+ objinstptr thisinst;
+ int spage;
+
+ /* Never try to generate a netlist while a file is being read, as */
+ /* can happen if an expression parameter attempts to query a netlist */
+ /* node. */
+
+ if (load_in_progress) return 0;
+
+ if (uinst->thisobject->symschem != NULL
+ && uinst->thisobject->schemtype != PRIMARY) {
+ thisobject = uinst->thisobject->symschem;
+ if ((spage = is_page(thisobject)) >= 0)
+ thisinst = xobjs.pagelist[spage]->pageinst;
+ }
+ else {
+ thisobject = uinst->thisobject;
+ thisinst = uinst;
+ }
+
+ if (checkvalid(thisobject) == -1) {
+ uselection *ssave;
+
+ if (cleartraversed(thisobject) == -1) {
+ Wprintf("Netlist error: Check for recursion in circuit!");
+ return -1;
+ }
+
+ /* Note: destroy/create nets messes up the part list. Why?? */
+
+ if (areawin->selects > 0)
+ ssave = remember_selection(areawin->topinstance, areawin->selectlist,
+ areawin->selects);
+ destroynets(thisobject);
+ createnets(thisinst, quiet);
+ if (areawin->selects > 0) {
+ areawin->selectlist = regen_selection(areawin->topinstance, ssave);
+ free_selection(ssave);
+ }
+ }
+
+ if (thisobject->labels == NULL && thisobject->polygons == NULL) {
+ if (quiet == FALSE)
+ Wprintf("Netlist error: No netlist elements in object %s",
+ thisobject->name);
+ return 0;
+ }
+ return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate netlist, write information according to mode, and then */
+/* destroy the netlist (this will be replaced eventually with a dynamic */
+/* netlist model in which the netlist changes according to editing of */
+/* individual elements, not created and destroyed wholesale) */
+/*----------------------------------------------------------------------*/
+
+void writenet(objectptr thisobject, char *mode, char *suffix)
+{
+ objectptr cschem;
+ objinstptr thisinst;
+ char filename[100];
+ char *prefix, *cpos, *locmode = mode, *stsave = NULL;
+ FILE *fp;
+ /* Calllist topcell; (jdk) */
+ Boolean is_spice = FALSE, sp_end_save = spice_end;
+
+ /* Always use the master schematic, if there is one. */
+
+ if (thisobject->schemtype == SECONDARY)
+ cschem = thisobject->symschem;
+ else
+ cschem = thisobject;
+
+ /* Update the netlist if this has not been done */
+
+ if (NameToPageObject(cschem->name, &thisinst, NULL) == NULL) {
+ Wprintf("Not a schematic. . . cannot generate output!\n");
+ return;
+ }
+ if (updatenets(thisinst, FALSE) <= 0) {
+ Wprintf("No file written!");
+ return;
+ }
+
+ prefix = (char *)malloc(sizeof(char));
+ *prefix = '\0';
+
+ if ((cpos = strchr(cschem->name, ':')) != NULL) *cpos = '\0';
+ sprintf(filename, "%s.%s", cschem->name, suffix);
+ if (cpos != NULL) *cpos = ':';
+
+ if (!strncmp(mode, "index", 5)) { /* This mode generates no output */
+ locmode += 5;
+ fp = (FILE *)NULL;
+ }
+ else if ((fp = fopen(filename, "w")) == NULL) {
+ Wprintf("Could not open file %s for writing.", filename);
+ free(prefix);
+ return;
+ }
+
+ /* Clear device indices from any previous netlist output */
+ cleartraversed(cschem);
+ clear_indices(cschem);
+
+ /* Make sure list of include-once files is empty */
+
+ free_included();
+
+ /* Handle different netlist modes */
+
+ if (!strcmp(mode, "spice")) {
+
+ if (thisobject->schemtype == SYMBOL)
+ cschem = thisobject->symschem;
+
+ is_spice = TRUE;
+ fprintf(fp, "*SPICE %scircuit <%s> from XCircuit v%g rev %d\n\n",
+ (thisobject->schemtype == SYMBOL) ? "sub" : "",
+ cschem->name, PROG_VERSION, PROG_REVISION);
+
+ /* writeglobals(cschem, fp); */
+ cleartraversed(cschem);
+ writehierarchy(cschem, thisinst, NULL, fp, mode);
+ }
+ else if (!strcmp(mode, "flatspice")) {
+ is_spice = TRUE;
+ fprintf(fp, "*SPICE (flattened) circuit \"%s\" from XCircuit v%g rev %d\n\n",
+ cschem->name, PROG_VERSION, PROG_REVISION);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ }
+ topflat(cschem, thisinst, NULL, prefix, fp, mode);
+ }
+ else if (!strcmp(mode, "pseuspice")) {
+ is_spice = TRUE;
+ fprintf(fp, "*SPICE subcircuit \"%s\" from XCircuit v%g rev %d\n\n",
+ cschem->name, PROG_VERSION, PROG_REVISION);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ }
+ writeflat(cschem, NULL, prefix, fp, mode);
+ freeflatindex();
+ }
+ else if (!strcmp(mode, "flatsim") || !strcmp(mode, "pseusim")) {
+ fprintf(fp, "| sim circuit \"%s\" from XCircuit v%3.2f rev %d\n",
+ cschem->name, PROG_VERSION, PROG_REVISION);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ }
+ topflat(cschem, thisinst, NULL, prefix, fp, mode);
+ }
+ else if (!strcmp(locmode, "pcb")) {
+ struct Ptab *ptable = (struct Ptab *)NULL;
+ writepcb(&ptable, cschem, NULL, "", mode);
+ if (stsave != NULL) {
+ fputs(stsave, fp);
+ fprintf(fp, "\n");
+ }
+ outputpcb(ptable, fp);
+ freepcb(ptable);
+ }
+ else if (!strncmp(mode, "flat", 4)) {
+ /* User-defined modes beginning with the word "flat": */
+ /* Assume a flattened netlist, and assume nothing else. */
+
+ if (thisobject->schemtype == SYMBOL)
+ cschem = thisobject->symschem;
+ cleartraversed(cschem);
+ writeflat(cschem, NULL, prefix, fp, mode);
+ freeflatindex();
+ }
+ else if (!strncmp(mode, "pseu", 4)) {
+ /* User-defined modes beginning with the word "pseu": */
+ /* Assume a flattened netlist for everything under the top level. */
+
+ if (thisobject->schemtype == SYMBOL)
+ cschem = thisobject->symschem;
+ cleartraversed(cschem);
+ topflat(cschem, thisinst, NULL, prefix, fp, mode);
+ }
+ else {
+ /* All user-defined modes: Assume a hierarchical netlist, and */
+ /* assume nothing else. */
+
+ if (thisobject->schemtype == SYMBOL)
+ cschem = thisobject->symschem;
+ cleartraversed(cschem);
+ writehierarchy(cschem, thisinst, NULL, fp, mode);
+ }
+
+ /* Finish up SPICE files with a ".end" statement (if requested) */
+ if (is_spice && (spice_end == True)) fprintf(fp, ".end\n");
+ spice_end = sp_end_save;
+
+ /* Finish up */
+
+ if (fp != NULL) {
+ fclose(fp);
+ Wprintf("%s netlist saved as %s", mode, filename);
+ }
+ if (stsave != NULL) free(stsave);
+ free(prefix);
+}
+
+/*----------------------------------------------------------------------*/
+/* Flatten netlist and save into a table of pcb-style nets */
+/* The routine is recursive. Each call returns TRUE if some nested */
+/* call generated output; this is a reasonable way to tell if we have */
+/* reached the bottom of the hierarchy. */
+/*----------------------------------------------------------------------*/
+
+Boolean writepcb(struct Ptab **ptableptr, objectptr cschem, CalllistPtr cfrom,
+ char *prefix, char *mode)
+{
+ PolylistPtr plist;
+ LabellistPtr llist;
+ CalllistPtr calls;
+ PortlistPtr ports;
+ int i, testnet, tmplen, subnet;
+ char *newprefix = (char *)malloc(sizeof(char));
+ char *sout, *snew;
+ struct Ptab *hidx, *htmp;
+ struct Pstr *tmpstr;
+ struct Pnet *tmpnet;
+ objinstptr cinst;
+ buslist *sbus;
+ int locnet, lbus;
+ Boolean outputdone = FALSE;
+ Boolean outputcall;
+
+ /* Step 1A: Go through the polygons of this object and add */
+ /* any unvisited nets to the table. */
+
+ for (plist = cschem->polygons; plist != NULL; plist = plist->next) {
+ for (lbus = 0;;) {
+ if (plist->subnets == 0)
+ testnet = plist->net.id;
+ else {
+ sbus = plist->net.list + lbus;
+ testnet = sbus->netid;
+ }
+
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if (hidx->nets != NULL) {
+ for (i = 0; i < hidx->nets->numnets; i++)
+ if (*(hidx->nets->netidx + i) == testnet) break;
+ if (i < hidx->nets->numnets) break;
+ }
+ hidx = hidx->next;
+ }
+ if (hidx == NULL) { /* make new entry for net in table */
+ htmp = (struct Ptab *)malloc(sizeof(struct Ptab));
+ tmpnet = (struct Pnet *)malloc(sizeof(struct Pnet));
+ tmpnet->numnets = 1;
+ tmpnet->netidx = (int *)malloc(sizeof(int));
+ *(tmpnet->netidx) = testnet;
+ tmpnet->next = NULL;
+ htmp->cschem = cschem;
+ htmp->nets = tmpnet;
+ htmp->pins = NULL;
+ htmp->next = *ptableptr;
+ *ptableptr = htmp;
+ /* Fprintf(stdout, "Added new index entry for net %d\n", testnet); */
+ }
+ if (++lbus >= plist->subnets) break;
+ }
+ }
+
+ /* Step 1B: Do the same thing for labels. */
+
+ for (llist = cschem->labels; llist != NULL; llist = llist->next) {
+ for (lbus = 0;;) {
+ if (llist->subnets == 0)
+ testnet = llist->net.id;
+ else {
+ sbus = llist->net.list + lbus;
+ testnet = sbus->netid;
+ }
+
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if (hidx->nets != NULL) {
+ for (i = 0; i < hidx->nets->numnets; i++)
+ if (*(hidx->nets->netidx + i) == testnet) break;
+ if (i < hidx->nets->numnets) break;
+ }
+ hidx = hidx->next;
+ }
+ if (hidx == NULL) { /* make new entry for net in table */
+ htmp = (struct Ptab *)malloc(sizeof(struct Ptab));
+ tmpnet = (struct Pnet *)malloc(sizeof(struct Pnet));
+ tmpnet->numnets = 1;
+ tmpnet->netidx = (int *)malloc(sizeof(int));
+ *(tmpnet->netidx) = testnet;
+ tmpnet->next = NULL;
+ htmp->cschem = cschem;
+ htmp->nets = tmpnet;
+ htmp->pins = NULL;
+ htmp->next = *ptableptr;
+ *ptableptr = htmp;
+ /* Fprintf(stdout, "Added new index entry for net %d\n", testnet); */
+ }
+ if (++lbus >= llist->subnets) break;
+ }
+ }
+
+ /* Step 2: Resolve fixed device indices */
+ resolve_devindex(cschem, FALSE);
+
+ /* Step 3: Go through the list of calls to search for endpoints */
+
+ for (calls = cschem->calls; calls != NULL; calls = calls->next) {
+ objectptr cthis;
+
+ cinst = calls->callinst;
+
+ /* Trivial objects should have been dealt with already. */
+ /* If we don't continue the loop here, you get netlist output for */
+ /* objects like dots and circles. */
+ if (calls->callobj->schemtype == TRIVIAL) continue;
+
+ /* Step 4: If call is to a bottom-most schematic, output the device connections */
+ /* Info-label can provide an alternate name or specify the instance number */
+
+ cthis = calls->callobj;
+ if (calls->callobj->schemtype == PRIMARY || calls->callobj->schemtype ==
+ SECONDARY)
+ if (calls->callobj->symschem != NULL)
+ cthis = calls->callobj->symschem;
+
+ if ((sout = parseinfo(cschem, cthis, calls, prefix, mode, FALSE, TRUE)) == NULL) {
+ if (calls->devname == NULL)
+ calls->devname = strdup(calls->callinst->thisobject->name);
+ sprintf(_STR, "%s_%s", calls->devname, d36a(devindex(cschem, calls)));
+ }
+ else {
+ sscanf(sout, "%s", _STR); /* Copy the first word out of sout */
+ }
+ newprefix = (char *)realloc(newprefix, sizeof(char) * (strlen(prefix)
+ + strlen(_STR) + 2));
+ sprintf(newprefix, "%s%s/", prefix, _STR);
+
+ /*----------------------------------------------------------------*/
+ /* Parsing of the "pcb:" info label--- */
+ /* Find all <net>=<name> strings and create the appropriate nets */
+ /*----------------------------------------------------------------*/
+
+ if (sout) {
+ char rsave, *lhs, *rhs, *rend, *sptr = sout, *tmppinname;
+
+ while ((rhs = strchr(sptr, '=')) != NULL) {
+ Genericlist *implicit, newlist;
+ struct Pstr *psrch = NULL;
+
+ lhs = rhs - 1;
+ while ((lhs >= sptr) && isspace(*lhs)) lhs--;
+ while ((lhs >= sptr) && !isspace(*lhs)) lhs--;
+ *rhs = '\0';
+ rhs++;
+ if (isspace(*lhs)) lhs++;
+ while ((*rhs) && isspace(*rhs)) rhs++;
+ for (rend = rhs; (*rend) && (!isspace(*rend)); rend++);
+ rsave = *rend;
+ *rend = '\0';
+
+ /* Get the net from the equation RHS. If none exists, assume */
+ /* the name is a global net and add it to the list of globals. */
+
+ implicit = nametonet(cschem, cinst, rhs);
+ if (implicit == NULL) {
+ stringpart *strptr;
+ label templabel;
+
+ labeldefaults(&templabel, GLOBAL, 0, 0);
+ strptr = templabel.string;
+ strptr->type = TEXT_STRING;
+ strptr->data.string = strdup(rhs);
+ newlist.subnets = 0;
+ newlist.net.id = globalmax() - 1;
+ addglobalpin(cschem, cinst, &templabel, &newlist);
+ implicit = &newlist;
+ free(strptr->data.string);
+ }
+
+ /* Get the name of the pin */
+ tmppinname = (char *)malloc(strlen(newprefix) + strlen(lhs) + 2);
+ strcpy(tmppinname, newprefix);
+ if ((tmplen = strlen(newprefix)) > 0) tmppinname[tmplen - 1] = '-';
+ strcat(tmppinname, lhs);
+
+ /* Find the net in the ptable, or create a new entry for it */
+
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if (hidx->nets != NULL) {
+ for (i = 0; i < hidx->nets->numnets; i++)
+ if (*(hidx->nets->netidx + i) == implicit->net.id)
+ break;
+ if (i < hidx->nets->numnets) break;
+ }
+ hidx = hidx->next;
+ }
+ if (hidx == NULL) {
+ htmp = (struct Ptab *)malloc(sizeof(struct Ptab));
+ tmpnet = (struct Pnet *)malloc(sizeof(struct Pnet));
+ tmpnet->numnets = 1;
+ tmpnet->netidx = (int *)malloc(sizeof(int));
+ *(tmpnet->netidx) = implicit->net.id;
+ tmpnet->next = NULL;
+ htmp->cschem = cschem;
+ htmp->nets = tmpnet;
+ htmp->pins = NULL;
+ htmp->next = *ptableptr;
+ *ptableptr = htmp;
+ hidx = htmp;
+ }
+ else {
+ /* Check if any entries are the same as tmppinname */
+ for (psrch = hidx->pins; psrch != NULL; psrch = psrch->next) {
+ if (!strcmp(psrch->string->data.string, tmppinname))
+ break;
+ }
+ }
+
+ /* Get the pin name from the equation LHS */
+ if (psrch == NULL) {
+ tmpstr = (struct Pstr *)malloc(sizeof(struct Pstr));
+ tmpstr->string = (stringpart *)malloc(sizeof(stringpart));
+ tmpstr->string->type = TEXT_STRING;
+ tmpstr->string->nextpart = NULL;
+ tmpstr->string->data.string = tmppinname;
+ tmpstr->next = hidx->pins;
+ hidx->pins = tmpstr;
+ }
+ else {
+ free(tmppinname);
+ }
+
+ /* Proceed to the next LHS=RHS pair */
+ *rend = rsave;
+ sptr = rend;
+ }
+ free(sout);
+ }
+
+ outputcall = FALSE;
+ if (calls->callobj->calls != NULL) {
+
+ /* Step 4A: Push current net translations */
+ /* (Don't push or pop global net numbers: no translation needed!) */
+
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if ((hidx->nets != NULL) && (((hidx->nets->numnets > 0) &&
+ (*(hidx->nets->netidx) >= 0)) || (hidx->nets->numnets == 0))) {
+ tmpnet = (struct Pnet *)malloc(sizeof(struct Pnet));
+ tmpnet->numnets = 0;
+ tmpnet->netidx = NULL;
+ tmpnet->next = hidx->nets;
+ hidx->nets = tmpnet;
+ }
+ hidx = hidx->next;
+ }
+
+ /* Step 4B: Generate net translation table for each subcircuit */
+
+ for (ports = calls->ports; ports != NULL; ports = ports->next) {
+ for (hidx = *ptableptr; hidx != NULL; hidx = hidx->next) {
+ if (hidx->nets != NULL) {
+ if (hidx->nets->next != NULL) {
+ for (i = 0; i < hidx->nets->next->numnets; i++)
+ if (*(hidx->nets->next->netidx + i) == ports->netid)
+ break;
+ if (i < hidx->nets->next->numnets) break;
+ }
+ else if (ports->netid < 0) {
+ if (hidx->nets->netidx != NULL)
+ if (*(hidx->nets->netidx) == ports->netid)
+ break;
+ }
+ }
+ }
+ if (hidx != NULL) {
+ hidx->nets->numnets++;
+ if (hidx->nets->numnets == 1)
+ hidx->nets->netidx = (int *)malloc(sizeof(int));
+ else
+ hidx->nets->netidx = (int *)realloc(hidx->nets->netidx,
+ hidx->nets->numnets * sizeof(int));
+
+ /* Translate net value */
+ locnet = translatedown(ports->netid, ports->portid,
+ calls->callobj);
+ *(hidx->nets->netidx + hidx->nets->numnets - 1) = locnet;
+
+ /* Fprintf(stdout, "Translation: net %d in object %s is net "
+ "%d in object %s\n", ports->netid, cschem->name,
+ locnet, calls->callobj->name); */
+ }
+ }
+
+ /* Step 4C: Run routine recursively on the subcircuit */
+
+ /* Fprintf(stdout, "Recursive call of writepcb() to %s\n",
+ calls->callobj->name); */
+ outputcall = writepcb(ptableptr, calls->callobj, calls, newprefix, mode);
+
+ /* Step 4D: Pop the translation table */
+ /* (Don't pop global nets (designated by negative net number)) */
+
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if ((hidx->nets != NULL) && (((hidx->nets->numnets > 0) &&
+ (*(hidx->nets->netidx) >= 0)) || (hidx->nets->numnets == 0))) {
+ tmpnet = hidx->nets->next;
+ if (hidx->nets->numnets > 0) free(hidx->nets->netidx);
+ free(hidx->nets);
+ hidx->nets = tmpnet;
+ }
+ hidx = hidx->next;
+ }
+ }
+
+ if (!outputcall) {
+ stringpart *ppin;
+
+ /* Fprintf(stdout, "Reached lowest-level schematic: Finding connections\n"); */
+ for (ports = calls->ports; ports != NULL; ports = ports->next) {
+ locnet = translatedown(ports->netid, ports->portid, calls->callobj);
+ /* Global pin names should probably be ignored, not just */
+ /* when an object is declared to be "trivial". Not sure if */
+ /* this breaks certain netlists. . . */
+ if (locnet < 0) continue;
+
+ /* Get the name of the pin in the called object with no prefix. */
+ subnet = getsubnet(locnet, calls->callobj);
+ ppin = nettopin(locnet, calls->callobj, NULL);
+ hidx = *ptableptr;
+ while (hidx != NULL) {
+ if (hidx->nets != NULL) {
+ for (i = 0; i < hidx->nets->numnets; i++)
+ if (*(hidx->nets->netidx + i) == ports->netid)
+ break;
+ if (i < hidx->nets->numnets) break;
+ }
+ hidx = hidx->next;
+ }
+ if (hidx == NULL) {
+ snew = textprintsubnet(ppin, cinst, subnet);
+ Fprintf(stdout, "Warning: Unconnected pin %s%s\n", newprefix, snew);
+ free(snew);
+ }
+ else {
+ outputcall = TRUE;
+ outputdone = TRUE;
+ tmpstr = (struct Pstr *)malloc(sizeof(struct Pstr));
+ tmpstr->string = (stringpart *)malloc(sizeof(stringpart));
+ tmpstr->string->type = TEXT_STRING;
+ tmpstr->string->nextpart = NULL;
+ snew = textprintsubnet(ppin, cinst, subnet);
+ tmpstr->string->data.string = (char *)malloc(strlen(newprefix)
+ + strlen(snew) + 2);
+ strcpy(tmpstr->string->data.string, newprefix);
+ /* Replace slash '/' with dash '-' at bottommost level */
+ if ((tmplen = strlen(newprefix)) > 0)
+ tmpstr->string->data.string[tmplen - 1] = '-';
+ strcat(tmpstr->string->data.string, snew);
+ free(snew);
+ tmpstr->next = hidx->pins;
+ hidx->pins = tmpstr;
+
+ /* diagnositic information */
+ {
+ struct Pnet *locnet = hidx->nets;
+ int ctr = 0;
+ while (locnet->next != NULL) {
+ locnet = locnet->next;
+ ctr++;
+ }
+ /* Fprintf(stdout, "Logged level-%d net %d (local net %d) pin %s\n",
+ ctr, *(locnet->netidx), *(hidx->nets->netidx + i),
+ tmpstr->string); */
+ }
+ }
+ }
+ }
+ }
+
+ /* Step 5: Cleanup */
+
+ free(newprefix);
+ return outputdone;
+}
+
+/*----------------------------------------------------------------------*/
+/* Save PCB table into pcb-style file */
+/*----------------------------------------------------------------------*/
+
+void outputpcb(struct Ptab *ptable, FILE *fp)
+{
+ int netidx = 1, ccol, subnet;
+ struct Ptab *pseek;
+ struct Pstr *sseek;
+ char *snew;
+ stringpart *ppin;
+
+ if (fp == NULL) return;
+
+ for (pseek = ptable; pseek != NULL; pseek = pseek->next) {
+ if (pseek->pins != NULL) {
+ if ((pseek->nets != NULL) && (pseek->nets->numnets > 0)) {
+ subnet = getsubnet(*(pseek->nets->netidx), pseek->cschem);
+ ppin = nettopin(*(pseek->nets->netidx), pseek->cschem, "");
+ snew = textprintsubnet(ppin, NULL, subnet);
+ strcpy(_STR, snew);
+ free(snew);
+ }
+ else
+ sprintf(_STR, "NET%d ", netidx++);
+ fprintf(fp, "%-11s ", _STR);
+ ccol = 12;
+ for (sseek = pseek->pins; sseek != NULL; sseek = sseek->next) {
+ ccol += stringlength(sseek->string, False, NULL) + 3;
+ if (ccol > 78) {
+ fprintf(fp, "\\\n ");
+ ccol = 18 + stringlength(sseek->string, False, NULL);
+ }
+ snew = textprint(sseek->string, NULL);
+ fprintf(fp, "%s ", snew);
+ free(snew);
+ }
+ fprintf(fp, "\n");
+ }
+ /* else fprintf(fp, "NET%d *UNCONNECTED*\n", netidx++); */
+ }
+}
+
+/*----------------------------------------------*/
+/* free memory allocated to PCB net tables */
+/*----------------------------------------------*/
+
+void freepcb(struct Ptab *ptable)
+{
+ struct Ptab *pseek, *pseek2;
+ struct Pstr *sseek, *sseek2;
+ struct Pnet *nseek, *nseek2;
+
+ pseek = ptable;
+ pseek2 = pseek;
+
+ while (pseek2 != NULL) {
+ pseek = pseek->next;
+
+ sseek = pseek2->pins;
+ sseek2 = sseek;
+ while (sseek2 != NULL) {
+ sseek = sseek->next;
+ freelabel(sseek2->string);
+ free(sseek2);
+ sseek2 = sseek;
+ }
+
+ nseek = pseek2->nets;
+ nseek2 = nseek;
+ while (nseek2 != NULL) {
+ nseek = nseek->next;
+ if (nseek2->numnets > 0) free(nseek2->netidx);
+ free(nseek2);
+ nseek2 = nseek;
+ }
+
+ free(pseek2);
+ pseek2 = pseek;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove an element from the netlist. This is necessary when an */
+/* element is deleted from the object, so that the netlist does not */
+/* refer to a nonexistant element, or try to perform netlist function */
+/* on it. */
+/* */
+/* Return True or False depending on whether a pin was "orphaned" on */
+/* the corresponding schematic or symbol (if any), as this may cause */
+/* the class of the object (FUNDAMENTAL, TRIVIAL, etc.) to change. */
+/*----------------------------------------------------------------------*/
+
+Boolean RemoveFromNetlist(objectptr thisobject, genericptr thiselem)
+{
+ Boolean pinchanged = False;
+ labelptr nlab;
+ polyptr npoly;
+ objectptr pschem;
+ objinstptr ninst;
+
+ PolylistPtr plist, plast;
+ LabellistPtr llist, llast;
+ CalllistPtr clist, clast;
+
+ pschem = (thisobject->schemtype == SECONDARY) ? thisobject->symschem
+ : thisobject;
+
+ switch (thiselem->type) {
+ case OBJINST:
+ ninst = (objinstptr)thiselem;
+ /* If this is an object instance, remove it from the calls */
+ clast = NULL;
+ for (clist = pschem->calls; clist != NULL; clist = clist->next) {
+ if (clist->callinst == ninst) {
+ if (clast == NULL)
+ pschem->calls = clist->next;
+ else
+ clast->next = clist->next;
+ freecalls(clist);
+ clist = (clast) ? clast : pschem->calls;
+ break;
+ }
+ else
+ clast = clist;
+ }
+ break;
+
+ case POLYGON:
+ npoly = (polyptr)thiselem;
+ if (nonnetwork(npoly)) break;
+
+ /* If this is a polygon, remove it from the netlist */
+ plast = NULL;
+ for (plist = pschem->polygons; plist != NULL; plist = plist->next) {
+ if (plist->poly == npoly) {
+ if (plast == NULL)
+ pschem->polygons = plist->next;
+ else
+ plast->next = plist->next;
+ if (plist->subnets > 0)
+ free(plist->net.list);
+ break;
+ }
+ else
+ plast = plist;
+ }
+ break;
+
+ case LABEL:
+ nlab = (labelptr)thiselem;
+ if ((nlab->pin != LOCAL) && (nlab->pin != GLOBAL)) break;
+
+ /* If this is a label, remove it from the netlist */
+ llast = NULL;
+ for (llist = pschem->labels; llist != NULL; llist = llist->next) {
+ if (llist->label == nlab) {
+ if (llast == NULL)
+ pschem->labels = llist->next;
+ else
+ llast->next = llist->next;
+ if (llist->subnets > 0)
+ free(llist->net.list);
+ break;
+ }
+ else
+ llast = llist;
+ }
+
+ /* Mark pin label in corresponding schematic/symbol as "orphaned" */
+ /* by changing designation from type "pin" to type "label". */
+
+ if (findlabelcopy(nlab, nlab->string) == NULL) {
+ changeotherpins(NULL, nlab->string);
+ if (nlab->pin == INFO) pinchanged = True;
+ }
+ }
+ return pinchanged;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove one element from the netlist */
+/*----------------------------------------------------------------------*/
+
+void remove_netlist_element(objectptr cschem, genericptr genelem) {
+
+ objectptr pschem;
+ CalllistPtr clist, clast, cnext;
+ LabellistPtr llist, llast, lnext;
+ PolylistPtr plist, plast, pnext;
+ Boolean found = FALSE;
+
+ /* Always call on the primary schematic */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ switch (ELEMENTTYPE(genelem)) {
+ case POLYGON:
+ /* remove polygon from polygon list */
+ plast = NULL;
+ for (plist = pschem->polygons; plist != NULL; ) {
+ pnext = plist->next;
+ if ((genericptr)plist->poly == genelem) {
+ found = TRUE;
+ if (plist->subnets > 0)
+ free(plist->net.list);
+ free(plist);
+ if (plast != NULL)
+ plast->next = pnext;
+ else
+ pschem->polygons = pnext;
+ break;
+ }
+ else
+ plast = plist;
+ plist = pnext;
+ }
+ break;
+
+ case LABEL:
+
+ /* remove label from label list */
+ llast = NULL;
+ for (llist = pschem->labels; llist != NULL; ) {
+ lnext = llist->next;
+ if ((genericptr)llist->label == genelem) {
+ found = TRUE;
+ if (llist->subnets > 0)
+ free(llist->net.list);
+ free(llist);
+ if (llast != NULL)
+ llast->next = lnext;
+ else
+ pschem->labels = lnext;
+ break;
+ }
+ else
+ llast = llist;
+ llist = lnext;
+ }
+
+ /* also check the globals */
+ llast = NULL;
+ for (llist = global_labels; llist != NULL; ) {
+ lnext = llist->next;
+ if ((genericptr)llist->label == genelem) {
+ found = TRUE;
+ if (llist->subnets > 0)
+ free(llist->net.list);
+ free(llist);
+ if (llast != NULL)
+ llast->next = lnext;
+ else
+ global_labels = lnext;
+ break;
+ }
+ else
+ llast = llist;
+ llist = lnext;
+ }
+ break;
+
+ case OBJINST:
+
+ /* remove instance from call list */
+ clast = NULL;
+ for (clist = pschem->calls; clist != NULL; ) {
+ cnext = clist->next;
+ if ((genericptr)clist->callinst == genelem) {
+ found = TRUE;
+ freecalls(clist);
+ if (clast != NULL)
+ clast->next = cnext;
+ else
+ pschem->calls = cnext;
+ }
+ else
+ clast = clist;
+ clist = cnext;
+ }
+ break;
+ }
+ if (found)
+ pschem->valid = FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated for the ports in a calls. */
+/*----------------------------------------------------------------------*/
+
+void freecalls(CalllistPtr calls)
+{
+ PortlistPtr ports, pptr;
+
+ for (ports = calls->ports; ports != NULL;) {
+ pptr = ports->next;
+ free(ports);
+ ports = pptr;
+ }
+ if (calls->devname != NULL) free(calls->devname);
+ free(calls);
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory for a Genericlist structure (may also be a Labellist or */
+/* Polylist structure). */
+/*----------------------------------------------------------------------*/
+
+void freegenlist(Genericlist *nets)
+{
+ if (nets == NULL) return;
+ if (nets->subnets > 0)
+ free(nets->net.list);
+ free(nets);
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated for the label list in a netlist. */
+/*----------------------------------------------------------------------*/
+
+void freelabellist(LabellistPtr *listtop)
+{
+ LabellistPtr labellist, llist;
+
+ for (labellist = *listtop; labellist != NULL;) {
+ llist = labellist->next;
+ freegenlist((Genericlist *)labellist);
+ labellist = llist;
+ }
+ *listtop = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated for the polygon list in a netlist. */
+/*----------------------------------------------------------------------*/
+
+void freepolylist(PolylistPtr *listtop)
+{
+ PolylistPtr polylist, plist;
+
+ for (polylist = *listtop; polylist != NULL;) {
+ plist = polylist->next;
+ freegenlist((Genericlist *)polylist);
+ polylist = plist;
+ }
+ *listtop = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated for netlist */
+/*----------------------------------------------------------------------*/
+
+void freenetlist(objectptr cschem)
+{
+ PolylistPtr *plist;
+ LabellistPtr *llist;
+
+ plist = &cschem->polygons;
+ freepolylist(plist);
+ llist = &cschem->labels;
+ freelabellist(llist);
+}
+
+/*----------------------------------------------------------------------*/
+/* Clear the "traversed" flag in all objects of the hierarchy. */
+/*----------------------------------------------------------------------*/
+
+int cleartraversed_level(objectptr cschem, int level)
+{
+ genericptr *cgen;
+ objinstptr cinst;
+ objectptr callobj, pschem;
+
+ /* Always call on the primary schematic */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ /* Recursively call cleartraversed() on all subobjects, a la gennetlist() */
+ /* Use the parts list of the object, not the calls, because calls */
+ /* may have been removed. */
+
+ if (level == HIERARCHY_LIMIT) return -1;
+
+ for (cgen = pschem->plist; cgen < pschem->plist + pschem->parts; cgen++) {
+ if (IS_OBJINST(*cgen)) {
+ cinst = TOOBJINST(cgen);
+
+ if (cinst->thisobject->symschem != NULL)
+ callobj = cinst->thisobject->symschem;
+ else
+ callobj = cinst->thisobject;
+
+ /* Don't infinitely recurse if object is on its own schematic */
+ /* However, we need to take a stab at more subtle recursion, too */
+
+ if (callobj != pschem)
+ if (cleartraversed_level(callobj, level + 1) == -1)
+ return -1;
+ }
+ }
+ pschem->traversed = False;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* This is the routine normally called, as it hides the "level" */
+/* argument tagging the level of recursion. */
+/*----------------------------------------------------------------------*/
+
+int cleartraversed(objectptr cschem) {
+ return cleartraversed_level(cschem, 0);
+}
+
+/*----------------------------------------------------------------------*/
+/* If any part of the netlist is invalid, destroy the entire netlist */
+/*----------------------------------------------------------------------*/
+
+int checkvalid(objectptr cschem)
+{
+ genericptr *cgen;
+ objinstptr cinst;
+ objectptr callobj, pschem;
+
+ /* If the object has been declared a non-network object, ignore it */
+ if (cschem->schemtype == NONETWORK) return 0;
+
+ /* Always operate on the master schematic */
+ pschem = (cschem->schemtype == SECONDARY) ? cschem->symschem : cschem;
+
+ /* Stop immediately if the netlist is invalid */
+ if (pschem->valid == False) return -1;
+
+ /* Otherwise, recursively call checkvalid() on all subobjects. */
+ /* Use the parts list of the object, not the calls, because calls */
+ /* may have been removed. */
+
+ for (cgen = pschem->plist; cgen < pschem->plist + pschem->parts; cgen++) {
+ if (IS_OBJINST(*cgen)) {
+ cinst = TOOBJINST(cgen);
+
+ if (cinst->thisobject->symschem != NULL)
+ callobj = cinst->thisobject->symschem;
+ else
+ callobj = cinst->thisobject;
+
+ /* Don't infinitely recurse if object is on its own schematic */
+
+ if (callobj == pschem) continue;
+
+ /* If there is a symbol, don't check its parts, but check if */
+ /* its netlist has been checkvalid. */
+
+ if ((cinst->thisobject->symschem != NULL) &&
+ (cinst->thisobject->labels == NULL) &&
+ (cinst->thisobject->polygons == NULL) &&
+ (cinst->thisobject->valid == False))
+ return -1;
+
+ /* Recursive call on subschematic */
+ if (checkvalid(callobj) == -1)
+ return -1;
+ }
+ }
+ return 0; /* All subnetlists and own netlist are valid */
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated to temporary labels generated for the netlist */
+/*----------------------------------------------------------------------*/
+
+void freetemplabels(objectptr cschem)
+{
+ genericptr *cgen;
+ objinstptr cinst;
+ objectptr callobj;
+
+ /* Recursively call freetemplabels() on all subobjects, a la gennetlist() */
+ /* Use the parts list of the object, not the calls, because calls */
+ /* may have been removed. */
+
+ for (cgen = cschem->plist; cgen < cschem->plist + cschem->parts; cgen++) {
+ if (IS_OBJINST(*cgen)) {
+
+ cinst = TOOBJINST(cgen);
+ if (cinst->thisobject->symschem != NULL)
+ callobj = cinst->thisobject->symschem;
+ else
+ callobj = cinst->thisobject;
+
+ /* Don't infinitely recurse if object is on its own schematic */
+ if (callobj != cschem) freetemplabels(callobj);
+
+ /* Also free the temp labels of any associated symbol */
+ if (cinst->thisobject->symschem != NULL) freetemplabels(cinst->thisobject);
+ }
+
+ /* Free any temporary labels which have been created */
+
+ else if (IS_LABEL(*cgen)) {
+ labelptr clab = TOLABEL(cgen);
+ /* int tmpval = (int)(cgen - cschem->plist); (jdk) */
+ if (clab->string->type != FONT_NAME) {
+ genericptr *tgen;
+
+ clab = TOLABEL(cgen);
+ freelabel(clab->string);
+ free(clab);
+ for (tgen = cgen + 1; tgen < cschem->plist + cschem->parts; tgen++)
+ *(tgen - 1) = *tgen;
+ cschem->parts--;
+ cgen--;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Free memory allocated for netlists, ports, and calls */
+/*----------------------------------------------------------------------*/
+
+void freenets(objectptr cschem)
+{
+ CalllistPtr calls, cptr;
+ PortlistPtr ports, pptr;
+ genericptr *cgen;
+ objinstptr cinst;
+ objectptr callobj;
+
+ /* Recursively call freenets() on all subobjects, a la gennetlist() */
+ /* Use the parts list of the object, not the calls, because calls */
+ /* may have been removed. */
+
+ if (cschem->schemtype == PRIMARY || cschem->schemtype == SECONDARY ||
+ (cschem->schemtype == SYMBOL && cschem->symschem == NULL)) {
+ for (cgen = cschem->plist; cgen < cschem->plist + cschem->parts; cgen++) {
+ if (IS_OBJINST(*cgen)) {
+
+ cinst = TOOBJINST(cgen);
+ if (cinst->thisobject->symschem != NULL)
+ callobj = cinst->thisobject->symschem;
+ else
+ callobj = cinst->thisobject;
+
+ /* Don't infinitely recurse if object is on its own schematic */
+ if (callobj != cschem) freenets(callobj);
+
+ /* Also free the netlist of any associated symbol */
+ if (cinst->thisobject->symschem != NULL) freenets(cinst->thisobject);
+ }
+ }
+ }
+
+ /* Free the allocated structures for this object */
+
+ for (calls = cschem->calls; calls != NULL;) {
+ cptr = calls->next;
+ freecalls(calls);
+ calls = cptr;
+ }
+ cschem->calls = NULL;
+
+ for (ports = cschem->ports; ports != NULL;) {
+ pptr = ports->next;
+ free(ports);
+ ports = pptr;
+ }
+ cschem->ports = NULL;
+
+ freenetlist(cschem);
+
+ cschem->traversed = False;
+ cschem->valid = False;
+ freegenlist(cschem->highlight.netlist);
+ cschem->highlight.netlist = NULL;
+ cschem->highlight.thisinst = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free the global pin list */
+/*----------------------------------------------------------------------*/
+
+void freeglobals()
+{
+ LabellistPtr labellist, llist;
+
+ for (labellist = global_labels; labellist != NULL;) {
+ llist = labellist->next;
+
+ /* Labels in the global list are temporary and must be deallocated */
+ freelabel(labellist->label->string);
+ free(labellist->label);
+
+ freegenlist((Genericlist *)labellist);
+ labellist = llist;
+ }
+ global_labels = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get rid of locally-defined pin names */
+/*----------------------------------------------------------------------*/
+
+void clearlocalpins(objectptr cschem)
+{
+ NetnamePtr netnames, nextname;
+
+ for (netnames = cschem->netnames; netnames != NULL; ) {
+ nextname = netnames->next;
+ if (netnames->localpin != NULL) {
+ freelabel(netnames->localpin);
+ }
+ free(netnames);
+ netnames = nextname;
+ }
+ cschem->netnames = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Handle lists of included files */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* check_included() --- check if a file has already been included. */
+/* Check by inode instead of filename so that we cannot trick the */
+/* program by giving, e.g., one relative path and one full path. */
+/*----------------------------------------------------------------------*/
+
+Boolean check_included(char *filename)
+{
+ struct stat filestatus;
+ int numi;
+
+ if (stat(filename, &filestatus) == 0) {
+ if (included_files == NULL) return FALSE;
+ for (numi = 0; *(included_files + numi) != (ino_t)NULL; numi++) {
+ if (*(included_files + numi) == filestatus.st_ino) return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* append_included() --- update the list of included files by adding */
+/* the inode of filename to the list. */
+/*----------------------------------------------------------------------*/
+
+void append_included(char *filename)
+{
+ struct stat filestatus;
+ int numi;
+
+ if (stat(filename, &filestatus) == 0) {
+
+ if (included_files == NULL) {
+ included_files = (ino_t *)malloc(2 * sizeof(ino_t));
+ *included_files = filestatus.st_ino;
+ *(included_files + 1) = (ino_t)NULL;
+ }
+ else {
+ for (numi = 0; *(included_files + numi) != (ino_t)NULL; numi++);
+
+ included_files = (ino_t *)realloc(included_files,
+ (++numi) * sizeof(ino_t));
+
+ *(included_files + numi - 1) = filestatus.st_ino;
+ *(included_files + numi) = (ino_t)NULL;
+ }
+ }
+ else {
+ Wprintf("Error: Cannot stat include file \"%s\"\n", filename);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+void free_included()
+{
+ if (included_files != NULL) {
+ free(included_files);
+ included_files = NULL;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/ngspice.c b/ngspice.c
new file mode 100644
index 0000000..50b5f2d
--- /dev/null
+++ b/ngspice.c
@@ -0,0 +1,659 @@
+/*----------------------------------------------------------------------*/
+/* ngspice.c --- Handling of background ngspice process. */
+/* Copyright (c) 2004 Tim Edwards, MultiGiG, Inc. */
+/* These routines work only if ngspice is on the system. */
+/*----------------------------------------------------------------------*/
+
+/* #undef SPICE_DEBUG */
+#define SPICE_DEBUG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <time.h>
+#ifndef _MSC_VER
+#include <sys/wait.h> /* for waitpid() */
+#include <sys/time.h>
+#include <ctype.h>
+#endif
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+
+/* This code should be able to run without requiring Tcl-based XCircuit */
+/* but this has not been worked out, so instead it is just disabled. */
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include <tk.h>
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+extern char _STR2[250], _STR[150];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern Display *dpy;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern Cursor appcursors[NUM_CURSORS];
+
+#ifndef HAVE_VFORK
+#define vfork fork
+#endif
+
+int spice_state; /* Track state of the simulator */
+
+#define SPICE_INIT 0 /* Initial state; ngspice interpreter is idle. */
+#define SPICE_BUSY 1 /* Simulation in progress; ngspice is busy. */
+#define SPICE_READY 2 /* Simulation at break; ngspice is waiting for */
+ /* "resume". */
+
+#define EXPECT_ANY 0 /* Read routine accepts all input until input */
+ /* buffer is empty, then returns. */
+#define EXPECT_PROMPT 1 /* Read routine accepts all input up to the */
+ /* next ngspice prompt, removes the prompt, */
+ /* sets the Tcl return value to the history */
+ /* number, and returns. */
+#define EXPECT_REF 2 /* Read routine accepts all input until the */
+ /* first "Reference value" line, truncates the */
+ /* output, and sets the Tcl return value to the */
+ /* reference value seen. */
+
+#ifndef CONST84
+#define CONST84
+#endif
+
+/*------------------------------------------------------*/
+/* Global variable definitions */
+/*------------------------------------------------------*/
+
+#ifndef _MSC_VER
+pid_t spiceproc = -1; /* ngspice process */
+#else
+HANDLE spiceproc = INVALID_HANDLE_VALUE;
+#endif
+
+int pipeRead, pipeWrite; /* I/O pipe pair for ngspice */
+
+/*------------------------------------------------------*/
+/* Start a ngspice process and arrange the I/O pipes */
+/* (Commented lines cause ngspice to relay its stderr */
+/* to xcircuit's stderr) */
+/* */
+/* Return codes: */
+/* 0 success */
+/* -1 failed---ngspice exited with error condition */
+/* -2 exec failed---e.g., unable to find ngspice */
+/* 1 ngspice is already running */
+/*------------------------------------------------------*/
+
+#ifdef _MSC_VER
+
+int start_spice()
+{
+ STARTUPINFO st_info;
+ PROCESS_INFORMATION pr_info;
+ SECURITY_ATTRIBUTES attr;
+ HANDLE child_stdin, child_stdout, tmp;
+ char cmd[4096];
+
+ attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ attr.lpSecurityDescriptor = NULL;
+ attr.bInheritHandle = FALSE;
+
+ if (!CreatePipe(&tmp, &child_stdout, &attr, 0))
+ goto spice_error;
+
+ SetHandleInformation(tmp, HANDLE_FLAG_INHERIT, 0);
+ pipeRead = _open_osfhandle(tmp, _O_RDONLY);
+ if (!CreatePipe(&child_stdin, &tmp, &attr, 0))
+ goto spice_error;
+ SetHandleInformation(tmp, HANDLE_FLAG_INHERIT, 0);
+ pipeWrite = _open_osfhandle(tmp, _O_WRONLY);
+
+ ZeroMemory(&pr_info, sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&st_info, sizeof(STARTUPINFO));
+ st_info.cb = sizeof(STARTUPINFO);
+ st_info.dwFlags = STARTF_USESTDHANDLES;
+ st_info.hStdError = st_info.hStdOutput = child_stdout;
+ st_info.hStdInput = child_stdin;
+
+ snprintf(cmd, 4095, "%s -p", SPICE_EXEC);
+ if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
+ &st_info, &pr_info) == 0)
+ goto spice_error;
+
+ CloseHandle(pr_info.hThread);
+ spiceproc = pr_info.hProcess;
+ return 0;
+
+spice_error:
+ Fprintf(stderr, "Exec of ngspice failed\n");
+ return -2;
+}
+
+#else /* ! MSC_VER */
+
+int start_spice()
+{
+ int std_in[2], std_out[2], ret;
+
+ ret = pipe(std_in);
+ ret = pipe(std_out);
+
+ /* Input goes from xcircuit to ngspice to provide commands to the */
+ /* ngspice interpreter front-end. Output goes from ngspice back to */
+ /* xcircuit to provide data for displaying. */
+
+ if (spiceproc < 0) { /* ngspice is not running yet */
+ spiceproc = vfork();
+ if (spiceproc == 0) { /* child process (ngspice) */
+#ifdef SPICE_DEBUG
+ fprintf(stdout, "Calling %s\n", SPICE_EXEC);
+#endif
+ close(std_in[0]);
+ close(std_out[1]);
+
+ dup2(std_in[1], fileno(stdout));
+ dup2(std_in[1], fileno(stderr));
+ dup2(std_out[0], fileno(stdin));
+
+ Flush(stderr);
+
+ /* Force interactive mode with "-p". Otherwise, ngspice will */
+ /* detect that the pipe is not a terminal and switch to batch- */
+ /* processing mode. */
+
+ execlp(SPICE_EXEC, "ngspice", "-p", (char *)NULL);
+ spiceproc = -1;
+ Fprintf(stderr, "Exec of ngspice failed\n");
+ return -2;
+ }
+ else if (spiceproc < 0) {
+ Wprintf("Error: ngspice not running");
+ close(std_in[0]);
+ close(std_in[1]);
+ close(std_out[0]);
+ close(std_out[1]);
+ return -1; /* error condition */
+ }
+ else { /* parent process */
+ close(std_in[1]);
+ close(std_out[0]);
+ pipeRead = std_in[0];
+ pipeWrite = std_out[1];
+ return 0; /* success */
+ }
+ }
+ return 1; /* spice is already running */
+}
+
+#endif /* ! MSC_VER */
+
+/*------------------------------------------------------*/
+/* Send text to the ngspice simulator */
+/*------------------------------------------------------*/
+
+void send_to_spice(char *text)
+{
+ int tlen = strlen(text);
+ write(pipeWrite, text, tlen);
+ if (*(text + tlen - 1) != '\n')
+ write(pipeWrite, "\n", 1);
+
+ if (!strncmp(text, "run", 3) || !strncmp(text, "resume", 6))
+ spice_state = SPICE_BUSY;
+ else if (!strncmp(text, "quit", 4) || !strncmp(text, "exit", 4))
+ spice_state = SPICE_INIT;
+
+#ifdef SPICE_DEBUG
+ /* fprintf(stdout, "writing: %s\n", text); */
+#endif
+}
+
+/*------------------------------------------------------*/
+/* Get text from the ngspice simulator */
+/*------------------------------------------------------*/
+
+#define RECV_BUFSIZE 1024
+
+char *recv_from_spice(Tcl_Interp *interp, int expect)
+{
+ int n, numc, totc, nfd;
+ fd_set readfds, writefds, exceptfds;
+ static char *buffer = NULL;
+ struct timeval timeout;
+ char *pptr, *bufptr;
+ float refval;
+
+ if (buffer == NULL)
+ buffer = (char *)malloc(RECV_BUFSIZE);
+
+ /* 2-second timeout on reads */
+ timeout.tv_sec = (expect == EXPECT_ANY) ? 0 : 2;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&exceptfds);
+
+ bufptr = buffer;
+ totc = 0;
+ numc = RECV_BUFSIZE - 1;
+ while (numc == RECV_BUFSIZE - 1) {
+
+ nfd = pipeRead + 1;
+ FD_ZERO(&writefds);
+ FD_SET(pipeRead, &readfds);
+ FD_SET(pipeRead, &exceptfds);
+
+ *bufptr = '\0';
+ n = select(nfd, &readfds, &writefds, &exceptfds, &timeout);
+ if (n == 0) {
+ if (expect != EXPECT_ANY)
+ Fprintf(stderr, "Timeout during select()\n");
+ return buffer; /* Timeout, or no data */
+ }
+ else if (n < 0) {
+ /* Interrupt here? */
+ Fprintf(stderr, "Exception received by select()\n");
+ return buffer;
+ }
+ numc = read(pipeRead, bufptr, RECV_BUFSIZE - 1);
+ *(bufptr + numc) = '\0'; /* Terminate the line just read */
+ totc += numc;
+
+ switch(expect) {
+ case EXPECT_PROMPT:
+ for (pptr = bufptr + numc - 1; pptr >= buffer; pptr--)
+ if (*pptr == '\n')
+ break;
+ if (!strncmp(pptr + 1, "ngspice", 7)) {
+ *(pptr) = '\0';
+ if (sscanf(pptr + 8, "%d", &numc) == 1) {
+ sprintf(_STR2, "%d", numc);
+ Tcl_SetResult(interp, _STR2, TCL_STATIC);
+ }
+ return buffer;
+ }
+ /* Force the process to continue reading until the */
+ /* prompt is received. */
+ numc = RECV_BUFSIZE - 1;
+ break;
+
+ case EXPECT_REF:
+ for (pptr = bufptr + numc - 1; pptr > buffer; pptr--) {
+ if (*pptr == '\r') {
+ while ((--pptr >= buffer) && !isspace(*pptr));
+ if (sscanf(pptr + 1, "%g", &refval)) {
+ sprintf(_STR2, "%g", refval);
+ Tcl_SetResult(interp, _STR2, TCL_STATIC);
+ }
+ return buffer;
+ }
+ }
+ /* Force the process to continue reading until a */
+ /* reference value is received. */
+ numc = RECV_BUFSIZE - 1;
+
+ /* Drop through to below to remove the control chars */
+
+ case EXPECT_ANY:
+ /* Remove control characters from the input */
+ pptr = bufptr;
+ while (*pptr != '\0') {
+ if (*pptr == '\r') *pptr = '\n';
+ else if (!isprint(*pptr)) *pptr = ' ';
+ pptr++;
+ }
+ break;
+
+ }
+ if (numc == RECV_BUFSIZE - 1) {
+ buffer = (char *)realloc(buffer, totc + RECV_BUFSIZE);
+ bufptr = buffer + totc;
+ }
+ }
+
+#ifdef SPICE_DEBUG
+ /* fprintf(stdout, "read %d characters: %s", totc, buffer); */
+#endif
+ return buffer;
+}
+
+/*------------------------------------------------------*/
+/* Send break (ctrl-c) to the ngspice simulator */
+/* Return 0 on success, -1 if ngspice didn't return a */
+/* prompt within the timeout period. */
+/*------------------------------------------------------*/
+
+int break_spice(Tcl_Interp *interp)
+{
+ char *msg;
+
+#ifdef _MSC_VER
+ if (spiceproc == INVALID_HANDLE_VALUE) return 0; /* No process to interrupt */
+#else
+ if (spiceproc == -1) return 0; /* No process to interrupt */
+#endif
+
+ /* Sending SIGINT in any state other than "busy" will kill */
+ /* the ngspice process, not interrupt it! */
+
+ if (spice_state == SPICE_BUSY) {
+#ifndef _MSC_VER
+ kill(spiceproc, SIGINT);
+#else
+ TerminateProcess(spiceproc, -1);
+#endif
+ msg = recv_from_spice(interp, EXPECT_PROMPT); /* Flush the output */
+ if (*msg == '\0')
+ return -1;
+ }
+
+ spice_state = SPICE_READY;
+#ifdef SPICE_DEBUG
+ /* fprintf(stdout, "interrupt ngspice\n"); */
+#endif
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Resume the ngspice simulator */
+/*------------------------------------------------------*/
+
+void resume_spice()
+{
+ spice_state = SPICE_BUSY;
+ write(pipeWrite, "resume\n", 7);
+#ifdef SPICE_DEBUG
+ /* fprintf(stdout, "resume ngspice\n"); */
+#endif
+}
+
+/*------------------------------------------------------*/
+/* Exit ngspice. . . not so gently */
+/*------------------------------------------------------*/
+
+int exit_spice()
+{
+#ifdef _MSC_VER
+ if (spiceproc == INVALID_HANDLE_VALUE) return -1; /* ngspice not running */
+#else
+ if (spiceproc < 0) return -1; /* ngspice not running */
+#endif
+
+#ifdef SPICE_DEBUG
+ fprintf(stdout, "Waiting for ngspice to exit\n");
+#endif
+#ifndef _MSC_VER
+ kill(spiceproc, SIGKILL);
+ waitpid(spiceproc, NULL, 0);
+#else
+ TerminateProcess(spiceproc, -1);
+#endif
+#ifdef SPICE_DEBUG
+ fprintf(stdout, "ngspice has exited\n");
+#endif
+
+#ifdef _MSC_VER
+ spiceproc = INVALID_HANDLE_VALUE;
+#else
+ spiceproc = -1;
+#endif
+ spice_state = SPICE_INIT;
+
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Spice command */
+/* */
+/* Run the ngspice simulator from the tcl command line. */
+/* Currently, the Tcl command-line interface is the */
+/* *only* way to access the ngspice simulator through */
+/* XCircuit. ngspice runs as a separate process via a */
+/* fork call, and sends and receives through the */
+/* "spice" command in Tcl-XCircuit. */
+/*------------------------------------------------------*/
+
+int xctcl_spice(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, idx;
+ char *msg, *eptr;
+
+ static char *subCmds[] = {
+ "start", "send", "get", "break", "resume", "status",
+ "flush", "exit", "run", "print", NULL
+ };
+ enum SubIdx {
+ StartIdx, SendIdx, GetIdx, BreakIdx, ResumeIdx, StatusIdx,
+ FlushIdx, ExitIdx, RunIdx, PrintIdx
+ };
+
+ if (objc == 1 || objc > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else if ((result = Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK) {
+ return result;
+ }
+
+ switch(idx) {
+ case StartIdx:
+ if (spice_state != SPICE_INIT) {
+ Tcl_SetResult(interp, "ngspice process already running", NULL);
+ return TCL_ERROR;
+ }
+ result = start_spice();
+ if (result != 0) {
+ Tcl_SetResult(interp, "unable to run ngspice", NULL);
+ return TCL_ERROR;
+ }
+ msg = recv_from_spice(interp, EXPECT_PROMPT);
+ if (*msg == '\0')
+ return TCL_ERROR;
+ Fprintf(stdout, "%s", msg);
+ Flush(stdout);
+
+ /* Force the output not to use "more" */
+ send_to_spice("set nomoremode true");
+ msg = recv_from_spice(interp, EXPECT_PROMPT);
+
+ /* This needs to be considerably more clever. Should */
+ /* also generate the spice file if it does not exist. */
+ /* Finally, needs to add models and some statement */
+ /* like "trans" to the end to start the simulation. */
+
+ sprintf(_STR2, "source %s.spc", topobject->name);
+ send_to_spice(_STR2);
+ msg = recv_from_spice(interp, EXPECT_PROMPT);
+ if (*msg == '\0')
+ return TCL_ERROR;
+ else {
+ Fprintf(stdout, "%s", msg);
+ Flush(stdout);
+ spice_state = SPICE_READY;
+ }
+ break;
+
+ case RunIdx:
+ if (spice_state != SPICE_READY) {
+ Tcl_SetResult(interp, "Spice process busy or nonexistant", NULL);
+ return TCL_ERROR;
+ }
+
+ send_to_spice("run");
+ msg = recv_from_spice(interp, EXPECT_REF);
+ if (*msg == '\0')
+ return TCL_ERROR;
+ else {
+ spice_state = SPICE_BUSY;
+ Fprintf(stdout, "%s", msg);
+ Flush(stdout);
+ }
+ break;
+
+ case SendIdx:
+ /* Allow commands in INIT mode, because they may come from */
+ /* parameterized labels. No output will be generated. */
+ if (spice_state == SPICE_INIT)
+ break;
+ else if (spice_state == SPICE_BUSY)
+ if (break_spice(interp) < 0)
+ return TCL_ERROR;
+
+ if (objc == 2) break;
+
+ /* Prevent execution of "run" and "resume" using this */
+ /* method, so we keep control over the output and the */
+ /* state of the simulator. */
+
+ msg = Tcl_GetString(objv[2]);
+ if (!strncmp(msg, "run", 3) || !strncmp(msg, "resume", 6)) {
+ Tcl_SetResult(interp, "Do not use \"send\" with "
+ "\"run\" or \"resume\"\n", NULL);
+ return TCL_ERROR;
+ }
+ else
+ send_to_spice(msg);
+
+ msg = recv_from_spice(interp, EXPECT_PROMPT);
+ if (*msg == '\0')
+ return TCL_ERROR;
+ else
+ Tcl_SetResult(interp, msg, TCL_STATIC);
+ break;
+
+ case FlushIdx:
+ if (spice_state == SPICE_INIT)
+ break;
+ msg = recv_from_spice(interp, EXPECT_ANY); /* Grab input and discard */
+ break;
+
+ case GetIdx:
+ if (spice_state == SPICE_INIT)
+ break;
+ msg = recv_from_spice(interp, EXPECT_ANY); /* Grab input and return */
+ if (msg)
+ Tcl_SetResult(interp, msg, TCL_STATIC);
+ break;
+
+ case BreakIdx:
+ if (spice_state == SPICE_INIT)
+ break;
+ else if (spice_state == SPICE_BUSY)
+ if (break_spice(interp) < 0)
+ return TCL_ERROR;
+
+ /* Return the value of the stepsize from the function. */
+ send_to_spice("print length(TIME)");
+ goto process_result;
+
+ case PrintIdx:
+ /* Allow command in INIT mode, because it may come from */
+ /* parameterized labels. No output will be generated. */
+ if (spice_state == SPICE_INIT)
+ break;
+
+ /* Do *not* allow this command to be sent while spice */
+ /* is running. */
+ else if (spice_state == SPICE_BUSY)
+ if (break_spice(interp) < 0)
+ return TCL_ERROR;
+
+ /* Similar to "spice send {print ...}", but processes */
+ /* the output like "spice break" does to return just */
+ /* the result. However, if no index is provided for */
+ /* the variable, we determine the timestep and set the */
+ /* index accordingly. */
+ if (objc == 2) break;
+ msg = Tcl_GetString(objv[2]);
+ if (strchr(msg, '[') != NULL)
+ sprintf(_STR2, "print %s", msg);
+ else {
+ float refval;
+ char *stepstr;
+
+ send_to_spice("print length(TIME)");
+ stepstr = recv_from_spice(interp, EXPECT_PROMPT);
+ if (stepstr && ((eptr = strrchr(stepstr, '=')) != NULL)) {
+ eptr++;
+ while (isspace(*eptr)) eptr++;
+ if (sscanf(eptr, "%g", &refval) == 1)
+ sprintf(_STR2, "print %s[%d]", msg, (int)(refval - 1));
+ else
+ sprintf(_STR2, "print %s", msg);
+ }
+ else
+ sprintf(_STR2, "print %s", msg);
+ }
+ send_to_spice(_STR2);
+
+process_result:
+ msg = recv_from_spice(interp, EXPECT_PROMPT); /* Grab the output */
+ if (msg && ((eptr = strrchr(msg, '=')) != NULL)) {
+ eptr++;
+ while (isspace(*eptr)) eptr++;
+ Tcl_SetResult(interp, eptr, TCL_STATIC);
+ }
+ else if (*msg == '\0')
+ return TCL_ERROR;
+ break;
+
+ case ResumeIdx:
+ if (spice_state != SPICE_READY) {
+ Tcl_SetResult(interp, "Spice process busy or nonexistant", NULL);
+ return TCL_ERROR;
+ }
+ resume_spice();
+ break;
+
+ case StatusIdx:
+ switch(spice_state) {
+ case SPICE_INIT:
+ Tcl_SetResult(interp, "init", NULL);
+ break;
+ case SPICE_BUSY:
+ Tcl_SetResult(interp, "busy", NULL);
+ break;
+ case SPICE_READY:
+ Tcl_SetResult(interp, "ready", NULL);
+ break;
+ }
+ break;
+
+ case ExitIdx:
+ exit_spice();
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+#endif /* TCL_WRAPPER */
+/*----------------------------------------------------------------------*/
diff --git a/opengl.c b/opengl.c
new file mode 100644
index 0000000..75d1868
--- /dev/null
+++ b/opengl.c
@@ -0,0 +1,445 @@
+/*----------------------------------------------------------------------*/
+/* opengl.c --- routines defining graphics, whether OpenGL or X11 */
+/* Copyright (c) 2005 Tim Edwards, MultiGiG, Inc. */
+/*----------------------------------------------------------------------*/
+
+#ifdef OPENGL
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 6/1/05 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+
+#include "prototypes.h"
+
+extern Colormap cmap;
+extern int *appcolors;
+
+extern char STIPDATA[STIPPLES][4];
+
+extern float gl_line_limit, gl_point_limit;
+
+/*----------------------------------------------------------------------*/
+/* Global variables--- */
+/* Maintain current linewidth, because we need to pass this to the */
+/* rendering routines, since we're duplicating all of the X calls, */
+/* and they don't pass linewidth to the geometry drawing routines. */
+/*----------------------------------------------------------------------*/
+
+float cur_linewidth;
+
+/*----------------------------------------------*/
+/* Set color in OpenGL (this should be replaced */
+/* for speed. . .) */
+/*----------------------------------------------*/
+
+void
+SetForeground(Display *dpy, GC nullptr, int idx)
+{
+ XColor fgcolor;
+ int red, green, blue;
+
+ fgcolor.pixel = idx;
+ fgcolor.flags = DoRed | DoGreen | DoBlue;
+
+ XQueryColor(dpy, cmap, &fgcolor);
+
+ glColor3us((GLushort)fgcolor.red, (GLushort)fgcolor.green,
+ (GLushort)fgcolor.blue);
+}
+
+/*----------------------------------------------*/
+/* Don't know if this is meaningful or not. */
+/*----------------------------------------------*/
+
+void
+SetBackground(Display *dpy, GC nullptr, int idx)
+{
+ /* null proc */
+}
+
+/*------------------------------------------------------*/
+/* Set drawing function */
+/*------------------------------------------------------*/
+
+void
+SetFunction(Display *dpy, GC nullptr, int xfunction)
+{
+ switch (xfunction) {
+ case GXcopy:
+ glDisable(GL_COLOR_LOGIC_OP);
+ /* Is it better to disable the logic op? */
+ /*
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_COPY);
+ */
+ break;
+ case GXxor:
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_XOR);
+ break;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Set line attributes */
+/*------------------------------------------------------*/
+
+void
+SetLineAttributes(Display *dpy, GC nullptr, float lwidth,
+ int ldash, int lcap, int lbevel)
+{
+ GLfloat glwidth = (lwidth <= 0) ? 1 : (GLfloat)lwidth;
+ glLineWidth(glwidth);
+ glPointSize(glwidth);
+
+ cur_linewidth = (float)glwidth;
+
+ if (lwidth > gl_line_limit)
+ glDisable(GL_LINE_SMOOTH);
+ else
+ glEnable(GL_LINE_SMOOTH);
+
+ switch (ldash) {
+ case LineSolid:
+ glDisable(GL_LINE_STIPPLE);
+ break;
+ case LineOnOffDash:
+ glEnable(GL_LINE_STIPPLE);
+ break;
+ }
+ /* Cap and Mitre not handled by OpenGL */
+}
+
+/*------------------------------------------------------*/
+/* Set Line dash */
+/*------------------------------------------------------*/
+
+void
+SetDashes(Display *dpy, GC nullptr, int offset, char dashlist[], int n)
+{
+ union {
+ char dashbytes[2];
+ u_short dashpat;
+ } dashspec;
+
+ dashspec.dashbytes[0] = dashlist[0];
+ dashspec.dashbytes[1] = dashlist[1];
+
+ glLineStipple((GLint)1, (GLushort)dashspec.dashpat);
+}
+
+/*------------------------------------------------------*/
+/* Set Polygon fill stipple (optimize this!) */
+/*------------------------------------------------------*/
+
+void
+SetStipple(Display *dpy, GC nullptr, int stipple)
+{
+ u_char stipdata[128];
+ char *stipsrc = STIPDATA[stipple];
+ char *stipdest = stipdata;
+ int i;
+ for (i = 0; i < 32; i++) {
+ memcpy(stipdest, stipsrc, 4);
+ stipdest += 4;
+ }
+ glPolygonStipple((GLubyte *)stipdata);
+}
+
+/*------------------------------------------------------*/
+/* Set Polygon fill style */
+/* (Currently there is no differentiating between the */
+/* FillStippled and FillOpaqueStippled styles) */
+/*------------------------------------------------------*/
+
+void
+SetFillStyle(Display *dpy, GC nullptr, int fillstyle)
+{
+ switch(fillstyle) {
+ case FillSolid:
+ glDisable(GL_POLYGON_STIPPLE);
+ break;
+ case FillStippled:
+ glEnable(GL_POLYGON_STIPPLE);
+ break;
+ case FillOpaqueStippled:
+ glEnable(GL_POLYGON_STIPPLE);
+ break;
+ }
+}
+
+/*------------------------------------------------------*/
+/* Draw a line without endpoints */
+/*------------------------------------------------------*/
+
+void
+DrawLineNoEndpoint(Display *dpy, Window win, GC nullptr,
+ int x1, int y1, int x2, int y2)
+{
+ int i;
+ GLdouble x, y;
+ double theta, xmin, ymin, xmax, ymax, xoff, yoff;
+
+ /* Simple line, if we are within the hardware's width */
+ /* limit for lines. */
+
+ if (cur_linewidth < gl_line_limit) {
+ glBegin(GL_LINES);
+ glVertex2i(x1, y1);
+ glVertex2i(x2, y2);
+ glEnd();
+ return;
+ }
+
+ /* If we're outside the hardware's limit to draw */
+ /* lines, then we revert to a (much slower) */
+ /* quadrangle drawing routine. */
+
+ glBegin(GL_QUADS);
+
+ xmin = (double)x1;
+ ymin = (double)y1;
+ xmax = (double)x2;
+ ymax = (double)y2;
+ theta = atan2(ymax - ymin, xmax - xmin);
+ xoff = cur_linewidth * cos(theta - 1.5708) / 2;
+ yoff = cur_linewidth * sin(theta - 1.5708) / 2;
+
+ x = (GLdouble)(xmax + xoff);
+ y = (GLdouble)(ymax + yoff);
+ glVertex2d(x, y);
+
+ x = (GLdouble)(xmax - xoff);
+ y = (GLdouble)(ymax - yoff);
+ glVertex2d(x, y);
+
+ x = (GLdouble)(xmin - xoff);
+ y = (GLdouble)(ymin - yoff);
+ glVertex2d(x, y);
+
+ x = (GLdouble)(xmin + xoff);
+ y = (GLdouble)(ymin + yoff);
+ glVertex2d(x, y);
+
+ glEnd();
+}
+
+/*------------------------------------------------------*/
+/* Draw line (compatibility function for XDrawLine() */
+/*------------------------------------------------------*/
+
+void
+DrawLine(Display *dpy, Window win, GC nullptr,
+ int x1, int y1, int x2, int y2)
+{
+ /* Lines are capped with round ends. */
+ /* (to-do: deal with the square end flag on lines) */
+
+ DrawLineNoEndpoint(dpy, win, nullptr, x1, y1, x2, y2);
+ DrawPoint(dpy, win, nullptr, x1, y1);
+ DrawPoint(dpy, win, nullptr, x2, y2);
+}
+
+/*--------------------------------------------------------------*/
+/* Draw multiple lines (compatibility function for XDrawLines() */
+/* (Slight performance improvement over DrawLine by calling */
+/* point-drawing routine only once in-between segments). */
+/*--------------------------------------------------------------*/
+
+void
+DrawLines(Display *dpy, Window win, GC nullptr,
+ XPoint *points, int npoints, int mode)
+{
+ int i;
+
+ for (i = 0; i < npoints - 1; i++) {
+ DrawLineNoEndpoint(dpy, win, nullptr, points[i].x, points[i].y,
+ points[i + 1].x, points[i + 1].y);
+ DrawPoint(dpy, win, nullptr, points[i].x, points[i].y);
+ }
+ DrawPoint(dpy, win, nullptr, points[i].x, points[i].y);
+}
+
+/*------------------------------------------------------*/
+/* Draw point (compatibility function for XDrawPoint() */
+/* To avoid the problem with OpenGL's inability to */
+/* render smooth circles at all zoom levels, we bypass */
+/* the glPoint mechanism and use a tesselated polygon */
+/* instead. */
+/*------------------------------------------------------*/
+
+void
+DrawPoint(Display *dpy, Window win, GC nullptr, int x, int y)
+{
+ int i;
+ double theta, delta, radius;
+ GLdouble px, py;
+
+ /* If we're below the OpenGL hardware limit on smooth point */
+ /* drawing, then use the simple point-rendering routine. */
+
+ if (cur_linewidth < gl_point_limit) {
+ glBegin(GL_POINTS);
+ glVertex2i(x, y);
+ glEnd();
+ return;
+ }
+
+ /* If we're above the OpenGL hardware limit on point size, */
+ /* use a (much slower) 72-point polygon to render each dot. */
+ /* This generally works well because at the scale where */
+ /* the hardware can't render the point, it is unlikely that */
+ /* there will be more than a handful of points visible in */
+ /* the window. */
+
+ radius = (double)(cur_linewidth / 2);
+ theta = 0;
+ delta = RADFAC * (360 / RSTEPS);
+
+ glBegin(GL_POLYGON);
+ for (i = 0; i < RSTEPS; i++) {
+ px = (GLdouble)(x + radius * cos(theta));
+ py = (GLdouble)(y + radius * sin(theta));
+ theta += delta;
+ glVertex2d(px, py);
+ }
+ glEnd();
+}
+
+/*----------------------------------------------------------------------*/
+/* Helper function for GLU polygon tesselation intersections. */
+/* This routine was arbitrarily scrapped together from information in */
+/* the manpage for gluTessCallback(). */
+/*----------------------------------------------------------------------*/
+
+void
+myCombine(GLdouble coords[3], GLdouble *vertex_data[4],
+ GLfloat weight[4], GLdouble **outData)
+{
+ GLdouble *new = (GLdouble *)malloc(2 * sizeof(GLdouble));
+ new[0] = coords[0];
+ new[1] = coords[1];
+ *outData = new;
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw a filled polygon (compatibility function for XFillPolygon() */
+/*----------------------------------------------------------------------*/
+
+void
+FillPolygon(Display *dpy, Window win, GC nullptr, XPoint *points,
+ int npoints, int shape, int mode)
+{
+ int i, j;
+ static GLUtesselator *tess = NULL;
+ static GLdouble *v;
+
+ if (tess == NULL) {
+ tess = gluNewTess();
+ gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin);
+ gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex2dv);
+ gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd);
+ gluTessCallback(tess, GLU_TESS_COMBINE, (_GLUfuncptr)myCombine);
+ v = (GLdouble *)malloc(2 * npoints * sizeof(GLdouble));
+ }
+ else {
+ v = (GLdouble *)realloc(v, 2 * npoints * sizeof(GLdouble));
+ }
+
+ gluTessBeginPolygon(tess, NULL);
+ gluTessBeginContour(tess);
+ j = 0;
+ for (i = 0; i < npoints; i++, j += 2) {
+ v[j] = (GLdouble)points[i].x;
+ v[j + 1] = (GLdouble)points[i].y;
+ gluTessVertex(tess, &v[j], &v[j]);
+ }
+ gluTessEndContour(tess);
+ gluTessEndPolygon(tess);
+}
+
+/*------------------------------------------------------*/
+/* Render a background image */
+/*------------------------------------------------------*/
+
+void
+backgroundbbox(int b)
+{
+ /* null proc for now . . . */
+}
+
+void
+readbackground(FILE *f)
+{
+ /* null proc for now . . . */
+}
+
+void
+savebackground(FILE *f, char *c)
+{
+ /* null proc for now . . . */
+}
+
+void
+loadbackground()
+{
+ /* null proc for now . . . */
+}
+
+int
+renderbackground()
+{
+ /* null proc for now . . . */
+}
+
+int
+copybackground()
+{
+ /* null proc for now . . . */
+}
+
+int
+reset_gs()
+{
+ /* This is a null proc because OpenGL doesn't use */
+ /* ghostscript, and it's easier to make a null proc */
+ /* than to #ifdef the calls. */
+
+}
+
+int
+exit_gs()
+{
+ /* ditto */
+}
+
+/*-------------------------------------------------------------------------*/
+
+#endif /* OPENGL */
diff --git a/parameter.c b/parameter.c
new file mode 100644
index 0000000..eb277cb
--- /dev/null
+++ b/parameter.c
@@ -0,0 +1,2626 @@
+/*----------------------------------------------------------------------*/
+/* parameter.c */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 10/26/99 */
+/* revised for segmented strings, 3/8/01 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Externally declared global variables */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+#ifndef TCL_WRAPPER
+extern Widget menuwidgets[];
+#endif
+extern char _STR[150];
+
+/*----------------------------------------------------------------------*/
+/* The following u_char array matches parameterization types to element */
+/* types which are able to accept the given parameterization. */
+/*----------------------------------------------------------------------*/
+
+u_char param_select[] = {
+ ALL_TYPES, /* P_NUMERIC */
+ LABEL, /* P_SUBSTRING */
+ POLYGON | SPLINE | LABEL | OBJINST | ARC, /* P_POSITION_X */
+ POLYGON | SPLINE | LABEL | OBJINST | ARC, /* P_POSITION_Y */
+ POLYGON | SPLINE | ARC | PATH, /* P_STYLE */
+ LABEL, /* P_JUSTIFY */
+ ARC, /* P_ANGLE1 */
+ ARC, /* P_ANGLE2 */
+ ARC, /* P_RADIUS */
+ ARC, /* P_MINOR_AXIS */
+ LABEL | OBJINST, /* P_ROTATION */
+ LABEL | OBJINST, /* P_SCALE */
+ POLYGON | SPLINE | ARC | PATH, /* P_LINEWIDTH */
+ ALL_TYPES, /* P_COLOR */
+ ALL_TYPES, /* P_EXPRESSION */
+ POLYGON | SPLINE | LABEL | OBJINST | ARC /* P_POSITION */
+};
+
+#ifdef TCL_WRAPPER
+#ifndef _MSC_VER
+xcWidget *param_buttons[] = { NULL /* (jdk) */
+ /* To be done---map buttons to Tk_Windows! */
+};
+#else
+xcWidget *param_buttons[];
+#endif
+#else
+Widget *param_buttons[] = {
+ &ParametersNumericButton, /* P_NUMERIC */
+ &ParametersSubstringButton, /* P_SUBSTRING */
+ &ParametersPositionButton, /* P_POSITION_X */
+ &ParametersPositionButton, /* P_POSITION_Y */
+ &ParametersStyleButton, /* P_STYLE */
+ &ParametersJustificationButton, /* P_JUSTIFY */
+ &ParametersStartAngleButton, /* P_ANGLE1 */
+ &ParametersEndAngleButton, /* P_ANGLE2 */
+ &ParametersRadiusButton, /* P_RADIUS */
+ &ParametersMinorAxisButton, /* P_MINOR_AXIS */
+ &ParametersRotationButton, /* P_ROTATION */
+ &ParametersScaleButton, /* P_SCALE */
+ &ParametersLinewidthButton, /* P_LINEWIDTH */
+ &ParametersColorButton, /* P_COLOR */
+ &ParametersPositionButton, /* P_POSITION */
+};
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Basic routines for matching parameters by key values. Note that */
+/* this really, really ought to be replaced by a hash table search! */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Check for the existance of a parameter with key "key" in object */
+/* "thisobj". Return true if the parameter exists. */
+/*----------------------------------------------------------------------*/
+
+Boolean check_param(objectptr thisobj, char *key)
+{
+ oparamptr tops;
+
+ for (tops = thisobj->params; tops != NULL; tops = tops->next)
+ if (!strcmp(tops->key, key))
+ return TRUE;
+
+ return FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a new parameter; allocate memory for the parameter and the */
+/* key. */
+/*----------------------------------------------------------------------*/
+
+oparamptr make_new_parameter(char *key)
+{
+ oparamptr newops;
+
+ newops = (oparamptr)malloc(sizeof(oparam));
+ newops->next = NULL;
+ newops->key = (char *)malloc(1 + strlen(key));
+ strcpy(newops->key, key);
+ return newops;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a new element (numeric) parameter. Fill in essential values */
+/*----------------------------------------------------------------------*/
+
+eparamptr make_new_eparam(char *key)
+{
+ eparamptr newepp;
+
+ newepp = (eparamptr)malloc(sizeof(eparam));
+ newepp->next = NULL;
+ newepp->key = (char *)malloc(1 + strlen(key));
+ strcpy(newepp->key, key);
+ newepp->pdata.refkey = NULL; /* equivalently, sets pointno=0 */
+ newepp->flags = 0;
+
+ return newepp;
+}
+
+/*----------------------------------------------------------------------*/
+/* Determine if a parameter is indirectly referenced. If so, return */
+/* the parameter name. If not, return NULL. */
+/*----------------------------------------------------------------------*/
+
+char *find_indirect_param(objinstptr thisinst, char *refkey)
+{
+ eparamptr epp;
+
+ for (epp = thisinst->passed; epp != NULL; epp = epp->next) {
+ if ((epp->flags & P_INDIRECT) && !strcmp(epp->pdata.refkey, refkey))
+ return epp->key;
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the parameter in the indicated object by key */
+/*----------------------------------------------------------------------*/
+
+oparamptr match_param(objectptr thisobj, char *key)
+{
+ oparamptr fparam;
+
+ for (fparam = thisobj->params; fparam != NULL; fparam = fparam->next)
+ if (!strcmp(fparam->key, key))
+ return fparam;
+
+ return NULL; /* No parameter matched the key---error condition */
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the parameter in the indicated instance by key. If no such */
+/* instance value exists, return NULL. */
+/*----------------------------------------------------------------------*/
+
+oparamptr match_instance_param(objinstptr thisinst, char *key)
+{
+ oparamptr fparam;
+
+ for (fparam = thisinst->params; fparam != NULL; fparam = fparam->next)
+ if (!strcmp(fparam->key, key))
+ return fparam;
+
+ return NULL; /* No parameter matched the key---error condition */
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the parameter in the indicated instance by key. If no such */
+/* instance value exists, return the object (default) parameter. */
+/* */
+/* find_param() hides instances of expression parameters, returning the */
+/* default parameter value. In cases where the instance value (last */
+/* evaluated expression result) is needed, use match_instance_param(). */
+/* An exception is made when the instance param has type XC_EXPR, */
+/* indicating that the instance redefines the entire expression. */
+/*----------------------------------------------------------------------*/
+
+oparamptr find_param(objinstptr thisinst, char *key)
+{
+ oparamptr fparam, ops;
+ fparam = match_instance_param(thisinst, key);
+ ops = match_param(thisinst->thisobject, key);
+ if ((fparam == NULL) || ((ops->type == XC_EXPR) && (fparam->type != XC_EXPR)))
+ fparam = ops;
+
+ return fparam;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the total number of parameters in an object */
+/*----------------------------------------------------------------------*/
+
+int get_num_params(objectptr thisobj)
+{
+ oparamptr fparam;
+ int nparam = 0;
+
+ for (fparam = thisobj->params; fparam != NULL; fparam = fparam->next)
+ nparam++;
+ return nparam;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove all element parameters from an element */
+/*----------------------------------------------------------------------*/
+
+void free_all_eparams(genericptr thiselem)
+{
+ while (thiselem->passed != NULL)
+ free_element_param(thiselem, thiselem->passed);
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove an element parameter (eparam) and free memory associated with */
+/* the parameter key. */
+/*----------------------------------------------------------------------*/
+
+void free_element_param(genericptr thiselem, eparamptr thisepp)
+{
+ eparamptr epp, lastepp = NULL;
+
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ if (epp == thisepp) {
+ if (lastepp != NULL)
+ lastepp->next = epp->next;
+ else
+ thiselem->passed = epp->next;
+
+ /* If object is an instance and the pdata record is not NULL, */
+ /* then this is an indirect reference with the reference key */
+ /* stored as an allocated string in pdata.refkey, which needs */
+ /* to be free'd. */
+
+ if ((epp->flags & P_INDIRECT) && (epp->pdata.refkey != NULL))
+ free(epp->pdata.refkey);
+
+ free(epp->key);
+ free(epp);
+ break;
+ }
+ lastepp = epp;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Free an instance parameter. Note that this routine does not free */
+/* any strings associated with string parameters! */
+/* */
+/* Return a pointer to the entry before the one deleted, so we can use */
+/* free_instance_param() inside a loop over an instance's parameters */
+/* without having to keep track of the previous pointer position. */
+/*----------------------------------------------------------------------*/
+
+oparamptr free_instance_param(objinstptr thisinst, oparamptr thisparam)
+{
+ oparamptr ops, lastops = NULL;
+
+ for (ops = thisinst->params; ops != NULL; ops = ops->next) {
+ if (ops == thisparam) {
+ if (lastops != NULL)
+ lastops->next = ops->next;
+ else
+ thisinst->params = ops->next;
+ free(ops->key);
+ free(ops);
+ break;
+ }
+ lastops = ops;
+ }
+ return lastops;
+}
+
+/*----------------------------------------------------------------------*/
+/* Convenience function used by files.c to set a color parameter. */
+/*----------------------------------------------------------------------*/
+
+void std_eparam(genericptr gen, char *key)
+{
+ eparamptr epp;
+
+ if (key == NULL) return;
+
+ epp = make_new_eparam(key);
+ epp->next = gen->passed;
+ gen->passed = epp;
+}
+
+/*----------------------------------------------*/
+/* Draw a circle at all parameter positions */
+/*----------------------------------------------*/
+
+void indicateparams(genericptr thiselem)
+{
+ int k;
+ oparamptr ops;
+ eparamptr epp;
+ genericptr *pgen;
+
+ if (thiselem != NULL) {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ if (ops == NULL) continue; /* error condition */
+ if (ELEMENTTYPE(thiselem) == PATH)
+ k = epp->pdata.pathpt[1];
+ else
+ k = epp->pdata.pointno;
+ if (k < 0) k = 0;
+ switch(ops->which) {
+ case P_POSITION: case P_POSITION_X: case P_POSITION_Y:
+ switch(thiselem->type) {
+ case ARC:
+ UDrawCircle(&TOARC(&thiselem)->position, ops->which);
+ break;
+ case LABEL:
+ UDrawCircle(&TOLABEL(&thiselem)->position, ops->which);
+ break;
+ case OBJINST:
+ UDrawCircle(&TOOBJINST(&thiselem)->position, ops->which);
+ break;
+ case POLYGON:
+ UDrawCircle(TOPOLY(&thiselem)->points + k, ops->which);
+ break;
+ case SPLINE:
+ UDrawCircle(&TOSPLINE(&thiselem)->ctrl[k], ops->which);
+ break;
+ case PATH:
+ if (epp->pdata.pathpt[0] < 0)
+ pgen = ((pathptr)thiselem)->plist;
+ else
+ pgen = ((pathptr)thiselem)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON)
+ UDrawCircle(TOPOLY(pgen)->points + k, ops->which);
+ else /* spline */
+ UDrawCircle(&TOSPLINE(pgen)->ctrl[k], ops->which);
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------*/
+/* Set the menu marks according to properties */
+/* which are parameterized. Unmanage the */
+/* buttons which do not apply. */
+/* */
+/* pgen = NULL returns menu to default settings */
+/*----------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+void setparammarks(genericptr thiselem)
+{
+ /* Set GUI variables associated with the "parameter" menu. */
+
+ int i;
+ oparamptr ops;
+ eparamptr epp;
+ Boolean ptest[NUM_PARAM_TYPES];
+
+ for (i = 0; i < NUM_PARAM_TYPES; i++)
+ ptest[i] = FALSE;
+
+ /* For each parameter declared, set the corresponding Tcl variable */
+ if (thiselem != NULL) {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ if (ops == NULL) continue; /* error condition */
+ XcInternalTagCall(xcinterp, 3, "parameter", "make",
+ translateparamtype(ops->which));
+ ptest[ops->which] = TRUE;
+ }
+ }
+
+ /* Now reset all of those parameters that were not set above. */
+ /* Note that the parameters that we want to mark ignore the following types: */
+ /* "numeric", "substring", "expression", and "position". */
+
+ for (i = P_POSITION_X; i <= P_COLOR; i++)
+ if (ptest[i] != TRUE)
+ XcInternalTagCall(xcinterp, 3, "parameter", "replace", translateparamtype(i));
+}
+#else
+
+void setparammarks(genericptr thiselem)
+{
+ Widget w;
+ Arg wargs[1];
+ const int rlength = sizeof(param_buttons) / sizeof(Widget *);
+ int i, j, paramno;
+ oparamptr ops;
+ eparamptr epp;
+
+ /* Clear all checkmarks */
+
+ for (i = 0; i < rlength; i++) {
+ XtSetArg(wargs[0], XtNsetMark, False);
+ XtSetValues(*param_buttons[i], wargs, 1);
+ }
+
+ /* Check those properties which are parameterized in the element */
+
+ if (thiselem != NULL) {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ w = *param_buttons[ops->which];
+ XtSetArg(wargs[0], XtNsetMark, True);
+ XtSetValues(w, wargs, 1);
+ }
+ }
+
+ /* Unmanage widgets which do not apply to the element type */
+
+ for (i = 0; i < rlength; i++) {
+ if ((thiselem == NULL) || (param_select[i] & thiselem->type))
+ XtManageChild(*param_buttons[i]);
+ else
+ XtUnmanageChild(*param_buttons[i]);
+ }
+}
+
+#endif
+
+/*------------------------------------------------------*/
+/* This function is like epsubstitute() below it, but */
+/* only substitutes those values that are expression */
+/* types. This allows constraints to be applied when */
+/* editing elements. */
+/*------------------------------------------------------*/
+
+void exprsub(genericptr thiselem)
+{
+ genericptr *pgen;
+ eparamptr epp;
+ int k, ival;
+ oparamptr dps, ops;
+ float fval;
+ XPoint *setpt;
+ char *promoted;
+
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ dps = find_param(areawin->topinstance, epp->key);
+ if (dps != NULL) {
+ switch(dps->type) {
+ case XC_EXPR:
+ if ((promoted = evaluate_expr(topobject, dps, areawin->topinstance))
+ == NULL) continue;
+ if (sscanf(promoted, "%g", &fval) == 1)
+ ival = (int)(fval + 0.5);
+ free(promoted);
+ if (ELEMENTTYPE(thiselem) == PATH)
+ k = epp->pdata.pathpt[1];
+ else
+ k = epp->pdata.pointno;
+ if (ops->which == P_POSITION_X) {
+ switch(thiselem->type) {
+ case PATH:
+ pgen = TOPATH(&thiselem)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ setpt->x = ival;
+ }
+ else { /* spline */
+ TOSPLINE(pgen)->ctrl[k].x = ival;
+ }
+ break;
+ case POLYGON:
+ setpt = TOPOLY(&thiselem)->points + k;
+ setpt->x = ival;
+ break;
+ case SPLINE:
+ TOSPLINE(&thiselem)->ctrl[k].x = ival;
+ break;
+ }
+ }
+ else if (ops->which == P_POSITION_Y) {
+ switch(thiselem->type) {
+ case PATH:
+ pgen = TOPATH(&thiselem)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ setpt->y = ival;
+ }
+ else { /* spline */
+ TOSPLINE(pgen)->ctrl[k].y = ival;
+ }
+ break;
+ case POLYGON:
+ setpt = TOPOLY(&thiselem)->points + k;
+ setpt->y = ival;
+ break;
+ case SPLINE:
+ TOSPLINE(&thiselem)->ctrl[k].y = ival;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Make numerical parameter substitutions into an */
+/* element. */
+/*------------------------------------------------------*/
+
+int epsubstitute(genericptr thiselem, objectptr thisobj, objinstptr pinst,
+ Boolean *needrecalc)
+{
+ genericptr *pgen;
+ eparamptr epp;
+ oparamptr dps, ops;
+ int retval = -1;
+ int i, k, ival, diff;
+ char *key;
+ float fval;
+ XPoint *setpt;
+ char *promoted;
+
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+
+ /* Use the parameter from the instance, if available. */
+ /* Otherwise, revert to the type of the object. */
+ /* Normally they will be the same. */
+
+ ops = match_param(thisobj, epp->key);
+ dps = (pinst != NULL) ? find_param(pinst, epp->key) : ops;
+
+ if (dps != NULL) {
+
+ /* Get integer and float values. Promote types if necessary */
+
+ switch(dps->type) {
+ case XC_INT:
+ ival = dps->parameter.ivalue;
+ fval = (float)(ival);
+ break;
+ case XC_FLOAT:
+ fval = dps->parameter.fvalue;
+ ival = (int)(fval + ((fval < 0) ? -0.5 : 0.5));
+ break;
+ case XC_STRING:
+ promoted = textprint(dps->parameter.string, pinst);
+ if (sscanf(promoted, "%g", &fval) == 1)
+ ival = (int)(fval + ((fval < 0) ? -0.5 : 0.5));
+ else
+ ival = 0;
+ free(promoted);
+ break;
+ case XC_EXPR:
+ if ((promoted = evaluate_expr(thisobj, dps, pinst)) == NULL) continue;
+ if (sscanf(promoted, "%g", &fval) == 1)
+ ival = (int)(fval + ((fval < 0) ? -0.5 : 0.5));
+ free(promoted);
+ break;
+ }
+ }
+ else if (ops == NULL)
+ continue;
+
+ if ((epp->flags & P_INDIRECT) && (epp->pdata.refkey != NULL)) {
+ key = epp->pdata.refkey;
+ if (key != NULL) {
+ objinstptr thisinst;
+ oparamptr refop, newop;
+
+ thisinst = (objinstptr)thiselem;
+
+ /* Sanity check: refkey must exist in object */
+ refop = match_param(thisinst->thisobject, key);
+ if (refop == NULL) {
+ Fprintf(stderr, "Error: Reference key %s does not"
+ " exist in object %s\n",
+ key, thisinst->thisobject->name);
+ continue;
+ }
+
+ /* If an instance value already exists, remove it */
+ newop = match_instance_param(thisinst, refop->key);
+ if (newop != NULL)
+ free_instance_param(thisinst, newop);
+
+ /* Create a new instance parameter */
+ newop = copyparameter(dps);
+ newop->next = thisinst->params;
+ thisinst->params = newop;
+
+ /* Change the key from the parent to the child */
+ if (strcmp(ops->key, refop->key)) {
+ free(newop->key);
+ newop->key = strdup(refop->key);
+ }
+ continue;
+ }
+ }
+
+ if (ELEMENTTYPE(thiselem) == PATH)
+ k = epp->pdata.pathpt[1];
+ else
+ k = epp->pdata.pointno;
+ switch(ops->which) {
+ case P_POSITION_X:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case PATH:
+ if (k < 0) {
+ pgen = TOPATH(&thiselem)->plist;
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points;
+ diff = ival - setpt->x;
+ }
+ else { /* spline */
+ diff = ival - TOSPLINE(pgen)->ctrl[0].x;
+ }
+ for (pgen = TOPATH(&thiselem)->plist; pgen <
+ TOPATH(&thiselem)->plist +
+ TOPATH(&thiselem)->parts; pgen++) {
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ for (i = 0; i < TOPOLY(pgen)->number; i++) {
+ setpt = TOPOLY(pgen)->points + i;
+ setpt->x += diff;
+ }
+ }
+ else { /* spline */
+ for (i = 0; i < 4; i++) {
+ TOSPLINE(pgen)->ctrl[i].x += diff;
+ }
+ if (needrecalc) *needrecalc = True;
+ }
+ }
+ }
+ else {
+ pgen = TOPATH(&thiselem)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ setpt->x = ival;
+ }
+ else { /* spline */
+ TOSPLINE(pgen)->ctrl[k].x = ival;
+ if (needrecalc) *needrecalc = True;
+ }
+ }
+ break;
+ case POLYGON:
+ if (k < 0) {
+ setpt = TOPOLY(&thiselem)->points;
+ diff = ival - setpt->x;
+ for (i = 0; i < TOPOLY(&thiselem)->number; i++) {
+ setpt = TOPOLY(&thiselem)->points + i;
+ setpt->x += diff;
+ }
+ }
+ else {
+ setpt = TOPOLY(&thiselem)->points + k;
+ setpt->x = ival;
+ }
+ break;
+ case SPLINE:
+ if (k < 0) {
+ setpt = &(TOSPLINE(&thiselem)->ctrl[0]);
+ diff = ival - setpt->x;
+ for (i = 0; i < 4; i++) {
+ setpt = &(TOSPLINE(&thiselem)->ctrl[i]);
+ setpt->x += diff;
+ }
+ }
+ else {
+ TOSPLINE(&thiselem)->ctrl[k].x = ival;
+ }
+ if (needrecalc) *needrecalc = True;
+ break;
+ case LABEL:
+ TOLABEL(&thiselem)->position.x = ival;
+ break;
+ case OBJINST:
+ TOOBJINST(&thiselem)->position.x = ival;
+ break;
+ case ARC:
+ TOARC(&thiselem)->position.x = ival;
+ break;
+ }
+ break;
+ case P_POSITION_Y:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case PATH:
+ if (k < 0) {
+ pgen = TOPATH(&thiselem)->plist;
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points;
+ diff = ival - setpt->y;
+ }
+ else { /* spline */
+ diff = ival - TOSPLINE(pgen)->ctrl[0].y;
+ }
+ for (pgen = TOPATH(&thiselem)->plist; pgen <
+ TOPATH(&thiselem)->plist +
+ TOPATH(&thiselem)->parts; pgen++) {
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ for (i = 0; i < TOPOLY(pgen)->number; i++) {
+ setpt = TOPOLY(pgen)->points + i;
+ setpt->y += diff;
+ }
+ }
+ else { /* spline */
+ for (i = 0; i < 4; i++) {
+ TOSPLINE(pgen)->ctrl[i].y += diff;
+ }
+ if (needrecalc) *needrecalc = True;
+ }
+ }
+ }
+ else {
+ pgen = TOPATH(&thiselem)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ setpt->y = ival;
+ }
+ else { /* spline */
+ TOSPLINE(pgen)->ctrl[k].y = ival;
+ if (needrecalc) *needrecalc = True;
+ }
+ }
+ break;
+ case POLYGON:
+ if (k < 0) {
+ setpt = TOPOLY(&thiselem)->points;
+ diff = ival - setpt->y;
+ for (i = 0; i < TOPOLY(&thiselem)->number; i++) {
+ setpt = TOPOLY(&thiselem)->points + i;
+ setpt->y += diff;
+ }
+ }
+ else {
+ setpt = TOPOLY(&thiselem)->points + k;
+ setpt->y = ival;
+ }
+ break;
+ case SPLINE:
+ if (k < 0) {
+ setpt = &(TOSPLINE(&thiselem)->ctrl[0]);
+ diff = ival - setpt->y;
+ for (i = 0; i < 4; i++) {
+ setpt = &(TOSPLINE(&thiselem)->ctrl[i]);
+ setpt->y += diff;
+ }
+ }
+ else {
+ TOSPLINE(&thiselem)->ctrl[k].y = ival;
+ }
+ if (needrecalc) *needrecalc = True;
+ break;
+ case LABEL:
+ TOLABEL(&thiselem)->position.y = ival;
+ break;
+ case OBJINST:
+ TOOBJINST(&thiselem)->position.y = ival;
+ break;
+ case ARC:
+ TOARC(&thiselem)->position.y = ival;
+ break;
+ }
+ break;
+ case P_STYLE:
+ retval = max(retval, 0);
+ switch(thiselem->type) {
+ case POLYGON:
+ TOPOLY(&thiselem)->style = ival;
+ break;
+ case SPLINE:
+ TOSPLINE(&thiselem)->style = ival;
+ break;
+ case ARC:
+ TOARC(&thiselem)->style = ival;
+ break;
+ case PATH:
+ TOPATH(&thiselem)->style = ival;
+ break;
+ }
+ break;
+ case P_JUSTIFY:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case LABEL:
+ TOLABEL(&thiselem)->justify = ival;
+ break;
+ }
+ break;
+ case P_ANGLE1:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case ARC:
+ TOARC(&thiselem)->angle1 = fval;
+ if (needrecalc) *needrecalc = True;
+ break;
+ }
+ break;
+ case P_ANGLE2:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case ARC:
+ TOARC(&thiselem)->angle1 = fval;
+ if (needrecalc) *needrecalc = True;
+ break;
+ }
+ break;
+ case P_RADIUS:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case ARC:
+ TOARC(&thiselem)->radius = ival;
+ TOARC(&thiselem)->yaxis = ival;
+ if (needrecalc) *needrecalc = True;
+ break;
+ }
+ break;
+ case P_MINOR_AXIS:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case ARC:
+ TOARC(&thiselem)->yaxis = ival;
+ if (needrecalc) *needrecalc = True;
+ break;
+ }
+ break;
+ case P_ROTATION:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case LABEL:
+ TOLABEL(&thiselem)->rotation = ival;
+ break;
+ case OBJINST:
+ TOOBJINST(&thiselem)->rotation = ival;
+ break;
+ }
+ break;
+ case P_SCALE:
+ retval = max(retval, 1);
+ switch(thiselem->type) {
+ case LABEL:
+ TOLABEL(&thiselem)->scale = fval;
+ break;
+ case OBJINST:
+ TOOBJINST(&thiselem)->scale = fval;
+ break;
+ }
+ break;
+ case P_LINEWIDTH:
+ retval = max(retval, 0);
+ switch(thiselem->type) {
+ case POLYGON:
+ TOPOLY(&thiselem)->width = fval;
+ break;
+ case SPLINE:
+ TOSPLINE(&thiselem)->width = fval;
+ break;
+ case ARC:
+ TOARC(&thiselem)->width = fval;
+ break;
+ case PATH:
+ TOPATH(&thiselem)->width = fval;
+ break;
+ }
+ break;
+ case P_COLOR:
+ retval = max(retval, 0);
+ thiselem->color = ival;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+/*------------------------------------------------------*/
+/* Make numerical parameter substitutions into all */
+/* elements of an object. "thisinst" may be NULL, in */
+/* which case all default values are used in the */
+/* substitution. */
+/* */
+/* Return values: */
+/* -1 if the instance declares no parameters */
+/* 0 if parameters do not change the instance's bbox */
+/* 1 if parameters change instance's bbox */
+/* 2 if parameters change instance's netlist */
+/*------------------------------------------------------*/
+
+int opsubstitute(objectptr thisobj, objinstptr pinst)
+{
+ genericptr *eptr, *pgen, thiselem;
+ stringpart *strptr;
+ int retval = -1;
+ Boolean needrecalc; /* for arcs and splines */
+
+ /* Perform expression parameter substitutions on all labels. */
+ /* Note that this used to be done on an immediate basis as */
+ /* labels were parsed. The main difference is that only one */
+ /* expression parameter can be used per label if it is to */
+ /* compute the result of some aspect of the label, such as */
+ /* position; this is a tradeoff for much simplified handling */
+ /* of expression results, like having to avoid infinite */
+ /* recursion in an expression result. */
+
+ for (eptr = thisobj->plist; eptr < thisobj->plist + thisobj->parts; eptr++)
+ if ((*eptr)->type == LABEL)
+ for (strptr = (TOLABEL(eptr))->string; strptr != NULL; strptr =
+ nextstringpartrecompute(strptr, pinst));
+
+ if (thisobj->params == NULL)
+ return -1; /* object has no parameters */
+
+ for (eptr = thisobj->plist; eptr < thisobj->plist + thisobj->parts; eptr++) {
+
+ needrecalc = False;
+ thiselem = *eptr;
+ if (thiselem->passed == NULL) continue; /* Nothing to substitute */
+ retval = epsubstitute(thiselem, thisobj, pinst, &needrecalc);
+
+ /* substitutions into arcs and splines require that the */
+ /* line segments be recalculated. */
+
+ if (needrecalc) {
+ switch(thiselem->type) {
+ case ARC:
+ calcarc((arcptr)thiselem);
+ break;
+ case SPLINE:
+ calcspline((splineptr)thiselem);
+ break;
+ case PATH:
+ for (pgen = ((pathptr)thiselem)->plist; pgen < ((pathptr)thiselem)->plist
+ + ((pathptr)thiselem)->parts; pgen++)
+ if (ELEMENTTYPE(*pgen) == SPLINE)
+ calcspline((splineptr)*pgen);
+ break;
+ }
+ }
+ }
+ return retval;
+}
+
+/*------------------------------------------------------*/
+/* Same as above, but determines the object from the */
+/* current page hierarchy. */
+/*------------------------------------------------------*/
+
+int psubstitute(objinstptr thisinst)
+{
+ objinstptr pinst;
+ objectptr thisobj;
+
+ pinst = (thisinst == areawin->topinstance) ? areawin->topinstance : thisinst;
+ if (pinst == NULL) return -1; /* there is no instance */
+ thisobj = pinst->thisobject;
+
+ return opsubstitute(thisobj, pinst);
+}
+
+/*----------------------------------------------*/
+/* Check if an element contains a parameter. */
+/*----------------------------------------------*/
+
+Boolean has_param(genericptr celem)
+{
+ if (IS_LABEL(celem) == LABEL) {
+ stringpart *cstr;
+ labelptr clab = (labelptr)celem;
+ for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart)
+ if (cstr->type == PARAM_START)
+ return TRUE;
+ }
+ if (celem->passed != NULL) return TRUE;
+ return FALSE;
+}
+
+/*------------------------------------------------------*/
+/* Find "current working values" in the element list of */
+/* an object, and write them into the instance's */
+/* parameter list. */
+/* This is just the opposite of "psubstitute()", except */
+/* that instance values are created prior to writeback, */
+/* and resolved afterward. */
+/*------------------------------------------------------*/
+
+void pwriteback(objinstptr thisinst)
+{
+ genericptr *eptr, *pgen, thiselem;
+ objectptr thisobj;
+ objinstptr pinst;
+ eparamptr epp;
+ oparamptr ops, ips;
+ int k, type, *destivalptr, found;
+ XPoint *setpt;
+ Boolean changed, need_redraw = FALSE;
+ union {
+ int ival;
+ float fval;
+ } wtemp;
+
+ pinst = thisinst;
+ thisobj = (pinst == NULL) ? topobject : pinst->thisobject;
+
+ /* Make sure that all instance values exist */
+ if (pinst != NULL) copyparams(pinst, pinst);
+
+ /* Because more than one element can point to the same parameter, we search */
+ /* through each (numerical) parameter declared in the object. If any */
+ /* element has a different value, the parameter is changed to match. This */
+ /* operates on the assumption that no more than one element will change the */
+ /* value of any one parameter on a single call to pwriteback(). */
+
+ for (ops = thisobj->params; ops != NULL; ops = ops->next) {
+ /* handle pre-assigned numeric parameters only */
+ if ((ops->which == P_SUBSTRING) || (ops->which == P_EXPRESSION) ||
+ (ops->which == P_NUMERIC))
+ continue;
+ found = 0;
+ changed = FALSE;
+ ips = (pinst != NULL) ? match_instance_param(pinst, ops->key) : NULL;
+ for (eptr = thisobj->plist; eptr < thisobj->plist + thisobj->parts; eptr++) {
+ thiselem = *eptr;
+ if (thiselem->passed == NULL) continue; /* Nothing to write back */
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ if (!strcmp(epp->key, ops->key)) {
+ found++;
+ if (ELEMENTTYPE(thiselem) == PATH)
+ k = epp->pdata.pathpt[1];
+ else
+ k = epp->pdata.pointno;
+ if (k < 0) k = 0;
+ switch(ops->which) {
+ case P_POSITION_X:
+ switch(thiselem->type) {
+ case OBJINST:
+ wtemp.ival = TOOBJINST(eptr)->position.x;
+ break;
+ case LABEL:
+ wtemp.ival = TOLABEL(eptr)->position.x;
+ break;
+ case POLYGON:
+ setpt = TOPOLY(eptr)->points + k;
+ wtemp.ival = setpt->x;
+ break;
+ case ARC:
+ wtemp.ival = TOARC(eptr)->position.x;
+ break;
+ case SPLINE:
+ wtemp.ival = TOSPLINE(eptr)->ctrl[k].x;
+ break;
+ case PATH:
+ if (epp->pdata.pathpt[0] < 0)
+ pgen = TOPATH(eptr)->plist;
+ else
+ pgen = TOPATH(eptr)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ wtemp.ival = setpt->x;
+ }
+ else
+ wtemp.ival = TOSPLINE(pgen)->ctrl[k].x;
+ break;
+ }
+ break;
+ case P_POSITION_Y:
+ switch(thiselem->type) {
+ case OBJINST:
+ wtemp.ival = TOOBJINST(eptr)->position.y;
+ break;
+ case LABEL:
+ wtemp.ival = TOLABEL(eptr)->position.y;
+ break;
+ case POLYGON:
+ setpt = TOPOLY(eptr)->points + k;
+ wtemp.ival = setpt->y;
+ break;
+ case ARC:
+ wtemp.ival = TOARC(eptr)->position.y;
+ break;
+ case SPLINE:
+ wtemp.ival = TOSPLINE(eptr)->ctrl[k].y;
+ break;
+ case PATH:
+ if (epp->pdata.pathpt[0] < 0)
+ pgen = TOPATH(eptr)->plist;
+ else
+ pgen = TOPATH(eptr)->plist + epp->pdata.pathpt[0];
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ setpt = TOPOLY(pgen)->points + k;
+ wtemp.ival = setpt->y;
+ }
+ else
+ wtemp.ival = TOSPLINE(pgen)->ctrl[k].y;
+ break;
+ }
+ break;
+ case P_STYLE:
+ switch(thiselem->type) {
+ case POLYGON:
+ wtemp.ival = TOPOLY(eptr)->style;
+ break;
+ case ARC:
+ wtemp.ival = TOARC(eptr)->style;
+ break;
+ case SPLINE:
+ wtemp.ival = TOSPLINE(eptr)->style;
+ break;
+ case PATH:
+ wtemp.ival = TOPATH(eptr)->style;
+ break;
+ }
+ break;
+ case P_JUSTIFY:
+ switch(thiselem->type) {
+ case LABEL:
+ wtemp.ival = TOLABEL(eptr)->justify;
+ break;
+ }
+ break;
+ case P_ANGLE1:
+ switch(thiselem->type) {
+ case ARC:
+ wtemp.fval = TOARC(eptr)->angle1;
+ break;
+ }
+ break;
+ case P_ANGLE2:
+ switch(thiselem->type) {
+ case ARC:
+ wtemp.fval = TOARC(eptr)->angle1;
+ break;
+ }
+ break;
+ case P_RADIUS:
+ switch(thiselem->type) {
+ case ARC:
+ wtemp.ival = TOARC(eptr)->radius;
+ break;
+ }
+ break;
+ case P_MINOR_AXIS:
+ switch(thiselem->type) {
+ case ARC:
+ wtemp.ival = TOARC(eptr)->yaxis;
+ break;
+ }
+ break;
+ case P_ROTATION:
+ switch(thiselem->type) {
+ case OBJINST:
+ wtemp.ival = TOOBJINST(eptr)->rotation;
+ break;
+ case LABEL:
+ wtemp.ival = TOLABEL(eptr)->rotation;
+ break;
+ }
+ break;
+ case P_SCALE:
+ switch(thiselem->type) {
+ case OBJINST:
+ wtemp.fval = TOOBJINST(eptr)->scale;
+ break;
+ case LABEL:
+ wtemp.fval = TOLABEL(eptr)->scale;
+ break;
+ }
+ break;
+ case P_LINEWIDTH:
+ switch(thiselem->type) {
+ case POLYGON:
+ wtemp.fval = TOPOLY(eptr)->width;
+ break;
+ case ARC:
+ wtemp.fval = TOARC(eptr)->width;
+ break;
+ case SPLINE:
+ wtemp.fval = TOSPLINE(eptr)->width;
+ break;
+ case PATH:
+ wtemp.fval = TOPATH(eptr)->width;
+ break;
+ }
+ break;
+ case P_COLOR:
+ wtemp.ival = thiselem->color;
+ break;
+ }
+ type = (ips != NULL) ? ips->type : ops->type;
+ if (type != XC_FLOAT && type != XC_INT) break;
+
+ destivalptr = (ips != NULL) ? &ips->parameter.ivalue
+ : &ops->parameter.ivalue;
+ if ((!changed) && (wtemp.ival != *destivalptr)) {
+ *destivalptr = wtemp.ival;
+ changed = TRUE;
+ }
+ else if (found > 1) need_redraw = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Any instance values which are identical to the default value */
+ /* get erased (so they won't be written to the output unnecessarily) */
+
+ if (pinst != NULL) resolveparams(pinst);
+
+ if (need_redraw) {
+ incr_changes(thisobj);
+ invalidate_netlist(thisobj);
+ }
+
+ /* Because more than one element may use the same parameter, */
+ /* pwriteback checks for cases in which a change in one element */
+ /* precipitates a change in another. If so, force a redraw. */
+
+ if (need_redraw && (thisinst == areawin->topinstance))
+ drawarea(NULL, NULL, NULL);
+}
+
+/*------------------------------------------------------*/
+/* If the instance comes from the library, replace the */
+/* default value with the instance value. */
+/*------------------------------------------------------*/
+
+void replaceparams(objinstptr thisinst)
+{
+ objectptr thisobj;
+ oparamptr ops, ips;
+ /* int i, nullparms = 0; (jdk) */
+
+ thisobj = thisinst->thisobject;
+
+ for (ops = thisobj->params; ops != NULL; ops = ops->next) {
+ ips = match_instance_param(thisinst, ops->key);
+ if (ips == NULL) continue; /* this parameter is already default */
+
+ switch(ops->type) {
+ case XC_STRING:
+ if (stringcomp(ops->parameter.string, ips->parameter.string)) {
+ freelabel(ops->parameter.string);
+ ops->parameter.string = ips->parameter.string;
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ case XC_EXPR:
+ /* Expression parameters should be replaced *only* if the
+ * instance value is also an expression, and not an evaluated
+ * result.
+ */
+ if ((ips->type == XC_EXPR) &&
+ strcmp(ops->parameter.expr, ips->parameter.expr)) {
+ free(ops->parameter.expr);
+ ops->parameter.expr = ips->parameter.expr;
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ case XC_INT: case XC_FLOAT:
+ if (ops->parameter.ivalue != ips->parameter.ivalue) {
+ ops->parameter.ivalue = ips->parameter.ivalue;
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------*/
+/* Resolve differences between the object instance */
+/* parameters and the default parameters. If they */
+/* are the same for any parameter, delete that instance */
+/* such that the instance reverts to the default value. */
+/*------------------------------------------------------*/
+
+void resolveparams(objinstptr thisinst)
+{
+ objectptr thisobj;
+ liblistptr spec;
+ oparamptr ops, ips;
+ int i;
+
+ /* If the instance has no parameters itself, ignore it. */
+ if (thisinst == NULL || thisinst->params == NULL) return;
+
+ /* If the object was pushed into from a library, we want to change */
+ /* the default, not the instanced, parameter values. However, this */
+ /* is not true for "virtual" library objects (in the instlist) */
+
+ if ((i = checklibtop()) >= 0) {
+ for (spec = xobjs.userlibs[i].instlist; spec != NULL;
+ spec = spec->next)
+ if (spec->thisinst == thisinst)
+ break;
+
+ if ((spec == NULL) || (spec->virtual == FALSE)) {
+ /* Fprintf(stdout, "Came from library: changing default value\n"); */
+ replaceparams(thisinst);
+ return;
+ }
+ }
+
+ /* Parameters which are changed on a top-level page must also change */
+ /* the default value; otherwise, the instance value shadows the page */
+ /* object's value but the page object's value is the one written to */
+ /* the output file. */
+
+ else if (is_page(thisinst->thisobject) >= 0) {
+ replaceparams(thisinst);
+ return;
+ }
+
+ thisobj = thisinst->thisobject;
+
+ for (ops = thisobj->params; ops != NULL; ops = ops->next) {
+ ips = match_instance_param(thisinst, ops->key);
+ if (ips == NULL) continue; /* this parameter is already default */
+
+ /* If type or which fields do not match, then we don't need to look */
+ /* any further; object and instance have different parameters. */
+ if ((ips->type != ops->type) || (ips->which != ops->which)) continue;
+
+ switch(ops->type) {
+ case XC_STRING:
+ if (!stringcomp(ops->parameter.string, ips->parameter.string)) {
+ freelabel(ips->parameter.string);
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ case XC_EXPR:
+ if (!strcmp(ops->parameter.expr, ips->parameter.expr)) {
+ free(ips->parameter.expr);
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ case XC_INT: case XC_FLOAT:
+ if (ops->parameter.ivalue == ips->parameter.ivalue) {
+ free_instance_param(thisinst, ips);
+ }
+ break;
+ }
+ }
+
+ if (thisinst->params != NULL) {
+ /* Object must recompute bounding box if any instance */
+ /* uses a non-default parameter. */
+
+ calcbboxvalues(thisinst, NULL);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Return a copy of the single eparameter "cepp" */
+/*--------------------------------------------------------------*/
+
+eparamptr copyeparam(eparamptr cepp, genericptr thiselem)
+{
+ eparamptr newepp;
+
+ newepp = make_new_eparam(cepp->key);
+ if ((cepp->flags & P_INDIRECT) && (cepp->pdata.refkey != NULL))
+ newepp->pdata.refkey = strdup(cepp->pdata.refkey);
+ else
+ newepp->pdata.pointno = cepp->pdata.pointno; /* also covers pathpt[] */
+ newepp->flags = cepp->flags;
+ return newepp;
+}
+
+/*------------------------------------------------------*/
+/* Copy all element parameters from source to dest */
+/*------------------------------------------------------*/
+
+void copyalleparams(genericptr destinst, genericptr sourceinst)
+{
+ eparamptr cepp, newepp;
+
+ for (cepp = sourceinst->passed; cepp != NULL; cepp = cepp->next) {
+ newepp = copyeparam(cepp, sourceinst);
+ newepp->next = destinst->passed;
+ destinst->passed = newepp;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Return a copy of the single parameter "cops" */
+/*--------------------------------------------------------------*/
+
+oparamptr copyparameter(oparamptr cops)
+{
+ oparamptr newops;
+
+ newops = make_new_parameter(cops->key);
+ newops->type = cops->type;
+ newops->which = cops->which;
+ switch(cops->type) {
+ case XC_STRING:
+ newops->parameter.string = stringcopy(cops->parameter.string);
+ break;
+ case XC_EXPR:
+ newops->parameter.expr = strdup(cops->parameter.expr);
+ break;
+ case XC_INT: case XC_FLOAT:
+ newops->parameter.ivalue = cops->parameter.ivalue;
+ break;
+ default:
+ Fprintf(stderr, "Error: bad parameter\n");
+ break;
+ }
+ return newops;
+}
+
+/*------------------------------------------------------*/
+/* Fill any NULL instance parameters with the values */
+/* from the calling instance, or from the instance */
+/* object's defaults if destinst = sourceinst. */
+/* */
+/* Expression parameters get special treatment because */
+/* the instance value may be holding the last evaluated */
+/* expression, not an instance value of the expression. */
+/* If so, its type will be XC_STRING or XC_FLOAT, not */
+/* XC_EXPR. */
+/*------------------------------------------------------*/
+
+void copyparams(objinstptr destinst, objinstptr sourceinst)
+{
+ oparamptr psource, cops, newops, ips;
+
+ if (sourceinst == NULL) return;
+ if (destinst == sourceinst)
+ psource = sourceinst->thisobject->params;
+ else
+ psource = sourceinst->params;
+
+ for (cops = psource; cops != NULL; cops = cops->next) {
+ if ((ips = match_instance_param(destinst, cops->key)) == NULL) {
+ newops = copyparameter(cops);
+ newops->next = destinst->params;
+ destinst->params = newops;
+ }
+ else if ((cops->type == XC_EXPR) && (ips->type != XC_EXPR))
+ free_instance_param(destinst, ips);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Make an unreferenced parameter expression in the object */
+/* refobject. */
+/* The expression may have either a numeric or string result. */
+/* the proper "which" value is passed as an argument. */
+/* */
+/* Return NULL if unsuccessful, the parameter key (which may */
+/* have been modified by checkvalidname()) otherwise. */
+/*--------------------------------------------------------------*/
+
+char *makeexprparam(objectptr refobject, char *key, char *value, int which)
+{
+ oparamptr newops;
+ char *newkey, stkey[20];
+ int pidx;
+
+ /* Check against object names, which are reserved words */
+
+ if (key == NULL) {
+ strcpy(stkey, getnumericalpkey(which));
+ pidx = 0;
+ while (check_param(refobject, stkey)) {
+ pidx++;
+ sprintf(stkey, "%s%d", getnumericalpkey(which), pidx);
+ }
+ newkey = stkey;
+ }
+ else {
+ /* Check parameter key for valid name syntax */
+
+ newkey = checkvalidname(key, NULL);
+ if (newkey == NULL) newkey = key;
+
+ /* Ensure that no two parameters have the same name! */
+
+ if (check_param(refobject, newkey)) {
+ Wprintf("There is already a parameter named %s!", newkey);
+ if (newkey != key) free(newkey);
+ return NULL;
+ }
+ }
+
+ newops = make_new_parameter(newkey);
+ newops->next = refobject->params;
+ refobject->params = newops;
+ newops->type = XC_EXPR; /* expression requiring evaluation */
+ newops->which = which;
+ newops->parameter.expr = strdup(value);
+ incr_changes(refobject);
+ if ((newkey != key) && (newkey != stkey)) free(newkey);
+
+ return newops->key;
+}
+
+/*------------------------------------------------------------------*/
+/* Make an unreferenced numerical parameter in the object refobject */
+/* */
+/* Return FALSE if unsuccessful, TRUE otherwise. */
+/*------------------------------------------------------------------*/
+
+Boolean makefloatparam(objectptr refobject, char *key, float value)
+{
+ oparamptr newops;
+ char *newkey;
+
+ /* Check against object names, which are reserved words */
+
+ newkey = checkvalidname(key, NULL);
+ if (newkey == NULL) newkey = key;
+
+ /* Ensure that no two parameters have the same name! */
+
+ if (check_param(refobject, newkey)) {
+ Wprintf("There is already a parameter named %s!", newkey);
+ if (newkey != key) free(newkey);
+ return FALSE;
+ }
+
+ newops = make_new_parameter(key);
+ newops->next = refobject->params;
+ refobject->params = newops;
+ newops->type = XC_FLOAT; /* general-purpose numeric */
+ newops->which = P_NUMERIC;
+ newops->parameter.fvalue = value;
+ incr_changes(refobject);
+ if (newkey != key) free(newkey);
+
+ return TRUE;
+}
+
+/*----------------------------------------------------------------*/
+/* Make an unreferenced string parameter in the object refobject. */
+/* Return FALSE if unsuccessful, TRUE otherwise. */
+/*----------------------------------------------------------------*/
+
+Boolean makestringparam(objectptr refobject, char *key, stringpart *strptr)
+{
+ oparamptr newops;
+ char *newkey;
+
+ /* Check against object names, which are reserved words */
+
+ newkey = checkvalidname(key, NULL);
+ if (newkey == NULL) newkey = key;
+
+ /* Ensure that no two parameters have the same name! */
+
+ if (check_param(refobject, newkey)) {
+ Wprintf("There is already a parameter named %s!", newkey);
+ if (newkey != key) free(newkey);
+ return FALSE;
+ }
+
+ newops = make_new_parameter(newkey);
+ newops->next = refobject->params;
+ refobject->params = newops;
+ newops->type = XC_STRING;
+ newops->which = P_SUBSTRING;
+ newops->parameter.string = strptr;
+ incr_changes(refobject);
+ if (newkey != key) free(newkey);
+
+ return TRUE;
+}
+
+/*--------------------------------------------------------------*/
+/* Return the built-in parameter key corresponding to a */
+/* parameter type (as defined in xcircuit.h). */
+/* */
+/* Numerical parameters have designated keys to avoid the */
+/* necessity of having to specify a key, to avoid conflicts */
+/* with PostScript predefined keys, and other good reasons. */
+/*--------------------------------------------------------------*/
+
+char *getnumericalpkey(u_int mode)
+{
+ static char *param_keys[] = {
+ "p_gps", "p_str", "p_xps", "p_yps", "p_sty", "p_jst", "p_an1",
+ "p_an2", "p_rad", "p_axs", "p_rot", "p_scl", "p_wid", "p_col",
+ "p_bad"
+ };
+
+ if (mode < 0 || mode > 13) return param_keys[14];
+ return param_keys[mode];
+}
+
+/*--------------------------------------------------------------*/
+/* Make a numerical (integer or float) parameter. */
+/* If "key" is non-NULL, then the parameter key will be set */
+/* from this rather than from the list "param_keys". If the */
+/* key is an existing key with the same type as "mode", then */
+/* the new parameter will be linked to the existing one. */
+/*--------------------------------------------------------------*/
+
+void makenumericalp(genericptr *gelem, u_int mode, char *key, short cycle)
+{
+ genericptr pgen, *pathpgen;
+ oparamptr ops, newops;
+ eparamptr epp;
+ XPoint *pptr;
+ char new_key[7], *keyptr;
+ int pidx, i;
+ short loccycle = cycle;
+
+ /* Parameterized strings are handled by makeparam() */
+
+ if (IS_LABEL(*gelem) && mode == P_SUBSTRING) {
+ Fprintf(stderr, "Error: String parameter passed to makenumericalp()\n");
+ return;
+ }
+
+ /* Make sure the parameter doesn't already exist. */
+
+ for (epp = (*gelem)->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ if (ops->which == (u_char)mode) {
+ if ((mode == P_POSITION_X || mode == P_POSITION_Y) &&
+ ((*gelem)->type == POLYGON || (*gelem)->type == SPLINE) &&
+ (TOPOLY(gelem)->cycle != NULL))
+ {
+ if ((cycle < 0) || (TOPOLY(gelem)->cycle->number != cycle)) {
+ Fprintf(stderr, "Cannot duplicate a point parameter!\n");
+ return;
+ }
+ }
+ else {
+ Fprintf(stderr, "Cannot duplicate a parameter!\n");
+ return;
+ }
+ }
+ }
+
+ /* Ensure that no two parameters have the same name! */
+
+ if (key) {
+ keyptr = checkvalidname(key, NULL);
+ if (keyptr == NULL) keyptr = key;
+ }
+ else {
+ strcpy(new_key, getnumericalpkey(mode));
+ pidx = 0;
+ while (check_param(topobject, new_key)) {
+ pidx++;
+ sprintf(new_key, "%s%d", getnumericalpkey(mode), pidx);
+ }
+ keyptr = new_key;
+ }
+
+ /* Add the parameter to the element's parameter list */
+
+ epp = make_new_eparam(keyptr);
+ epp->next = (*gelem)->passed;
+ (*gelem)->passed = epp;
+
+ /* If keyptr does not point to an existing parameter, then we need */
+ /* to create it in the object's parameter list and set the default */
+ /* value to the existing value of the element. */
+
+ ops = match_param(topobject, keyptr);
+ if (ops == NULL) {
+ newops = make_new_parameter(keyptr);
+ newops->next = topobject->params;
+ topobject->params = newops;
+ newops->type = XC_INT; /* most commonly used value */
+ newops->which = (u_char)mode; /* what kind of parameter */
+ incr_changes(topobject);
+ }
+ else {
+ if (ops->which != (u_char)mode) {
+ free_element_param(*gelem, epp);
+ Fprintf(stderr, "Error: Attempt to link a parameter to "
+ "a parameter of a different type\n");
+ goto param_done;
+ }
+ else if (ops->type == XC_EXPR)
+ goto param_done;
+
+ if ((newops = match_instance_param(areawin->topinstance, keyptr)) == NULL) {
+ newops = make_new_parameter(keyptr);
+ newops->next = areawin->topinstance->params;
+ areawin->topinstance->params = newops;
+ newops->type = ops->type;
+ newops->which = ops->which;
+ }
+ else {
+ /* If the parameter exists and the instance has a non-default */
+ /* value for it, we will not change the instance record. If */
+ /* the element value is different, then it will change, so we */
+ /* should redraw. */
+ drawarea(NULL, NULL, NULL);
+ newops = NULL;
+ }
+ }
+
+ if (newops) {
+ if (mode == P_COLOR)
+ newops->parameter.ivalue = (int)((*gelem)->color);
+
+ switch((*gelem)->type) {
+ case LABEL:
+ switch(mode) {
+ case P_POSITION_X:
+ newops->parameter.ivalue = (int)TOLABEL(gelem)->position.x;
+ break;
+ case P_POSITION_Y:
+ newops->parameter.ivalue = (int)TOLABEL(gelem)->position.y;
+ break;
+ case P_JUSTIFY:
+ newops->parameter.ivalue = (int)TOLABEL(gelem)->justify;
+ break;
+ case P_ROTATION:
+ newops->parameter.ivalue = (int)TOLABEL(gelem)->rotation;
+ break;
+ case P_SCALE:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOLABEL(gelem)->scale;
+ break;
+ }
+ break;
+ case ARC:
+ switch(mode) {
+ case P_POSITION_X:
+ newops->parameter.ivalue = (int)TOARC(gelem)->position.x;
+ break;
+ case P_POSITION_Y:
+ newops->parameter.ivalue = (int)TOARC(gelem)->position.y;
+ break;
+ case P_ANGLE1:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOARC(gelem)->angle1;
+ break;
+ case P_ANGLE2:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOARC(gelem)->angle2;
+ break;
+ case P_RADIUS:
+ newops->parameter.ivalue = (int)TOARC(gelem)->radius;
+ break;
+ case P_MINOR_AXIS:
+ newops->parameter.ivalue = (int)TOARC(gelem)->yaxis;
+ break;
+ case P_STYLE:
+ newops->parameter.ivalue = (int)TOARC(gelem)->style;
+ break;
+ case P_LINEWIDTH:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOARC(gelem)->width;
+ break;
+ }
+ break;
+ case OBJINST:
+ switch(mode) {
+ case P_POSITION_X:
+ newops->parameter.ivalue = (int)TOOBJINST(gelem)->position.x;
+ break;
+ case P_POSITION_Y:
+ newops->parameter.ivalue = (int)TOOBJINST(gelem)->position.y;
+ break;
+ case P_ROTATION:
+ newops->parameter.ivalue = (int)TOOBJINST(gelem)->rotation;
+ break;
+ case P_SCALE:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOOBJINST(gelem)->scale;
+ break;
+ }
+ break;
+ case POLYGON:
+ if (loccycle == -1)
+ loccycle = (TOPOLY(gelem)->cycle != NULL) ?
+ TOPOLY(gelem)->cycle->number : -1;
+ switch(mode) {
+ case P_POSITION_X:
+ if (loccycle == -1) {
+ pptr = TOPOLY(gelem)->points;
+ newops->parameter.ivalue = (int)pptr->x;
+ for (i = 0; i < TOPOLY(gelem)->number; i++) {
+ pptr = TOPOLY(gelem)->points + i;
+ pptr->x -= newops->parameter.ivalue;
+ }
+ } else {
+ pptr = TOPOLY(gelem)->points + loccycle;
+ newops->parameter.ivalue = (int)pptr->x;
+ }
+ epp->pdata.pointno = loccycle;
+ break;
+ case P_POSITION_Y:
+ if (loccycle == -1) {
+ pptr = TOPOLY(gelem)->points;
+ newops->parameter.ivalue = (int)pptr->y;
+ for (i = 0; i < TOPOLY(gelem)->number; i++) {
+ pptr = TOPOLY(gelem)->points + i;
+ pptr->y -= newops->parameter.ivalue;
+ }
+ } else {
+ pptr = TOPOLY(gelem)->points + loccycle;
+ newops->parameter.ivalue = (int)pptr->y;
+ }
+ epp->pdata.pointno = loccycle;
+ break;
+ case P_STYLE:
+ newops->parameter.ivalue = (int)TOPOLY(gelem)->style;
+ break;
+ case P_LINEWIDTH:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOPOLY(gelem)->width;
+ break;
+ }
+ break;
+ case SPLINE:
+ if (loccycle == -1)
+ loccycle = (TOSPLINE(gelem)->cycle != NULL) ?
+ TOSPLINE(gelem)->cycle->number : -1;
+ switch(mode) {
+ case P_POSITION_X:
+ if (loccycle == -1) {
+ pptr = &(TOSPLINE(gelem)->ctrl[0]);
+ newops->parameter.ivalue = (int)pptr->x;
+ for (i = 0; i < 4; i++) {
+ pptr = &(TOSPLINE(gelem)->ctrl[i]);
+ pptr->x -= newops->parameter.ivalue;
+ }
+ } else {
+ pptr = TOSPLINE(gelem)->ctrl + loccycle;
+ newops->parameter.ivalue = (int)pptr->x;
+ }
+ epp->pdata.pointno = loccycle;
+ break;
+ case P_POSITION_Y:
+ if (loccycle == -1) {
+ pptr = &(TOSPLINE(gelem)->ctrl[0]);
+ newops->parameter.ivalue = (int)pptr->y;
+ for (i = 0; i < 4; i++) {
+ pptr = &(TOSPLINE(gelem)->ctrl[i]);
+ pptr->y -= newops->parameter.ivalue;
+ }
+ } else {
+ pptr = TOSPLINE(gelem)->ctrl + loccycle;
+ newops->parameter.ivalue = (int)pptr->y;
+ }
+ epp->pdata.pointno = loccycle;
+ break;
+ case P_STYLE:
+ newops->parameter.ivalue = (int)TOSPLINE(gelem)->style;
+ break;
+ case P_LINEWIDTH:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOSPLINE(gelem)->width;
+ break;
+ }
+ break;
+ case PATH:
+ if (loccycle == -1 && (mode == P_POSITION_X || mode == P_POSITION_Y)) {
+ pgen = getsubpart(TOPATH(gelem), &pidx);
+ if (ELEMENTTYPE(pgen) == POLYGON)
+ loccycle = (((polyptr)pgen)->cycle != NULL) ?
+ ((polyptr)pgen)->cycle->number : -1;
+ else
+ loccycle = (((splineptr)pgen)->cycle != NULL) ?
+ ((splineptr)pgen)->cycle->number : -1;
+ }
+ else {
+ Fprintf(stderr, "Can't parameterize a path point from "
+ "the command line.\n");
+ break;
+ }
+ switch(mode) {
+ case P_STYLE:
+ newops->parameter.ivalue = (int)TOPATH(gelem)->style;
+ break;
+ case P_LINEWIDTH:
+ newops->type = XC_FLOAT;
+ newops->parameter.fvalue = TOPATH(gelem)->width;
+ break;
+ case P_POSITION_X:
+ newops->type = XC_INT;
+ if (loccycle == -1) {
+ pathpgen = TOPATH(gelem)->plist;
+ if (ELEMENTTYPE(*pathpgen) == POLYGON) {
+ pptr = TOPOLY(pathpgen)->points;
+ newops->parameter.ivalue = (int)pptr->x;
+ }
+ else {
+ pptr = &(TOSPLINE(pathpgen)->ctrl[0]);
+ newops->parameter.ivalue = (int)pptr->x;
+ }
+ for (pathpgen = TOPATH(gelem)->plist; pathpgen <
+ TOPATH(gelem)->plist + TOPATH(gelem)->parts;
+ pathpgen++) {
+ if (ELEMENTTYPE(*pathpgen) == POLYGON) {
+ for (i = 0; i < TOPOLY(pathpgen)->number; i++) {
+ pptr = TOPOLY(pathpgen)->points + i;
+ pptr->x -= newops->parameter.ivalue;
+ }
+ }
+ else {
+ for (i = 0; i < 4; i++) {
+ pptr = &(TOSPLINE(pathpgen)->ctrl[i]);
+ pptr->x -= newops->parameter.ivalue;
+ }
+ }
+ }
+ }
+ else {
+ if (ELEMENTTYPE(pgen) == POLYGON)
+ newops->parameter.ivalue = ((polyptr)pgen)->points[loccycle].x;
+ else
+ newops->parameter.ivalue = ((splineptr)pgen)->ctrl[loccycle].x;
+ epp->pdata.pathpt[1] = loccycle;
+ epp->pdata.pathpt[0] = pidx;
+ }
+ break;
+ case P_POSITION_Y:
+ newops->type = XC_INT;
+ if (loccycle == -1) {
+ pathpgen = TOPATH(gelem)->plist;
+ if (ELEMENTTYPE(*pathpgen) == POLYGON) {
+ pptr = TOPOLY(pathpgen)->points;
+ newops->parameter.ivalue = (int)pptr->y;
+ }
+ else {
+ pptr = &(TOSPLINE(pathpgen)->ctrl[0]);
+ newops->parameter.ivalue = (int)pptr->y;
+ }
+ for (pathpgen = TOPATH(gelem)->plist; pathpgen <
+ TOPATH(gelem)->plist + TOPATH(gelem)->parts;
+ pathpgen++) {
+ if (ELEMENTTYPE(*pathpgen) == POLYGON) {
+ for (i = 0; i < TOPOLY(pathpgen)->number; i++) {
+ pptr = TOPOLY(pathpgen)->points + i;
+ pptr->y -= newops->parameter.ivalue;
+ }
+ }
+ else {
+ for (i = 0; i < 4; i++) {
+ pptr = &(TOSPLINE(pathpgen)->ctrl[i]);
+ pptr->y -= newops->parameter.ivalue;
+ }
+ }
+ }
+ }
+ else {
+ if (ELEMENTTYPE(pgen) == POLYGON)
+ newops->parameter.ivalue = ((polyptr)pgen)->points[loccycle].y;
+ else
+ newops->parameter.ivalue = ((splineptr)pgen)->ctrl[loccycle].y;
+ epp->pdata.pathpt[1] = loccycle;
+ epp->pdata.pathpt[0] = pidx;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+param_done:
+ if ((keyptr != new_key) && (keyptr != key)) free(keyptr);
+}
+
+/*--------------------------------------------------------------*/
+/* Remove a numerical (integer or float) parameter. Remove by */
+/* type, rather than key. There may be several keys associated */
+/* with a particular type, so we want to remove all of them. */
+/*--------------------------------------------------------------*/
+
+void removenumericalp(genericptr *gelem, u_int mode)
+{
+ genericptr *pgen;
+ eparamptr epp;
+ oparamptr ops;
+ char *key;
+ Boolean done = False, is_last = True;
+
+ /* Parameterized strings are handled by makeparam() */
+ if (mode == P_SUBSTRING) {
+ Fprintf(stderr, "Error: Unmakenumericalp called on a string parameter.\n");
+ return;
+ }
+
+ /* Avoid referencing the object by only looking at the element. */
+ /* But, avoid dereferencing the pointer! */
+
+ while (!done) {
+ key = NULL;
+ done = True;
+ for (epp = (*gelem)->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(topobject, epp->key);
+ if (ops == NULL) break; /* Error---no such parameter */
+ else if (ops->which == (u_char)mode) {
+ key = ops->key;
+ free_element_param(*gelem, epp);
+
+ /* check for any other references to the parameter. If there */
+ /* are none, remove all instance records of the eparam, then */
+ /* remove the parameter itself from the object. */
+
+ for (pgen = topobject->plist; pgen < topobject->plist
+ + topobject->parts; pgen++) {
+ if (*pgen == *gelem) continue;
+ for (epp = (*pgen)->passed; epp != NULL; epp = epp->next) {
+ if (!strcmp(epp->key, key)) {
+ is_last = False;
+ break;
+ }
+ }
+ if (!is_last) break;
+ }
+ if (is_last)
+ free_object_param(topobject, ops);
+
+ done = False;
+ break;
+ }
+ }
+ }
+}
+
+#ifndef TCL_WRAPPER
+
+/*--------------------------------------------------------------*/
+/* Insert an existing parameter into a string. */
+/* This code needs to be replaced in the non-Tcl version with */
+/* a new pop-up window using a callback to labeltext(). */
+/* */
+/* This routine has been replaced in the Tcl version with a */
+/* callback to command "label insert parameter" from the */
+/* parameter-select pop-up window. */
+/*--------------------------------------------------------------*/
+
+void insertparam()
+{
+ labelptr tlab;
+ oparamptr ops;
+ int result, nparms;
+ char *selparm;
+ char *newstr, *sptr;
+ char *sstart = (char *)malloc(1024);
+ oparamptr chosen_ops=NULL;
+
+ /* Don't allow nested parameters */
+
+ tlab = TOLABEL(EDITPART);
+ if (paramcross(topobject, tlab)) {
+ Wprintf("Parameters cannot be nested!");
+ return;
+ }
+
+ nparms = 0;
+ strcpy(sstart, "Choose: ");
+ sptr = sstart + 8;
+ for (ops = topobject->params; ops != NULL; ops = ops->next) {
+ if (ops->type == XC_STRING) {
+ chosen_ops = ops;
+ nparms++;
+ if (nparms != 1) {
+ strcat(sptr, ", ");
+ sptr += 2;
+ }
+ newstr = stringprint(ops->parameter.string, NULL);
+ sprintf(sptr, "%d = %s = <%s", nparms, ops->key, newstr);
+ free(newstr);
+ newstr = NULL;
+ sptr += strlen(sptr);
+ }
+ }
+
+ /* If only one parameter, then automatically use it. Otherwise, */
+ /* prompt for which parameter to use. */
+
+ if (nparms > 1) {
+ int i=0, select_int;
+ chosen_ops = NULL;
+ Wprintf("%s", sstart);
+ select_int = getkeynum();
+ for (ops = topobject->params; ops != NULL; ops = ops->next) {
+ if (ops->type == XC_STRING) {
+ if (i==select_int) chosen_ops = ops;
+ i++;
+ }
+ }
+ }
+
+ free(sstart);
+ ops = chosen_ops;
+ if (ops != NULL) selparm = ops->key;
+
+ if (ops != NULL)
+ labeltext(PARAM_START, selparm);
+ else
+ Wprintf("No such parameter.");
+}
+
+#endif
+
+/*--------------------------------------------------------------*/
+/* Parameterize a label string. */
+/*--------------------------------------------------------------*/
+
+void makeparam(labelptr thislabel, char *key)
+{
+ oparamptr newops;
+ stringpart *begpart, *endpart;
+ char *newkey;
+
+ /* Ensure that no two parameters have the same name! */
+
+ if (check_param(topobject, key)) {
+ Wprintf("There is already a parameter named %s!", key);
+ areawin->textend = 0;
+ return;
+ }
+
+ /* make sure this does not overlap another parameter */
+
+ if (paramcross(topobject, thislabel)) {
+ Wprintf("Parameters cannot be nested!");
+ areawin->textend = 0;
+ return;
+ }
+
+ /* Check parameter for valid name syntax */
+
+ newkey = checkvalidname(key, NULL);
+ if (newkey == NULL) newkey = key;
+
+ /* First, place PARAM_START and PARAM_END structures at the */
+ /* intended parameter boundaries */
+
+ if (areawin->textend > 0 && areawin->textend < areawin->textpos) {
+ /* partial string */
+ splitstring(areawin->textend, &thislabel->string, areawin->topinstance);
+ splitstring(areawin->textpos, &thislabel->string, areawin->topinstance);
+
+ /* Because "splitstring" changes all the pointers, find the */
+ /* stringpart structures at textend and textpos positions. */
+
+ begpart = findstringpart(areawin->textend, NULL, thislabel->string,
+ areawin->topinstance);
+ endpart = findstringpart(areawin->textpos, NULL, thislabel->string,
+ areawin->topinstance);
+
+ /* Make the new segments for PARAM_START and PARAM_END. */
+
+ begpart = makesegment(&thislabel->string, begpart);
+ endpart = makesegment(&thislabel->string, endpart);
+ }
+ else { /* full string */
+ /* Don't include the first font designator as part of the */
+ /* parameter or else havoc ensues. */
+ if (thislabel->string->type == FONT_NAME && thislabel->string->nextpart
+ != NULL) {
+ makesegment(&thislabel->string, thislabel->string->nextpart);
+ begpart = thislabel->string->nextpart;
+ }
+ else {
+ makesegment(&thislabel->string, thislabel->string);
+ begpart = thislabel->string;
+ }
+ endpart = makesegment(&thislabel->string, NULL);
+ }
+ begpart->type = PARAM_START;
+ begpart->data.string = (char *)malloc(1 + strlen(newkey));
+ strcpy(begpart->data.string, newkey);
+ endpart->type = PARAM_END;
+ endpart->data.string = (u_char *)NULL;
+
+ /* Now move the sections of string to the object parameter */
+
+ newops = make_new_parameter(newkey);
+ newops->next = topobject->params;
+ topobject->params = newops;
+ newops->type = XC_STRING;
+ newops->which = P_SUBSTRING;
+ newops->parameter.string = begpart->nextpart;
+ begpart->nextpart = endpart->nextpart;
+ endpart->nextpart = NULL;
+
+ areawin->textend = 0;
+ incr_changes(topobject);
+ if (newkey != key) free(newkey);
+}
+
+/*--------------------------------------------------------------*/
+/* Destroy the selected parameter in the indicated instance */
+/*--------------------------------------------------------------*/
+
+void destroyinst(objinstptr tinst, objectptr refobj, char *key)
+{
+ oparamptr ops;
+ /* short k; (jdk) */
+
+ if (tinst->thisobject == refobj) {
+ ops = match_instance_param(tinst, key);
+ if (ops != NULL) {
+ if (ops->type == XC_STRING)
+ freelabel(ops->parameter.string);
+ else if (ops->type == XC_EXPR)
+ free(ops->parameter.expr);
+ free_instance_param(tinst, ops);
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Search and destroy the selected parameter in all instances */
+/* of the specified object. */
+/*--------------------------------------------------------------*/
+
+void searchinst(objectptr topobj, objectptr refobj, char *key)
+{
+ objinstptr tinst;
+ genericptr *pgen;
+
+ if (topobj == NULL) return;
+
+ for (pgen = topobj->plist; pgen < topobj->plist + topobj->parts; pgen++) {
+ if (IS_OBJINST(*pgen)) {
+ tinst = TOOBJINST(pgen);
+ destroyinst(tinst, refobj, key);
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Destroy the object parameter with key "key" in the object */
+/* "thisobj". This requires first tracking down and removing */
+/* all instances of the parameter which may exist anywhere in */
+/* the database. */
+/*--------------------------------------------------------------*/
+
+void free_object_param(objectptr thisobj, oparamptr thisparam)
+{
+ int k, j, l = -1;
+ liblistptr spec;
+ oparamptr ops, lastops = NULL;
+ genericptr *pgen;
+ char *key = thisparam->key;
+
+ /* Find all instances of this object and remove any parameter */
+ /* substitutions which may have been made. */
+
+ for (k = 0; k < xobjs.pages; k++) {
+ if (xobjs.pagelist[k]->pageinst != NULL)
+ searchinst(xobjs.pagelist[k]->pageinst->thisobject, thisobj, key);
+ }
+ for (j = 0; j < xobjs.numlibs; j++) {
+ for (k = 0; k < xobjs.userlibs[j].number; k++) {
+ if (*(xobjs.userlibs[j].library + k) == thisobj)
+ l = j;
+ else
+ searchinst(*(xobjs.userlibs[j].library + k), thisobj, key);
+ }
+ }
+
+ /* Ensure that this parameter is not referred to in the undo records */
+ /* We could be kinder and gentler to the undo record here. . . */
+ flush_undo_stack();
+
+ /* Also check through all instances on the library page */
+ if (l >= 0)
+ for (spec = xobjs.userlibs[l].instlist; spec != NULL; spec = spec->next)
+ destroyinst(spec->thisinst, thisobj, key);
+
+ /* Remove the parameter from any labels that it might occur in */
+
+ for (pgen = thisobj->plist; pgen < thisobj->plist + thisobj->parts; pgen++) {
+ if (IS_LABEL(*pgen)) {
+ Boolean pending = TRUE;
+ stringpart *strptr;
+ labelptr plab = TOLABEL(pgen);
+
+ while (pending) {
+ pending = FALSE;
+ for (strptr = plab->string; strptr != NULL; strptr = strptr->nextpart) {
+ if (strptr->type == PARAM_START) {
+ if (!strcmp(strptr->data.string, key)) {
+ unmakeparam(plab, strptr);
+ pending = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Remove the parameter from the object itself, tidying up */
+ /* the linked list after it. */
+
+ for (ops = thisobj->params; ops != NULL; ops = ops->next) {
+ if (ops == thisparam) {
+ if (lastops != NULL)
+ lastops->next = ops->next;
+ else
+ thisobj->params = ops->next;
+ free(ops->key);
+ free(ops);
+ break;
+ }
+ lastops = ops;
+ }
+
+ incr_changes(thisobj);
+}
+
+/*--------------------------------------------------------------*/
+/* Check if this string contains a parameter */
+/*--------------------------------------------------------------*/
+
+stringpart *searchparam(stringpart *tstr)
+{
+ stringpart *rval = tstr;
+ for (rval = tstr; rval != NULL; rval = rval->nextpart)
+ if (rval->type == PARAM_START)
+ break;
+ return rval;
+}
+
+/*--------------------------------------------------------------*/
+/* Remove parameterization from a label string or substring. */
+/*--------------------------------------------------------------*/
+
+void unmakeparam(labelptr thislabel, stringpart *thispart)
+{
+ oparamptr ops;
+ stringpart *strptr, *lastpart, *endpart, *newstr, *subs;
+ char *key;
+
+ /* make sure there is a parameter here */
+
+ if (thispart->type != PARAM_START) {
+ Wprintf("There is no parameter here.");
+ return;
+ }
+ key = thispart->data.string;
+
+ /* Unparameterizing can cause a change in the string */
+ undrawtext(thislabel);
+
+ /* Methodology change 7/20/06: Remove only the instance of the */
+ /* parameter. The parameter itself will be deleted by a different */
+ /* method, using free_object_param(). */
+
+ ops = match_param(topobject, key);
+ subs = ops->parameter.string;
+
+ /* Copy the default parameter into the place we are unparameterizing */
+
+ newstr = NULL;
+ newstr = stringcopy(subs);
+
+ /* Delete the "PARAM_END" off of the copied string and link it into */
+ /* the existing string. */
+ /* (NOTE: If parameter is an empty string, there may be nothing */
+ /* before PARAM_END. . .) */
+
+ if (newstr->type != PARAM_END) {
+ for (endpart = newstr; endpart->nextpart->type != PARAM_END;
+ endpart = endpart->nextpart);
+ free(endpart->nextpart);
+ endpart->nextpart = thispart->nextpart;
+ }
+ else {
+ endpart = newstr;
+ newstr = newstr->nextpart;
+ free(endpart);
+ endpart = NULL;
+ }
+
+ /* Find the stringpart before the parameter call (if any) */
+
+ lastpart = NULL;
+ for (strptr = thislabel->string; strptr != NULL && strptr != thispart;
+ strptr = strptr->nextpart) {
+ lastpart = strptr;
+ }
+ if (lastpart == NULL)
+ thislabel->string = newstr;
+ else
+ lastpart->nextpart = newstr;
+ free(strptr);
+
+ /* Merge strings at boundaries, if possible. */
+ if (endpart) mergestring(endpart);
+ mergestring(lastpart);
+
+ redrawtext(thislabel);
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrapper for unmakeparam(). Remove a parameterized substring from a */
+/* label, or remove a numeric parameter from an element. */
+/* */
+/* NOTE: This routine should not combine the instance-only string */
+/* parameter removal and the numeric parameter deletion, which is */
+/* fundamentally different in nature. */
+/*----------------------------------------------------------------------*/
+
+void unparameterize(int mode)
+{
+ short *fselect, ptype;
+ int locpos;
+ stringpart *strptr, *tmpptr, *lastptr;
+ labelptr settext;
+
+ if (mode >= 0) {
+ ptype = (short)param_select[mode];
+ if (!checkselect(ptype)) select_element(ptype);
+ if (!checkselect(ptype)) return;
+ }
+ else
+ ptype = ALL_TYPES;
+
+ if ((areawin->selects == 1) && (mode == P_SUBSTRING) && areawin->textend > 0
+ && areawin->textend < areawin->textpos) {
+ if (SELECTTYPE(areawin->selectlist) != LABEL) return; /* Not a label */
+ settext = SELTOLABEL(areawin->selectlist);
+ strptr = findstringpart(areawin->textend, &locpos, settext->string,
+ areawin->topinstance);
+ while (strptr != NULL && strptr->type != PARAM_END)
+ strptr = strptr->nextpart;
+ if (strptr == NULL) return; /* No parameters */
+ tmpptr = settext->string;
+ lastptr = NULL;
+
+ /* Search for parameter boundary, in case selection doesn't include */
+ /* the whole parameter or the parameter start marker. */
+
+ for (tmpptr = settext->string; tmpptr != NULL && tmpptr != strptr;
+ tmpptr = nextstringpart(tmpptr, areawin->topinstance))
+ if (tmpptr->type == PARAM_START) lastptr = tmpptr;
+ /* Finish search, unlinking any parameter we might be inside */
+ for (; tmpptr != NULL; tmpptr = nextstringpart(tmpptr, areawin->topinstance));
+
+ if (lastptr != NULL) unmakeparam(settext, lastptr);
+ }
+ else {
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if ((mode == P_SUBSTRING) && SELECTTYPE(fselect) == LABEL) {
+ settext = SELTOLABEL(fselect);
+ strptr = settext->string;
+ while (strptr != NULL && strptr->type != PARAM_START)
+ strptr = strptr->nextpart;
+ if (strptr != NULL) unmakeparam(settext, strptr);
+ }
+ else if (mode == P_POSITION) {
+ removenumericalp(topobject->plist + (*fselect), P_POSITION_X);
+ removenumericalp(topobject->plist + (*fselect), P_POSITION_Y);
+ }
+ else
+ removenumericalp(topobject->plist + (*fselect), mode);
+ }
+ setparammarks(NULL);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Wrapper for makeparam() */
+/*--------------------------------------------------------------*/
+
+void parameterize(int mode, char *key, short cycle)
+{
+ short *fselect, ptype;
+ labelptr settext;
+ Boolean preselected;
+
+ preselected = (areawin->selects > 0) ? TRUE : FALSE;
+ if (mode >= 0) {
+ ptype = (short)param_select[mode];
+ if (!checkselect(ptype)) select_element(ptype);
+ if (!checkselect(ptype)) return;
+ }
+ else
+ ptype = ALL_TYPES;
+
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if ((mode == P_SUBSTRING) && (areawin->selects == 1) &&
+ (SELECTTYPE(fselect) == LABEL)) {
+ settext = SELTOLABEL(fselect);
+ makeparam(settext, key);
+ }
+ else if (mode == P_POSITION) {
+ makenumericalp(topobject->plist + (*fselect), P_POSITION_X, key, cycle);
+ makenumericalp(topobject->plist + (*fselect), P_POSITION_Y, key, cycle);
+ }
+ else
+ makenumericalp(topobject->plist + (*fselect), mode, key, cycle);
+ }
+ if (!preselected) unselect_all();
+ setparammarks(NULL);
+}
+
+/*----------------------------------------------------------------------*/
+/* Looks for a parameter overlapping the textend <--> textpos space. */
+/* Returns True if there is a parameter in this space. */
+/*----------------------------------------------------------------------*/
+
+Boolean paramcross(objectptr tobj, labelptr tlab)
+{
+ stringpart *firstptr, *lastptr;
+ int locpos;
+
+ lastptr = findstringpart(areawin->textpos, &locpos, tlab->string,
+ areawin->topinstance);
+
+ /* This text position can't be inside another parameter */
+ for (firstptr = lastptr; firstptr != NULL; firstptr = firstptr->nextpart)
+ if (firstptr->type == PARAM_END) return True;
+
+ /* The area between textend and textpos cannot contain a parameter */
+ if (areawin->textend > 0)
+ for (firstptr = findstringpart(areawin->textend, &locpos, tlab->string,
+ areawin->topinstance); firstptr != lastptr;
+ firstptr = firstptr->nextpart)
+ if (firstptr->type == PARAM_START || firstptr->type == PARAM_END)
+ return True;
+
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Check whether this page object was entered via a library page */
+/*----------------------------------------------------------------------*/
+
+int checklibtop()
+{
+ int i;
+ pushlistptr thispush;
+
+ for (thispush = areawin->stack; thispush != NULL; thispush = thispush->next)
+ if ((i = is_library(thispush->thisinst->thisobject)) >= 0)
+ return i;
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove all parameters from an object instance */
+/* (Reverts all parameters to default value) */
+/*----------------------------------------------------------------------*/
+
+void removeinstparams(objinstptr thisinst)
+{
+ oparamptr ops;
+
+ while (thisinst->params != NULL) {
+ ops = thisinst->params;
+ thisinst->params = ops->next;
+ free(ops->key);
+ if (ops->type == XC_STRING)
+ freelabel(ops->parameter.string);
+ else if (ops->type == XC_EXPR)
+ free(ops->parameter.expr);
+ free(ops);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove all parameters from an object. */
+/*----------------------------------------------------------------------*/
+
+void removeparams(objectptr thisobj)
+{
+ oparamptr ops;
+
+ while (thisobj->params != NULL) {
+ ops = thisobj->params;
+ thisobj->params = ops->next;
+ free(ops->key);
+ if (ops->type == XC_STRING)
+ freelabel(ops->parameter.string);
+ else if (ops->type == XC_EXPR)
+ free(ops->parameter.expr);
+ free(ops);
+ }
+ thisobj->params = NULL;
+}
+
+/*-----------------------------------------------------------------------*/
diff --git a/pp.c b/pp.c
new file mode 100644
index 0000000..f17156a
--- /dev/null
+++ b/pp.c
@@ -0,0 +1,129 @@
+/*--------------------------------------------------------------*/
+/* pp.c -- */
+/* */
+/* This helper program emulates m4 pre-processor behavior. */
+/* */
+/* As of July 2006, XCircuit no longer uses m4, having replaced */
+/* it with "sed" scripts. However, since this C code was */
+/* written to bypass the lack of "m4" under Windows, it is */
+/* still required to bypass the lack of "sed" under Windows. */
+/* The "m4" emulation is maintained. However, the m4 files */
+/* have been rewritten to remove the awkward "ifelse" syntax, */
+/* which has been replaced with a simpler "<variable_name>" */
+/* at the beginning of each variable-dependent line. This */
+/* program also handles those situations. */
+/*--------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+
+typedef struct _pattern {
+ char *pattern;
+ char *string;
+ struct _pattern *next;
+} pattern;
+
+pattern* parse_args(int* argc, char ***argv)
+{
+ int i, len = 0;
+ pattern *p = (pattern*)malloc(sizeof(pattern));
+
+ p->pattern = "`eval'";
+ p->string = "eval";
+ p->next = NULL;
+
+ for (i=1; i<(*argc); i++) {
+ if (strncmp((*argv)[i], "-D", 2) == 0) {
+ char *c = strchr((*argv)[i], '=');
+ pattern *new_p;
+ if (c == NULL) {
+ printf("Invalid argument: %s\n", (*argv[i]));
+ exit(-1);
+ }
+ new_p = (pattern*)malloc(sizeof(pattern));
+ new_p->next = p;
+ p = new_p;
+ c[0] = '\0';
+ p->pattern = strdup((*argv)[i]+2);
+ if (c[1] == '"') {
+ char *c2;
+ c += 2;
+ c2 = strchr(c, '"');
+ if (c2 != NULL)
+ c2[0] = '\0';
+ } else {
+ char *c2;
+ c++;
+ c2 = strchr(c, ' ');
+ if (c2 != NULL)
+ c2[0] = '\0';
+ }
+ p->string = strdup(c);
+ /*fprintf(stderr, "%s -> %s\n", p->pattern, p->string);*/
+ len++;
+ }
+ }
+
+ *argc -= len+1;
+ *argv += len+1;
+
+ return p;
+}
+
+int main(int argc, char **argv)
+{
+ char buffer[4096];
+ char buffer2[4096];
+ char *c;
+ int i;
+ pattern *patterns, *p;
+ FILE *fin;
+
+ patterns = parse_args(&argc, &argv);
+
+ if (argc > 0) {
+ fin = fopen(argv[0], "r");
+ if (fin == NULL) {
+ printf("Unable to open file: %s\n", argv[0]);
+ exit(-1);
+ }
+ }
+ else
+ fin = stdin;
+
+ while (1) {
+ if (fgets(buffer, 4096, fin) == 0)
+ exit(0);
+ p = patterns;
+ while (p) {
+ while ((c = strstr(buffer, p->pattern)) != NULL) {
+ c[0] = '\0';
+
+ /* Handle variable-dependent lines */
+ if (c == buffer && !strcmp(p->string, "1")) {
+ strcpy(buffer2, c + strlen(p->pattern) + 1);
+ strcpy(buffer, buffer2);
+ }
+ else if (c == buffer && !strcmp(p->string, "0")) {
+ p = NULL;
+ break;
+ }
+ else {
+ strcpy(buffer2, buffer);
+ strcat(buffer2, p->string);
+ strcat(buffer2, c + strlen(p->pattern));
+ strcpy(buffer, buffer2);
+ }
+ }
+ if (p == NULL) break;
+ p = p->next;
+ }
+ if (buffer[0] != '\0')
+ printf("%s", buffer);
+ }
+
+ if (argc > 0)
+ fclose(fin);
+
+ return 0;
+}
diff --git a/prototypes.h b/prototypes.h
new file mode 100644
index 0000000..bb5fb38
--- /dev/null
+++ b/prototypes.h
@@ -0,0 +1,1019 @@
+/*----------------------------------------------------------------------*/
+/* prototypes.h: */
+/* Master list of function prototypes */
+/*----------------------------------------------------------------------*/
+
+/* from undo.c */
+
+/* Note variable argument list for register_for_undo() */
+extern void register_for_undo(u_int, u_char, objinstptr, ...);
+extern void undo_finish_series(void);
+extern void undo_action(void);
+extern void redo_action(void);
+extern void flush_undo_stack(void);
+extern void flush_redo_stack(void);
+extern void truncate_undo_stack(void);
+extern void free_undo_record(Undoptr);
+extern void free_redo_record(Undoptr);
+extern stringpart *get_original_string(labelptr);
+extern short *recover_selectlist(Undoptr);
+extern void free_selection(uselection *);
+extern uselection *remember_selection(objinstptr, short *, int);
+extern short *regen_selection(objinstptr, uselection *);
+#ifndef TCL_WRAPPER
+extern void undo_call(xcWidget, caddr_t, caddr_t);
+extern void redo_call(xcWidget, caddr_t, caddr_t);
+#endif
+
+
+/* from tclxcircuit.c */
+
+#ifdef TCL_WRAPPER
+extern void xctk_drag(ClientData, XEvent *);
+extern void xctk_draglscroll(ClientData, XEvent *);
+extern void xctk_dragfilebox(ClientData, XEvent *);
+extern void tcl_stdflush(FILE *);
+extern void tcl_printf(FILE *, const char *, ...);
+extern int XcTagCallback(Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
+extern Tcl_Obj *evaluate_raw(objectptr, oparamptr, objinstptr, int *);
+extern char *TCL_to_PS(char *);
+extern XCWindowData *GUI_init(int, Tcl_Obj *CONST objv[]);
+extern void build_app_database(Tk_Window);
+extern int XcInternalTagCall(Tcl_Interp *, int, ...);
+extern char *translateparamtype(int);
+extern char *translatestyle(int);
+extern char *translateencoding(int);
+
+#endif
+
+extern char *evaluate_expr(objectptr, oparamptr, objinstptr);
+
+/* from opengl.c: compatibility functions for OpenGL/X11 */
+
+#ifdef OPENGL
+extern void SetForeground(Display *, GC, int);
+extern void SetBackground(Display *, GC, int);
+extern void SetFunction(Display *, GC, int);
+extern void SetLineAttributes(Display *, GC, float, int, int, int);
+extern void SetDashes(Display *, GC, int, char dashlist[], int);
+extern void SetStipple(Display *, GC, int);
+extern void SetFillStyle(Display *, GC, int);
+extern void DrawLine(Display *, Window, GC, int, int, int, int);
+extern void DrawLines(Display *, Window, GC, XPoint *, int, int);
+extern void DrawPoint(Display *, Window, GC, int, int);
+extern void FillPolygon(Display *, Window, GC, XPoint *, int, int, int);
+#endif
+
+/* from elements.c: */
+
+/* element constructor functions */
+extern labelptr new_label(objinstptr, stringpart *, int, int, int);
+extern labelptr new_simple_label(objinstptr, char *, int, int, int);
+extern labelptr new_temporary_label(objectptr, char *, int, int);
+extern polyptr new_polygon(objinstptr, pointlist *, int);
+extern splineptr new_spline(objinstptr, pointlist);
+extern arcptr new_arc(objinstptr, int, int, int);
+extern objinstptr new_objinst(objinstptr, objinstptr, int, int);
+
+/* element destructor function */
+extern void remove_element(objinstptr, genericptr);
+
+/* functions to set default values for element types */
+extern void polydefaults(polyptr, int, int, int);
+extern void splinedefaults(splineptr, int, int);
+extern void arcdefaults(arcptr, int, int);
+extern void pathdefaults(pathptr, int, int);
+extern void instancedefaults(objinstptr, objectptr, int, int);
+extern void labeldefaults(labelptr, u_char, int, int);
+
+extern void converttocurve();
+extern void poly_add_point(polyptr, XPoint *);
+extern void drawdot(int, int);
+extern void copyalleparams(genericptr, genericptr);
+extern void copyparams(objinstptr, objinstptr);
+
+extern void textbutton(u_char, int, int);
+extern void charreport(labelptr);
+extern Boolean labeltext(int, char *);
+extern void textreturn(void);
+extern void rejustify(short);
+extern void findconstrained(polyptr);
+extern void reversepoints(XPoint *, short);
+extern void reversefpoints(XfPoint *, short);
+extern void freeparts(short *, short);
+extern void removep(short *, short);
+extern void unjoin(void);
+extern labelptr findlabelcopy(labelptr, stringpart *);
+extern Boolean neartest(XPoint *, XPoint *);
+extern void join(void);
+extern genericptr getsubpart(pathptr, int *);
+
+/* interactive manipulation of elements */
+extern void splinebutton(int, int);
+extern void updatepath(pathptr);
+extern void trackelement(xcWidget, caddr_t, caddr_t);
+extern void arcbutton(int, int);
+extern void trackarc(xcWidget, caddr_t, caddr_t);
+extern void boxbutton(int, int);
+extern void trackbox(xcWidget, caddr_t, caddr_t);
+extern void trackwire(xcWidget, caddr_t, caddr_t);
+extern void startwire(XPoint *);
+extern void setendpoint(short *, short, XPoint **, XPoint *);
+extern void wire_op(int, int ,int);
+
+/* from events.c: */
+
+extern Boolean recursefind(objectptr, objectptr);
+extern void transferselects(void);
+extern void select_invalidate_netlist(void);
+extern void newmatrix(void);
+extern void setpage(Boolean);
+extern int changepage(short);
+extern void newpage(short);
+extern void pushobject(objinstptr);
+extern void push_stack(pushlistptr *, objinstptr, char *);
+extern void pop_stack(pushlistptr *);
+extern void free_stack(pushlistptr *);
+extern void popobject(xcWidget, pointertype, caddr_t);
+extern void resetbutton(xcWidget, pointertype, caddr_t);
+extern void drawhbar(xcWidget, caddr_t, caddr_t);
+extern void drawvbar(xcWidget, caddr_t, caddr_t);
+extern void panhbar(xcWidget, caddr_t, XButtonEvent *);
+extern void endhbar(xcWidget, caddr_t, XButtonEvent *);
+extern void panvbar(xcWidget, caddr_t, XButtonEvent *);
+extern void endvbar(xcWidget, caddr_t, XButtonEvent *);
+extern void zoombox(xcWidget, caddr_t, caddr_t);
+extern void zoomin(int, int);
+extern void zoomout(int, int);
+extern void warppointer(int, int);
+extern void panbutton(u_int, int, int, float);
+extern void zoominrefresh(int, int);
+extern void zoomoutrefresh(int, int);
+extern void panrefresh(u_int, int, int, float);
+extern void checkwarp(XPoint *);
+extern void warparccycle(arcptr, short);
+extern int checkcycle(genericptr, short);
+extern pointselect *getrefpoint(genericptr, XPoint **);
+extern void copyvirtual(void);
+extern void nextpathcycle(pathptr, short);
+extern void nextpolycycle(polyptr *, short);
+extern void nextsplinecycle(splineptr *, short);
+extern void nextarccycle(arcptr *, short);
+extern void buttonhandler(xcWidget, caddr_t, XButtonEvent *);
+extern void keyhandler(xcWidget, caddr_t, XKeyEvent *);
+extern Boolean compatible_function(int);
+extern int eventdispatch(int, int, int);
+extern int functiondispatch(int, short, int, int);
+extern void releasehandler(xcWidget, caddr_t, XKeyEvent *);
+extern void setsnap(short);
+extern void snapelement(void);
+extern int ipow10(int);
+extern int calcgcf(int, int);
+extern void fraccalc(float, char *);
+extern void printpos(short, short);
+extern void findwirex(XPoint *, XPoint *, XPoint *, XPoint *, int *);
+extern void findattach(XPoint *, int *, XPoint *);
+extern XPoint *pathclosepoint(pathptr, XPoint *);
+extern void placeselects(short, short, XPoint *);
+extern void drag(int, int);
+extern void xlib_drag(xcWidget, caddr_t, XEvent *);
+extern void elemrotate(genericptr *, short, XPoint *);
+extern void elementrotate(short, XPoint *);
+extern void edit(int, int);
+extern void pathedit(genericptr);
+extern void xc_lower();
+extern void xc_raise();
+extern void xc_top(short *, short *);
+extern void xc_bottom(short *, short *);
+extern void exchange(void);
+extern void elhflip(genericptr *, short);
+extern void elvflip(genericptr *, short);
+extern void elementflip(XPoint *);
+extern void elementvflip(XPoint *);
+extern short getkeynum(void);
+#ifdef TCL_WRAPPER
+extern void makepress(ClientData);
+#else
+extern void makepress(XtPointer, xcIntervalId *);
+#endif
+extern void reviseselect(short *, int, short *);
+extern void deletebutton(int, int);
+extern void delete_one_element(objinstptr, genericptr);
+extern short *xc_undelete(objinstptr, objectptr, short, short *);
+extern objectptr delete_element(objinstptr, short *, int, short);
+extern void printname(objectptr);
+extern Boolean checkname(objectptr);
+extern char *checkvalidname(char *, objectptr);
+extern objectptr finddot(void);
+extern void movepoints(genericptr *, short, short);
+extern void editpoints(genericptr *, short, short);
+#ifndef TCL_WRAPPER
+extern void xlib_makeobject(xcWidget, caddr_t);
+#endif
+extern objinstptr domakeobject(int, char *, Boolean);
+extern void selectsave(xcWidget, caddr_t, caddr_t);
+extern void arceditpush(arcptr);
+extern void splineeditpush(splineptr);
+extern void polyeditpush(polyptr);
+extern void patheditpush(pathptr);
+extern pointlist copypoints(pointlist, int);
+extern void labelcopy(labelptr, labelptr);
+extern void arccopy(arcptr, arcptr);
+extern void polycopy(polyptr, polyptr);
+extern void splinecopy(splineptr, splineptr);
+extern void pathcopy(pathptr, pathptr);
+extern void instcopy(objinstptr, objinstptr);
+extern void delete_tagged(objinstptr);
+extern void createcopies(void);
+extern void copydrag(void);
+extern void copy_op(int, int, int);
+extern Boolean checkmultiple(XButtonEvent *);
+extern void continue_op(int, int, int);
+extern void finish_op(int, int, int);
+extern void path_op(genericptr, int, int, int);
+extern void inst_op(genericptr, int, int, int);
+extern void resizearea(xcWidget, caddr_t, caddr_t);
+extern void drawarea(xcWidget, caddr_t, caddr_t);
+extern void standard_element_delete(short);
+extern void delete_for_xfer(short, short *, int);
+extern void delete_noundo(short);
+
+/* from filelist.c: */
+
+extern int fcompare(const void *, const void *);
+extern void dragfilebox(xcWidget, caddr_t, XMotionEvent *);
+extern void startfiletrack(xcWidget, caddr_t, XCrossingEvent *);
+extern void endfiletrack(xcWidget, caddr_t, XCrossingEvent *);
+extern char *getcrashfilename(void);
+extern void crashrecover(void);
+extern void findcrashfiles(void);
+extern void listfiles(xcWidget, popupstruct *, caddr_t);
+extern void newfilelist(xcWidget, popupstruct *);
+extern void fileselect(xcWidget, popupstruct *, XButtonEvent *);
+extern void showlscroll(xcWidget, caddr_t, caddr_t);
+extern void draglscroll(xcWidget, popupstruct *, XButtonEvent *);
+extern void genfilelist(xcWidget, popupstruct *, Dimension);
+extern int lookdirectory(char *, int);
+
+/* from files.c: */
+
+#ifdef ASG
+extern void importspice(void);
+#endif
+
+extern char *ridnewline(char *);
+extern void free_single(genericptr);
+extern void reset(objectptr, short);
+extern void pagereset(short);
+extern void initmem(objectptr);
+extern void freelabel(stringpart *);
+extern Boolean compare_single(genericptr *, genericptr *);
+extern Boolean elemcompare(genericptr *, genericptr *);
+extern short objcompare(objectptr, objectptr);
+extern float getpsscale(float, short);
+extern void dostcount(FILE *, short *, short);
+extern short printparams(FILE *, objinstptr, short);
+extern void printobjectparams(FILE *, objectptr);
+extern void varcheck(FILE *, short, objectptr, short *, genericptr, u_char);
+extern void varfcheck(FILE *, float, objectptr, short *, genericptr, u_char);
+extern Boolean varpcheck(FILE *, short, objectptr, int, short *, genericptr, u_char);
+extern Boolean varpathcheck(FILE *, short, objectptr, int, short *,
+ genericptr *, pathptr, u_char);
+extern void getfile(xcWidget, pointertype, caddr_t);
+extern int filecmp(char *, char *);
+extern Boolean nextfilename(void);
+extern FILE *libopen(char *, short, char *, int);
+extern void loadfontlib(void);
+extern void loadglib(Boolean, short, short);
+extern void loadulib(void);
+extern void loadblib(void);
+extern void getlib(xcWidget, caddr_t, caddr_t);
+extern void getuserlib(xcWidget, caddr_t, caddr_t);
+extern Boolean loadlibrary(short);
+extern void startloadfile(int);
+extern void normalloadfile(void);
+extern void importfile(void);
+extern Boolean loadfile(short, int);
+extern void readlabel(objectptr, char *, stringpart **);
+extern void readparams(objectptr, objinstptr, objectptr, char *);
+extern u_char *find_match(u_char *);
+extern char *advancetoken(char *);
+extern char *varpscan(objectptr, char *, short *, genericptr, int, int, u_char);
+extern char *varscan(objectptr, char *, short *, genericptr, u_char);
+extern char *varfscan(objectptr, char *, float *, genericptr, u_char);
+extern objinstptr addtoinstlist(int, objectptr, Boolean);
+extern Boolean objectread(FILE *, objectptr, short, short, short, char *, int, TechPtr);
+void importfromlibrary(short, char *, char *);
+objectptr *new_library_object(short, char *, objlistptr *, TechPtr);
+Boolean library_object_unique(short, objectptr, objlistptr);
+void add_object_to_library(short, objectptr);
+u_char *find_delimiter(u_char *);
+char standard_delimiter_end(char);
+void output_graphic_data(FILE *, short *);
+
+extern Boolean CompareTechnology(objectptr, char *);
+extern TechPtr LookupTechnology(char *);
+extern TechPtr GetObjectTechnology(objectptr);
+extern TechPtr AddNewTechnology(char *, char *);
+extern void AddObjectTechnology(objectptr);
+extern void TechReplaceSave();
+extern void TechReplaceRestore();
+extern void TechReplaceAll();
+extern void TechReplaceNone();
+
+#ifdef TCL_WRAPPER
+extern void setfile(char *, int);
+extern void savetemp(ClientData);
+#else
+extern void setfile(xcWidget, xcWidget, caddr_t);
+extern void savetemp(XtPointer, xcIntervalId *);
+#endif
+extern void incr_changes(objectptr);
+extern void savelibpopup(xcWidget, char *, caddr_t);
+#ifndef TCL_WRAPPER
+extern void savelibrary(xcWidget, char *);
+#endif
+extern void savetechnology(char *, char *);
+extern void findfonts(objectptr, short *);
+extern void savefile(short);
+extern int printRGBvalues(char *, int, const char *);
+extern char *nosprint(char *, int *, int *);
+extern FILE *fileopen(char *, char *, char *, int);
+extern Boolean xc_tilde_expand(char *, int);
+extern Boolean xc_variable_expand(char *, int);
+extern short writelabel(FILE *, stringpart *, short *);
+extern char *writesegment(stringpart *, float *, int *, int *, int *);
+extern int writelabelsegs(FILE *, short *, stringpart *);
+extern void printobjects(FILE *, objectptr, objectptr **, short *, int);
+extern void printrefobjects(FILE *, objectptr, objectptr **, short *);
+extern void printpageobject(FILE *, objectptr, short, short);
+
+
+/* from fontfile.c: */
+
+extern FILE *findfontfile(char *);
+extern int loadfontfile(char *);
+
+/* from formats.c: */
+
+extern void loadlgf(int);
+extern void loadmat4(caddr_t);
+
+/* from functions.c: */
+
+extern long sqwirelen(XPoint *, XPoint *);
+extern float fsqwirelen(XfPoint *, XfPoint *);
+extern int wirelength(XPoint *, XPoint *);
+extern long finddist(XPoint *,XPoint *, XPoint *);
+extern void calcarc(arcptr);
+extern void decomposearc(pathptr);
+extern void initsplines(void);
+extern void computecoeffs(splineptr, float *, float *, float *, float *,
+ float *, float *);
+extern void calcspline(splineptr);
+extern void findsplinepos(splineptr, float, XPoint *, int *);
+extern void ffindsplinepos(splineptr, float, XfPoint *);
+extern float findsplinemin(splineptr, XPoint *);
+extern short closepoint(polyptr, XPoint *);
+extern short closedistance(polyptr, XPoint *);
+extern void updateinstparam(objectptr);
+extern short checkbounds(void);
+extern void window_to_user(short, short, XPoint *);
+extern void user_to_window(XPoint, XPoint *);
+
+extern float UTopScale(void);
+extern float UTopTransScale(float);
+extern float UTopDrawingScale(void);
+extern int UTopRotation(void);
+extern void UTopOffset(int *, int *);
+extern void UTopDrawingOffset(int *, int *);
+
+extern XPoint UGetCursor(void);
+extern XPoint UGetCursorPos(void);
+extern void u2u_snap(XPoint *);
+extern void snap(short, short, XPoint *);
+extern void UResetCTM(Matrix *);
+extern void InvertCTM(Matrix *);
+extern void UCopyCTM(Matrix *, Matrix *);
+extern void UMakeWCTM(Matrix *);
+extern void UMultCTM(Matrix *, XPoint, float, short);
+extern void USlantCTM(Matrix *, float);
+extern void UPreScaleCTM(Matrix *);
+extern short flipadjust(short);
+extern void UPreMultCTM(Matrix *, XPoint, float, short);
+extern void UPreMultCTMbyMat(Matrix *, Matrix *);
+extern void UTransformbyCTM(Matrix *, XPoint *, XPoint *, short);
+extern void UfTransformbyCTM(Matrix *, XfPoint *, XPoint *, short);
+extern void UPopCTM(void);
+extern void UPushCTM(void);
+extern void UTransformPoints(XPoint *, XPoint *, short, XPoint, float,
+ short);
+extern void InvTransformPoints(XPoint *, XPoint *, short, XPoint, float,
+ short);
+extern void manhattanize(XPoint *, polyptr, short, Boolean);
+extern void bboxcalc(short, short *, short *);
+extern void calcextents(genericptr *, short *, short *, short *, short *);
+extern void objinstbbox(objinstptr, XPoint *, int);
+extern void labelbbox(labelptr, XPoint *, objinstptr);
+extern void graphicbbox(graphicptr, XPoint *);
+extern void calcinstbbox(genericptr *, short *, short *, short *, short *);
+extern void calcbboxsingle(genericptr *, objinstptr, short *, short *, short *, short *);
+extern Boolean object_in_library(short, objectptr);
+extern void calcbboxinst(objinstptr);
+extern short find_object(objectptr, objectptr);
+extern void updatepagebounds(objectptr);
+extern void calcbbox(objinstptr);
+extern void calcbboxparam(objectptr, int);
+extern void singlebbox(genericptr *);
+extern void calcbboxselect(void);
+extern void calcbboxvalues(objinstptr, genericptr *);
+extern void centerview(objinstptr);
+extern void refresh(xcWidget, caddr_t, caddr_t);
+extern void zoomview(xcWidget, caddr_t, caddr_t);
+extern void UDrawSimpleLine(XPoint *, XPoint *);
+extern void UDrawLine(XPoint *, XPoint *);
+extern void UDrawCircle(XPoint *, u_char);
+extern void UDrawX(labelptr);
+extern void UDrawXDown(labelptr);
+extern int toplevelwidth(objinstptr, short *);
+extern int toplevelheight(objinstptr, short *);
+extern void extendschembbox(objinstptr, XPoint *, XPoint *);
+extern void pinadjust(short, short *, short *, short);
+extern void UDrawTextLine(labelptr, short);
+extern void UDrawTLine(labelptr);
+extern void UDrawXLine(XPoint, XPoint);
+extern void UDrawBox(XPoint, XPoint);
+extern float UDrawRescaleBox(XPoint *);
+extern void UDrawBBox(void);
+extern void strokepath(XPoint *, short, short, float);
+extern void makesplinepath(splineptr, XPoint *);
+extern void UDrawSpline(splineptr, float);
+extern void UDrawPolygon(polyptr, float);
+extern void UDrawArc(arcptr, float);
+extern void UDrawPath(pathptr, float);
+extern void UDrawObject(objinstptr, short, int, float, pushlistptr *);
+extern void TopDoLatex(void);
+
+/* from help.c: */
+
+extern void showhsb(xcWidget, caddr_t, caddr_t);
+extern void printhelppix(void);
+extern void starthelp(xcWidget, caddr_t, caddr_t);
+extern void simplescroll(xcWidget, xcWidget, XPointerMovedEvent *);
+extern void exposehelp(xcWidget, caddr_t, caddr_t);
+extern void printhelp(xcWidget);
+
+/* from keybindings.c */
+
+extern int firstbinding(xcWidget, int);
+extern Boolean ismacro(xcWidget, int);
+extern int boundfunction(xcWidget, int, short *);
+extern int string_to_func(const char *, short *);
+extern int string_to_key(const char *);
+extern char *function_binding_to_string(xcWidget, int);
+extern char *key_binding_to_string(xcWidget, int);
+extern char *compat_key_to_string(xcWidget, int);
+extern char *func_to_string(int);
+extern char *key_to_string(int);
+extern void printeditbindings(void);
+extern int add_vbinding(xcWidget, int, int, short);
+extern int add_binding(xcWidget, int, int);
+extern int add_keybinding(xcWidget, const char *, const char *);
+extern void default_keybindings(void);
+extern int remove_binding(xcWidget, int, int);
+extern void remove_keybinding(xcWidget, const char *, const char *);
+
+#ifndef TCL_WRAPPER
+extern void mode_rebinding(int, int);
+extern void mode_tempbinding(int, int);
+#endif
+
+/* from libraries.c: */
+
+extern short findhelvetica(void);
+extern void catreturn(void);
+extern int pageposition(short, int, int, int);
+extern short pagelinks(int);
+extern short *pagetotals(int, short);
+extern Boolean is_virtual(objinstptr);
+extern int is_page(objectptr);
+extern int is_library(objectptr);
+extern int NameToLibrary(char *);
+extern void tech_set_changes(TechPtr);
+extern void tech_mark_changed(TechPtr);
+extern int libfindobject(objectptr, int *);
+extern int libmoveobject(objectptr, int);
+extern void pagecat_op(int, int, int);
+extern void pageinstpos(short, short, objinstptr, int, int, int, int);
+extern objinstptr newpageinst(objectptr);
+extern void computespacing(short, int *, int *, int *, int *);
+extern void composepagelib(short);
+extern void updatepagelib(short, short);
+extern void pagecatmove(int, int);
+extern void composelib(short);
+extern short finddepend(objinstptr, objectptr **);
+extern void cathide(void);
+extern void catvirtualcopy(void);
+extern void catdelete(void);
+extern void catmove(int, int);
+extern void copycat(void);
+extern void catalog_op(int, int, int);
+extern void changecat(void);
+extern void startcatalog(xcWidget, pointertype, caddr_t);
+
+/* from menucalls.c: */
+
+extern void setgrid(xcWidget, float *);
+extern void measurestr(float, char *);
+extern void setwidth(xcWidget, float *);
+extern void changetextscale(float);
+extern void autoscale(int);
+extern float parseunits(char *);
+extern Boolean setoutputpagesize(XPoint *);
+extern void setkern(xcWidget, stringpart *);
+extern void setdscale(xcWidget, XPoint *);
+extern void setosize(xcWidget, objinstptr);
+extern void setwwidth(xcWidget, void *);
+#ifdef TCL_WRAPPER
+extern void renamepage(short);
+extern void renamelib(short);
+extern void setcolormark(int);
+extern void setallstylemarks(u_short);
+#endif
+extern labelptr gettextsize(float **);
+extern void stringparam(xcWidget, caddr_t, caddr_t);
+extern int setelementstyle(xcWidget, u_short, u_short);
+extern void togglegrid(u_short);
+extern void togglefontmark(int);
+extern void setcolorscheme(Boolean);
+extern void getgridtype(xcWidget, pointertype, caddr_t);
+extern void newlibrary(xcWidget, caddr_t, caddr_t);
+extern int createlibrary(Boolean);
+extern void makepagebutton(void);
+extern int findemptylib(void);
+extern polyptr checkforbbox(objectptr);
+#ifdef TCL_WRAPPER
+extern void setcolor(xcWidget, int);
+extern void setfontmarks(short, short);
+#endif
+extern void startparam(xcWidget, pointertype, caddr_t);
+extern void startunparam(xcWidget, pointertype, caddr_t);
+extern void setdefaultfontmarks(void);
+extern void setjustbit(xcWidget, pointertype, caddr_t);
+extern void setpinjustbit(xcWidget, pointertype, caddr_t);
+extern void setjust(xcWidget, pointertype, labelptr, short);
+extern void setvjust(xcWidget, pointertype, caddr_t);
+extern void sethjust(xcWidget, pointertype, caddr_t);
+extern void boxedit(xcWidget, pointertype, caddr_t);
+extern void locloadfont(xcWidget, char *);
+extern short findbestfont(short, short, short, short);
+extern void setfontval(xcWidget, pointertype, labelptr);
+extern void setfont(xcWidget, pointertype, caddr_t);
+extern void setfontstyle(xcWidget, pointertype, labelptr);
+extern void fontstyle(xcWidget, pointertype, caddr_t);
+extern void setfontencoding(xcWidget, pointertype, labelptr);
+extern void fontencoding(xcWidget, pointertype, caddr_t);
+extern void addtotext(xcWidget, pointertype, caddr_t);
+extern Boolean dospecial(void);
+
+/* from xtfuncs.c: */
+
+extern void makenewfontbutton(void); /* either here or menucalls.c */
+#ifndef TCL_WRAPPER
+extern void setfloat(xcWidget, float *);
+extern void autoset(xcWidget, xcWidgetList, caddr_t);
+extern void autostop(xcWidget, caddr_t, caddr_t);
+extern void togglegridstyles(xcWidget);
+extern void togglejustifs(xcWidget);
+extern void togglefontstyles(xcWidget);
+extern void toggleencodings(xcWidget);
+extern void getkern(xcWidget, caddr_t, caddr_t);
+extern void setcolor(xcWidget, pointertype, caddr_t);
+extern void setfill(xcWidget, pointertype, caddr_t);
+extern void makebbox(xcWidget, pointertype, caddr_t);
+extern void setclosure(xcWidget, pointertype, caddr_t);
+extern void setopaque(xcWidget, pointertype, caddr_t);
+extern void setline(xcWidget, pointertype, caddr_t);
+extern void changetool(xcWidget, pointertype, caddr_t);
+extern void exec_or_changetool(xcWidget, pointertype, caddr_t);
+extern void rotatetool(xcWidget, pointertype, caddr_t);
+extern void pantool(xcWidget, pointertype, caddr_t);
+extern void toggleexcl(xcWidget, menuptr, int);
+extern void highlightexcl(xcWidget, int, int);
+extern void toolcursor(int);
+extern void promptparam(xcWidget, caddr_t, caddr_t);
+extern void gettsize(xcWidget, caddr_t, caddr_t);
+extern void settsize(xcWidget, labelptr);
+extern void dotoolbar(xcWidget, caddr_t, caddr_t);
+extern void overdrawpixmap(xcWidget);
+extern buttonsave *getgeneric(xcWidget, void (*getfunction)(), void *);
+extern void getsnapspace(xcWidget, caddr_t, caddr_t);
+extern void getgridspace(xcWidget, caddr_t, caddr_t);
+extern void setscaley(xcWidget, float *);
+extern void setscalex(xcWidget, float *);
+extern void setorient(xcWidget, short *);
+extern void setpmode(xcWidget, short *);
+extern void setpagesize(xcWidget, XPoint *);
+extern void getdscale(xcWidget, caddr_t, caddr_t);
+extern void getosize(xcWidget, caddr_t, caddr_t);
+extern void getwirewidth(xcWidget, caddr_t, caddr_t);
+extern void getwwidth(xcWidget, caddr_t, caddr_t);
+extern void getfloat(xcWidget, float *, caddr_t);
+extern void setfilename(xcWidget, char **);
+extern void setpagelabel(xcWidget, char *);
+extern void makenewfontbutton(void);
+extern void newpagemenu(xcWidget, pointertype, caddr_t);
+extern void makenewencodingbutton(char *, char);
+extern void toggle(xcWidget, pointertype, Boolean *);
+extern void inversecolor(xcWidget, pointertype, caddr_t);
+extern void setgridtype(char *);
+extern void renamepage(short);
+extern void renamelib(short);
+extern void setcolormark(int);
+extern void setallstylemarks(u_short);
+extern void setnewcolor(xcWidget, caddr_t);
+extern void addnewcolor(xcWidget, caddr_t, caddr_t);
+extern void setfontmarks(short, short);
+extern void position_popup(xcWidget, xcWidget);
+extern void border_popup(xcWidget, caddr_t, caddr_t);
+extern void color_popup(xcWidget, caddr_t, caddr_t);
+extern void fill_popup(xcWidget, caddr_t, caddr_t);
+extern void param_popup(xcWidget, caddr_t, caddr_t);
+extern void addnewfont(xcWidget, caddr_t, caddr_t);
+#endif
+
+/* from netlist.c: */
+
+#ifdef TCL_WRAPPER
+extern Tcl_Obj *tclglobals(objinstptr);
+extern Tcl_Obj *tcltoplevel(objinstptr);
+void ratsnest(objinstptr);
+#endif
+
+extern void ReferencePosition(objinstptr, XPoint *, XPoint *);
+extern int NameToPinLocation(objinstptr, char *, int *, int *);
+extern Boolean RemoveFromNetlist(objectptr, genericptr);
+extern labelptr NetToLabel(int, objectptr);
+extern void NameToPosition(objinstptr, labelptr, XPoint *);
+extern XPoint *NetToPosition(int, objectptr);
+extern int getsubnet(int, objectptr);
+extern void invalidate_netlist(objectptr);
+extern void remove_netlist_element(objectptr, genericptr);
+extern int updatenets(objinstptr, Boolean);
+extern void createnets(objinstptr, Boolean);
+extern Boolean nonnetwork(polyptr);
+extern int globalmax(void);
+extern LabellistPtr geninfolist(objectptr, objinstptr, char *);
+extern void gennetlist(objinstptr);
+extern void gencalls(objectptr);
+extern void search_on_siblings(objinstptr, objinstptr, pushlistptr,
+ short, short, short, short);
+extern char *GetHierarchy(pushlistptr *, Boolean);
+extern Boolean HierNameToObject(objinstptr, char *, pushlistptr *);
+extern void resolve_devindex(objectptr, Boolean);
+extern void copy_bus(Genericlist *, Genericlist *);
+extern Genericlist *is_resolved(genericptr *, pushlistptr, objectptr *);
+extern Boolean highlightnet(objectptr, objinstptr, int, u_char);
+extern void highlightnetlist(objectptr, objinstptr, u_char);
+extern int pushnetwork(pushlistptr, objectptr);
+extern Boolean match_buses(Genericlist *, Genericlist *, int);
+extern int onsegment(XPoint *, XPoint *, XPoint *);
+extern Boolean neardist(long);
+extern Boolean nearpoint(XPoint *, XPoint *);
+extern int searchconnect(XPoint *, int, objinstptr, int);
+extern Genericlist *translateup(Genericlist *, objectptr, objectptr, objinstptr);
+extern Genericlist *addpoly(objectptr, polyptr, Genericlist *);
+extern long zsign(long, long);
+extern Boolean mergenets(objectptr, Genericlist *, Genericlist *);
+extern void removecall(objectptr, CalllistPtr);
+extern Genericlist *addpin(objectptr, objinstptr, labelptr, Genericlist *);
+extern Genericlist *addglobalpin(objectptr, objinstptr, labelptr, Genericlist *);
+extern void addcall(objectptr, objectptr, objinstptr);
+extern void addport(objectptr, Genericlist *);
+extern Boolean addportcall(objectptr, Genericlist *, Genericlist *);
+extern void makelocalpins(objectptr, CalllistPtr, char *);
+extern int porttonet(objectptr, int);
+extern stringpart *nettopin(int, objectptr, char *);
+extern Genericlist *pointtonet(objectptr, objinstptr, XPoint *);
+extern Genericlist *pintonet(objectptr, objinstptr, labelptr);
+extern Genericlist *nametonet(objectptr, objinstptr, char *);
+extern Genericlist *new_tmp_pin(objectptr, XPoint *, char *, char *, Genericlist *);
+extern Genericlist *make_tmp_pin(objectptr, objinstptr, XPoint *, Genericlist *);
+extern void resolve_devnames(objectptr);
+extern void resolve_indices(objectptr, Boolean);
+extern void clear_indices(objectptr);
+extern void unnumber(objectptr);
+extern char *parsepininfo(objinstptr, char *, int);
+extern char *defaultpininfo(objinstptr, int);
+extern char *parseinfo(objectptr, objectptr, CalllistPtr, char *, char *, Boolean,
+ Boolean);
+extern int writedevice(FILE *, char *, objectptr, CalllistPtr, char *);
+extern void writeflat(objectptr, CalllistPtr, char *, FILE *, char *);
+extern void writeglobals(objectptr, FILE *);
+extern void writehierarchy(objectptr, objinstptr, CalllistPtr, FILE *, char *);
+extern void writenet(objectptr, char *, char *);
+extern Boolean writepcb(struct Ptab **, objectptr, CalllistPtr, char *, char *);
+extern void outputpcb(struct Ptab *, FILE *);
+extern void freepcb(struct Ptab *);
+extern void freegenlist(Genericlist *);
+extern void freepolylist(PolylistPtr *);
+extern void freenetlist(objectptr);
+extern void freelabellist(LabellistPtr *);
+extern void freecalls(CalllistPtr);
+extern void freenets(objectptr);
+extern void freetemplabels(objectptr);
+extern void freeglobals(void);
+extern void destroynets(objectptr);
+extern int cleartraversed(objectptr);
+extern int checkvalid(objectptr);
+extern void clearlocalpins(objectptr);
+extern void append_included(char *);
+extern Boolean check_included(char *);
+extern void free_included(void);
+
+/* from ngspice.c: */
+extern int exit_spice(void);
+
+/* from parameter.c: */
+
+extern char *find_indirect_param(objinstptr, char *);
+extern oparamptr match_param(objectptr, char *);
+extern oparamptr match_instance_param(objinstptr, char *);
+extern oparamptr find_param(objinstptr, char *);
+extern int get_num_params(objectptr);
+extern void free_all_eparams(genericptr);
+extern void free_object_param(objectptr, oparamptr);
+extern oparamptr free_instance_param(objinstptr, oparamptr);
+extern void free_element_param(genericptr, eparamptr);
+
+extern oparamptr make_new_parameter(char *);
+extern eparamptr make_new_eparam(char *);
+
+extern char *getnumericalpkey(u_int);
+extern char *makeexprparam(objectptr, char *, char *, int);
+extern Boolean makefloatparam(objectptr, char *, float);
+extern Boolean makestringparam(objectptr, char *, stringpart *);
+extern void std_eparam(genericptr, char *);
+extern void indicateparams(genericptr);
+extern void setparammarks(genericptr);
+extern void makenumericalp(genericptr *, u_int, char *, short);
+extern void noparmstrcpy(u_char *, u_char *);
+extern void insertparam(void);
+extern void makeparam(labelptr, char *);
+extern void searchinst(objectptr, objectptr, char *);
+extern stringpart *searchparam(stringpart *);
+extern void unmakeparam(labelptr, stringpart *);
+extern void removenumericalp(genericptr *, u_int);
+extern void unparameterize(int);
+extern void parameterize(int, char *, short);
+extern genericptr findparam(objectptr, void *, u_char);
+extern Boolean paramcross(objectptr, labelptr);
+extern oparamptr parampos(objectptr, labelptr, char *, short *, short *);
+extern int opsubstitute(objectptr, objinstptr);
+extern void exprsub(genericptr);
+extern int epsubstitute(genericptr, objectptr, objinstptr, Boolean *);
+extern int psubstitute(objinstptr);
+extern Boolean has_param(genericptr);
+extern oparamptr copyparameter(oparamptr);
+extern eparamptr copyeparam(eparamptr, genericptr);
+
+extern void pwriteback(objinstptr);
+extern short paramlen(u_char *);
+extern int natstrlen(u_char *);
+extern int natstrcmp(u_char *, u_char *);
+extern void curtail(u_char *);
+extern int checklibtop(void);
+extern void removeinst(objinstptr);
+extern void removeparams(objectptr);
+extern void resolveparams(objinstptr);
+
+/* from python.c: */
+
+#ifdef HAVE_PYTHON
+extern int python_key_command(int);
+extern void init_interpreter(void);
+extern void exit_interpreter(void);
+#endif
+
+#ifdef HAVE_XPM
+extern xcWidget *pytoolbuttons(int *);
+#endif
+
+/* from rcfile.c: */
+
+extern short execcommand(short, char *);
+extern void defaultscript(void);
+extern void execscript(void);
+extern void loadrcfile(void);
+#ifndef HAVE_PYTHON
+extern short readcommand(short, FILE *);
+#endif
+
+/* from graphic.c */
+
+extern void count_graphics(objectptr, short *);
+extern void UDrawGraphic(graphicptr);
+extern Imagedata *addnewimage(char *, int, int);
+extern graphicptr new_graphic(objinstptr, char *, int, int);
+extern graphicptr gradient_field(objinstptr, int, int, int, int);
+extern void invalidate_graphics(objectptr);
+extern void freegraphic(graphicptr);
+extern short *collect_graphics(short *);
+
+/* from flate.c */
+
+#ifdef HAVE_LIBZ
+extern u_long large_deflate(u_char *, u_long, u_char *, u_long);
+extern u_long large_inflate(u_char *, u_long, u_char **, u_long);
+extern unsigned long ps_deflate (unsigned char *, unsigned long,
+ unsigned char *, unsigned long);
+extern unsigned long ps_inflate (unsigned char *, unsigned long,
+ unsigned char **, unsigned long);
+#endif
+
+/* from render.c: */
+
+extern void ghostinit(void);
+extern void send_client(Atom);
+extern void ask_for_next(void);
+extern void start_gs(void);
+extern void parse_bg(FILE *, FILE *);
+extern void bg_get_bbox(void);
+extern void backgroundbbox(int);
+extern void readbackground(FILE *);
+extern void savebackground(FILE *, char *);
+extern void register_bg(char *);
+extern void loadbackground(void);
+extern void send_to_gs(char *);
+extern int renderbackground(void);
+extern int copybackground(void);
+extern int exit_gs(void);
+extern int reset_gs(void);
+
+#ifndef TCL_WRAPPER
+extern Boolean render_client(XEvent *);
+#endif
+
+/* from schema.c: */
+
+extern objectptr NameToPageObject(char *, objinstptr *, int *);
+extern objectptr NameToObject(char *, objinstptr *, Boolean);
+extern int checkpagename(objectptr);
+extern void callwritenet(xcWidget, pointertype, caddr_t);
+extern void startconnect(xcWidget, caddr_t, caddr_t);
+extern void connectivity(xcWidget, caddr_t, caddr_t);
+extern Boolean setobjecttype(objectptr);
+extern void pinconvert(labelptr, pointertype);
+extern void dopintype(xcWidget, pointertype, caddr_t);
+extern void setsymschem(void);
+extern int findpageobj(objectptr);
+extern void collectsubschems(int);
+extern int findsubschems(int, objectptr, int, short *, Boolean);
+extern void copypinlabel(labelptr);
+extern int checkschem(objectptr, char *);
+extern int checksym(objectptr, char *);
+extern int changeotherpins(labelptr, stringpart *);
+extern void swapschem(int, int, char *);
+extern void dobeforeswap(xcWidget, caddr_t, caddr_t);
+extern void schemdisassoc(void);
+extern void startschemassoc(xcWidget, pointertype, caddr_t);
+extern Boolean schemassoc(objectptr, objectptr);
+#ifndef TCL_WRAPPER
+extern void xlib_swapschem(xcWidget, pointertype, caddr_t);
+#endif
+
+/* from selection.c: */
+
+extern void enable_selects(objectptr, short *, int);
+extern void disable_selects(objectptr, short *, int);
+extern void selectfilter(xcWidget, pointertype, caddr_t);
+extern Boolean checkselect(short);
+extern Boolean checkselect_draw(short, Boolean);
+extern void geneasydraw(short, int, objectptr, objinstptr);
+extern void gendrawselected(short *, objectptr, objinstptr);
+extern selection *genselectelement(short, u_char, objectptr, objinstptr);
+extern short *allocselect(void);
+extern void setoptionmenu(void);
+extern int test_insideness(int, int, XPoint *);
+extern Boolean pathselect(genericptr *, short, float);
+extern Boolean areaelement(genericptr *, XPoint *, Boolean, short);
+extern Boolean selectarea(objectptr, XPoint *, short);
+extern void startdesel(xcWidget, caddr_t, caddr_t);
+extern void deselect(xcWidget, caddr_t, caddr_t);
+extern void draw_normal_selected(objectptr, objinstptr);
+extern void freeselects(void);
+extern void draw_all_selected(void);
+extern void clearselects_noundo(void);
+extern void clearselects(void);
+extern void unselect_all(void);
+extern void select_connected_pins();
+extern void reset_cycles();
+extern selection *recurselect(short, u_char, pushlistptr *);
+extern short *recurse_select_element(short, u_char);
+extern void startselect(void);
+extern void trackselarea(void);
+extern void trackrescale(void);
+extern Boolean compareselection(selection *, selection *);
+extern pointselect *addcycle(genericptr *, short, u_char);
+extern void addanticycle(pathptr, splineptr, short);
+extern void copycycles(pointselect **, pointselect **);
+extern void advancecycle(genericptr *, short);
+extern void removecycle(genericptr *);
+extern void removeothercycles(pathptr, genericptr);
+extern Boolean checkforcycles(short *, int);
+extern void makerefcycle(pointselect *, short);
+
+/* from text.c: */
+
+extern Boolean hasparameter(labelptr);
+extern void joinlabels(void);
+extern void drawparamlabels(labelptr, short);
+extern stringpart *nextstringpart(stringpart *, objinstptr);
+extern stringpart *nextstringpartrecompute(stringpart *, objinstptr);
+extern stringpart *makesegment(stringpart **, stringpart *);
+extern stringpart *splitstring(int, stringpart **, objinstptr);
+extern stringpart *mergestring(stringpart *);
+extern stringpart *linkstring(objinstptr, stringpart *, Boolean);
+extern int findcurfont(int, stringpart *, objinstptr);
+extern stringpart *findtextinstring(char *, int *, stringpart *, objinstptr);
+extern stringpart *findstringpart(int, int *, stringpart *, objinstptr);
+extern void charprint(char *, stringpart *, int);
+extern void charprinttex(char *, stringpart *, int);
+extern char *stringprint(stringpart *, objinstptr);
+extern char *textprint(stringpart *, objinstptr);
+extern char *textprinttex(stringpart *, objinstptr);
+extern char *textprintsubnet(stringpart *, objinstptr, int);
+extern char *textprintnet(char *, char *, Genericlist *);
+extern int textcomp(stringpart *, char *, objinstptr);
+extern int textncomp(stringpart *, char *, objinstptr);
+extern int stringcomp(stringpart *, stringpart *);
+extern Boolean issymbolfont(int);
+extern Boolean issansfont(int);
+extern Boolean isisolatin1(int);
+extern int stringcomprelaxed(stringpart *, stringpart *, objinstptr);
+extern int stringparts(stringpart *);
+extern int stringlength(stringpart *, Boolean, objinstptr);
+extern stringpart *stringcopy(stringpart *);
+extern stringpart *stringcopyall(stringpart *, objinstptr);
+extern stringpart *stringcopyback(stringpart *, objinstptr);
+extern stringpart *deletestring(stringpart *, stringpart **, objinstptr);
+extern Genericlist *break_up_bus(labelptr, objinstptr, Genericlist *);
+extern int sub_bus_idx(labelptr, objinstptr);
+extern Boolean pin_is_bus(labelptr, objinstptr);
+extern int find_cardinal(int, labelptr, objinstptr);
+extern int find_ordinal(int, labelptr, objinstptr);
+
+extern short UDrawChar(u_char, short, short, int, int, float);
+extern void UDrawString(labelptr, int, objinstptr);
+extern void UDrawStringNoX(labelptr, int, objinstptr);
+extern void CheckMarginStop(labelptr, objinstptr, Boolean);
+extern TextExtents ULength(labelptr, objinstptr, short, XPoint *);
+extern void undrawtext(labelptr);
+extern void redrawtext(labelptr);
+extern void composefontlib(short);
+extern void fontcat_op(int, int, int);
+
+/* from xcircuit.c: */
+
+extern void Wprintf(char *, ...);
+extern void W1printf(char *, ...);
+extern void W2printf(char *, ...);
+extern void W3printf(char *, ...);
+
+extern XCWindowData *create_new_window(void);
+extern void pre_initialize(void);
+extern void post_initialize(void);
+extern void delete_window(XCWindowDataPtr);
+extern void printeventmode(void);
+extern void popupprompt(xcWidget, char *, char *, void (*function)(),
+ buttonsave *, const char *);
+extern void getproptext(xcWidget, propstruct *, caddr_t);
+extern int rgb_alloccolor(int, int, int);
+extern void addtocolorlist(xcWidget, int);
+extern int addnewcolorentry(int);
+extern int xc_getlayoutcolor(int);
+extern int query_named_color(char *);
+extern caddr_t CvtStringToPixel(XrmValuePtr, int *, XrmValuePtr, XrmValuePtr);
+extern void outputpopup(xcWidget, caddr_t, caddr_t);
+extern void docommand(void);
+extern int installowncmap(void); /* sometimes from xtgui.c */
+extern void destroypopup(xcWidget, popupstruct *, caddr_t);
+extern int xc_alloccolor(char *);
+extern void dointr(int);
+extern void DoNothing(xcWidget, caddr_t, caddr_t);
+extern u_short countchanges(char **);
+extern u_short getchanges(objectptr);
+extern void quitcheck(xcWidget, caddr_t, caddr_t);
+extern void quit(xcWidget, caddr_t);
+extern void resizetoolbar(void);
+extern void writescalevalues(char *, char *, char *);
+#ifdef TCL_WRAPPER
+extern Tcl_Obj *Tcl_NewHandleObj(void *);
+extern int Tcl_GetHandleFromObj(Tcl_Interp *, Tcl_Obj *, void **);
+#else
+extern void updatetext(xcWidget, xcWidgetList, caddr_t);
+extern void delwin(xcWidget, popupstruct *, XClientMessageEvent *);
+#endif
+
+
+extern void makecursors(void);
diff --git a/python.c b/python.c
new file mode 100644
index 0000000..bb44246
--- /dev/null
+++ b/python.c
@@ -0,0 +1,2120 @@
+/*--------------------------------------------------------------*/
+/* python.c --- Embedded python interpreter for xcircuit */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*--------------------------------------------------------------*/
+/* NOTE: These routines work only if python-2.0 is installed. */
+/* Requires library file libpython2.0.a. Hopefully */
+/* one day there will be a standard libpython${VERSION}.so */
+/* so that the whole thing doesn't have to be linked */
+/* into the xcircuit executable. . . */
+/* */
+/* Modeled after demo.c in Python2.0 source Demo/embed */
+/*--------------------------------------------------------------*/
+
+#if defined(HAVE_PYTHON) && !defined(TCL_WRAPPER)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* for usleep() */
+#include <string.h>
+
+#include <Python.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include "Xw/Xw.h"
+#include "Xw/MenuBtn.h"
+
+#ifdef HAVE_XPM
+#include <X11/xpm.h>
+#include "lib/pixmaps/q.xpm"
+#endif
+
+PyObject *xcmod;
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "menudep.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+
+#include "prototypes.h"
+
+static PyObject *xc_new(PyObject *, PyObject *);
+static PyObject *xc_set(PyObject *, PyObject *);
+static PyObject *xc_override(PyObject *, PyObject *);
+static PyObject *xc_library(PyObject *, PyObject *);
+static PyObject *xc_font(PyObject *, PyObject *);
+static PyObject *xc_color(PyObject *, PyObject *);
+static PyObject *xc_pause(PyObject *, PyObject *);
+static PyObject *xc_refresh(PyObject *, PyObject *);
+static PyObject *xc_bind(PyObject *, PyObject *);
+static PyObject *xc_unbind(PyObject *, PyObject *);
+static PyObject *xc_simplepopup(PyObject *, PyObject *);
+static PyObject *xc_popupprompt(PyObject *, PyObject *);
+static PyObject *xc_filepopup(PyObject *, PyObject *);
+static PyObject *xc_newbutton(PyObject *, PyObject *);
+static PyObject *xc_page(PyObject *, PyObject *);
+static PyObject *xc_load(PyObject *, PyObject *);
+static PyObject *xc_pan(PyObject *, PyObject *);
+static PyObject *xc_zoom(PyObject *, PyObject *);
+static PyObject *xc_getcursor();
+static PyObject *xc_getwindow();
+static PyObject *xc_reset();
+static PyObject *xc_netlist();
+#ifdef HAVE_XPM
+static PyObject *xc_newtool(PyObject *, PyObject *);
+#endif
+
+int string_to_type(const char *);
+
+/*----------------------------------------------------------------------*/
+/* External variable declarations */
+/*----------------------------------------------------------------------*/
+
+extern char _STR2[250], _STR[150];
+extern fontinfo *fonts;
+extern short fontcount;
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern short beeper;
+extern Widget menuwidgets[];
+extern Display *dpy;
+extern keybinding *keylist;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern ApplicationData appdata;
+#ifdef HAVE_XPM
+extern Widget toolbar;
+#endif
+
+/*----------------------------------------------------------------------*/
+
+short flags = -1;
+
+#define LIBOVERRIDE 1
+#define LIBLOADED 2
+#define COLOROVERRIDE 4
+#define FONTOVERRIDE 8
+#define KEYOVERRIDE 16
+
+/*----------------------------------------------------------------*/
+/* Similar to "PyRun_SimpleString()" but returns a PyObject value */
+/* rather than a status word. */
+/*----------------------------------------------------------------*/
+
+PyObject *PyRun_ObjString(char *string)
+{
+ PyObject *m, *d, *v;
+ m = PyImport_AddModule("__main__");
+ if (m == NULL) return NULL;
+ d = PyModule_GetDict(m);
+ v = PyRun_String(string, Py_file_input, d, d);
+ return v;
+}
+
+/*--------------------------------------------------------------*/
+/* Define all of the xcircuit functions available to Python */
+/* Currently this does the bare minimum of having Python do the */
+/* argument parsing; ideally, we would like to be doing more */
+/* fundamental processing here. */
+/*--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------*/
+/* Extract text from a popup and call the indicated python */
+/* function. If there is no text, function is called without */
+/* arguments. */
+/*--------------------------------------------------------------*/
+
+void pypromptvalue(Widget w, char *functionptr)
+{
+ if (strlen(_STR2) == 0)
+ sprintf(_STR, "%s()\n", functionptr);
+ else
+ sprintf(_STR, "%s('%s')\n", functionptr, _STR2);
+
+ PyRun_SimpleString(_STR);
+ refresh(NULL, NULL, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Pop up a prompt, and return the value to the indicated */
+/* python function. */
+/*--------------------------------------------------------------*/
+
+static PyObject *pypopupprompt(PyObject *self, PyObject *args,
+ const char *dofile, char *displaystr)
+{
+ const char *pfunction = NULL;
+ const char *prompt = NULL;
+ buttonsave *savebutton;
+
+ if (!PyArg_ParseTuple(args, "ss:popupprompt", &prompt, &pfunction))
+ return PyInt_FromLong(-1L);
+
+
+ savebutton = getgeneric(NULL, NULL, (void *)pfunction);
+ popupprompt(areawin->area, (char *)prompt, displaystr,
+ pypromptvalue, savebutton, dofile);
+
+ return PyInt_FromLong(0L);
+}
+
+/*--------------------------------------------------------------*/
+/* Wrappers for pypopuprompt() */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_popupprompt(PyObject *self, PyObject *args)
+{
+ return pypopupprompt(self, args, NULL, "");
+}
+
+static PyObject *xc_filepopup(PyObject *self, PyObject *args)
+{
+ return pypopupprompt(self, args, "", "");
+}
+
+static PyObject *xc_simplepopup(PyObject *self, PyObject *args)
+{
+ _STR2[0] = '\0';
+ return pypopupprompt(self, args, False, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Create objects and return a handle to that object in the */
+/* form of a Python integer Object. */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_new(PyObject *self, PyObject *args)
+{
+ const char *etype;
+ int type;
+
+ genericptr *newgen;
+ arcptr *newarc;
+ splineptr *newspline;
+ polyptr *newpoly;
+ labelptr *newlabel;
+ pathptr *newpath;
+ objinstptr *newobjinst;
+
+ if (!PyArg_ParseTuple(args, "s:newelement", &etype))
+ return NULL;
+
+ switch(type = string_to_type(etype)) {
+ case ARC:
+ NEW_ARC(newarc, topobject);
+ arcdefaults(*newarc, 0, 0);
+ newgen = (genericptr *)newarc;
+ break;
+ case SPLINE:
+ NEW_SPLINE(newspline, topobject);
+ splinedefaults(*newspline, 0, 0);
+ newgen = (genericptr *)newspline;
+ break;
+ case POLYGON:
+ NEW_POLY(newpoly, topobject);
+ polydefaults(*newpoly, 4, 0, 0);
+ newgen = (genericptr *)newpoly;
+ break;
+ case LABEL:
+ NEW_LABEL(newlabel, topobject);
+ labeldefaults(*newlabel, 0, 0, 0);
+ newgen = (genericptr *)newlabel;
+ break;
+ case PATH:
+ NEW_PATH(newpath, topobject);
+ pathdefaults(*newpath, 0, 0);
+ newgen = (genericptr *)newpath;
+ break;
+ case OBJINST:
+ NEW_OBJINST(newobjinst, topobject);
+ instancedefaults(*newobjinst, NULL, 0, 0);
+ newgen = (genericptr *)newobjinst;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "newelement() 2nd argument must be a valid element type");
+ return NULL;
+ }
+ incr_changes(topobject);
+ invalidate_netlist(topobject);
+
+ return PyInt_FromLong((long)(*newgen));
+}
+
+/*--------------------------------------------------------------*/
+/* Convert object type to a string */
+/*--------------------------------------------------------------*/
+
+char *type_to_string(int type)
+{
+ char *retstr = NULL;
+
+ switch(type) {
+ case LABEL:
+ retstr = malloc(6);
+ strcpy(retstr, "Label");
+ break;
+ case POLYGON:
+ retstr = malloc(8);
+ strcpy(retstr, "Polygon");
+ break;
+ case SPLINE:
+ retstr = malloc(12);
+ strcpy(retstr, "Bezier Curve");
+ break;
+ case OBJINST:
+ retstr = malloc(16);
+ strcpy(retstr, "Object Instance");
+ break;
+ case PATH:
+ retstr = malloc(5);
+ strcpy(retstr, "Path");
+ break;
+ case ARC:
+ retstr = malloc(4);
+ strcpy(retstr, "Arc");
+ break;
+ }
+ return retstr;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a string to an element type */
+/*--------------------------------------------------------------*/
+
+int string_to_type(const char *etype)
+{
+ if (!strcmp(etype, "Arc"))
+ return ARC;
+ else if (!strcmp(etype, "Bezier Curve"))
+ return SPLINE;
+ else if (!strcmp(etype, "Polygon"))
+ return POLYGON;
+ else if (!strcmp(etype, "Label"))
+ return LABEL;
+ else if (!strcmp(etype, "Path"))
+ return PATH;
+ else if (!strcmp(etype, "Object Instance"))
+ return OBJINST;
+ else
+ return -1;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert color index to 3-tuple and vice versa */
+/* We assume that this color exists in the color table. */
+/*--------------------------------------------------------------*/
+
+PyObject *PyIndexToRGB(int cidx)
+{
+ int i;
+ PyObject *RGBTuple;
+
+ if (cidx < 0) { /* Handle "default color" */
+ return PyString_FromString("Default");
+ }
+
+ for (i = 0; i < number_colors; i++) {
+ if (cidx == colorlist[i].color.pixel) {
+ RGBTuple = PyTuple_New(3);
+ PyTuple_SetItem(RGBTuple, 0,
+ PyInt_FromLong((long)(colorlist[i].color.red / 256)));
+ PyTuple_SetItem(RGBTuple, 1,
+ PyInt_FromLong((long)(colorlist[i].color.green / 256)));
+ PyTuple_SetItem(RGBTuple, 2,
+ PyInt_FromLong((long)(colorlist[i].color.blue / 256)));
+ return RGBTuple;
+ }
+ }
+ PyErr_SetString(PyExc_TypeError, "invalid or unknown color index");
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert color 3-tuple (RGB) or name to a color index */
+/*--------------------------------------------------------------*/
+
+int PyRGBToIndex(PyObject *cobj)
+{
+ PyObject *tobj;
+ int ccolor, r, g, b;
+
+ if (PyTuple_Check(cobj) && PyTuple_Size(cobj) == 3) { /* RGB 3-tuple */
+ tobj = PyTuple_GetItem(cobj, 0);
+ if (PyFloat_Check(tobj)) {
+ r = (int)(65535 * (float)PyFloat_AsDouble(tobj));
+ g = (int)(65535 * (float)PyFloat_AsDouble(PyTuple_GetItem(cobj, 1)));
+ b = (int)(65535 * (float)PyFloat_AsDouble(PyTuple_GetItem(cobj, 2)));
+ }
+ else if (PyInt_Check(tobj)) {
+ r = (int)(256 * PyInt_AsLong(tobj));
+ g = (int)(256 * PyInt_AsLong(PyTuple_GetItem(cobj, 1)));
+ b = (int)(256 * PyInt_AsLong(PyTuple_GetItem(cobj, 2)));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "tuple components must be integer or float");
+ return -1;
+ }
+ ccolor = rgb_alloccolor(r, g, b);
+ }
+ else if (PyString_Check(cobj)) { /* color name */
+ ccolor = xc_alloccolor(PyString_AsString(cobj));
+ }
+ else if (PyInt_Check(cobj)) { /* index (for backward compatibility) */
+ ccolor = (int)PyInt_AsLong(cobj);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be a string or 3-tuple");
+ return -1;
+ }
+
+ addnewcolorentry(ccolor);
+ return ccolor;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a Python list to a stringpart* */
+/*--------------------------------------------------------------*/
+
+stringpart *PySetStringParts(PyObject *dval)
+{
+ PyObject *lstr, *litem, *ditem, *sitem, *titem;
+ int i, j, llen;
+ stringpart *strptr, *newpart;
+ char *string;
+
+ /* If we pass a string, create a list of size 1 to hold the string. */
+ /* Otherwise, the argument must be a list. */
+
+ if (PyList_Check(dval)) {
+ lstr = dval;
+ }
+ else {
+ if (PyString_Check(dval)) {
+ lstr = PyList_New(1);
+ PyList_SetItem(lstr, 0, dval);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be a string or a list");
+ return NULL;
+ }
+ }
+
+ strptr = NULL;
+ llen = PyList_Size(lstr);
+ for (i = 0; i < llen; i++) {
+ newpart = makesegment(&strptr, NULL);
+ newpart->nextpart = NULL;
+
+ litem = PyList_GetItem(lstr, i);
+ if (PyDict_Check(litem)) {
+ if ((ditem = PyDict_GetItemString(litem, "Parameter")) != NULL) {
+ newpart->type = PARAM_START;
+ newpart->data.string = strdup(PyString_AsString(ditem));
+ }
+ else if ((ditem = PyDict_GetItemString(litem, "Font")) != NULL) {
+ newpart->type = FONT_NAME;
+ string = PyString_AsString(ditem);
+ for (j = 0; j < fontcount; j++)
+ if (!strcmp(fonts[j].psname, string)) break;
+ if (j == fontcount) loadfontfile(string);
+ newpart->data.font = j;
+ }
+ else if ((ditem = PyDict_GetItemString(litem, "Kern")) != NULL) {
+ newpart->type = KERN;
+ newpart->data.kern[0] = (int)PyInt_AsLong(PyTuple_GetItem(ditem, 0));
+ newpart->data.kern[1] = (int)PyInt_AsLong(PyTuple_GetItem(ditem, 1));
+ }
+ else if ((ditem = PyDict_GetItemString(litem, "Color")) != NULL) {
+ newpart->type = FONT_COLOR;
+ newpart->data.color = PyRGBToIndex(ditem);
+ }
+ else if ((ditem = PyDict_GetItemString(litem, "Font Scale")) != NULL) {
+ newpart->type = FONT_SCALE;
+ newpart->data.scale = (float)PyFloat_AsDouble(ditem);
+ }
+ else if ((ditem = PyDict_GetItemString(litem, "Text")) != NULL) {
+ newpart->type = TEXT_STRING;
+ newpart->data.string = strdup(PyString_AsString(ditem));
+ }
+ }
+ else if (PyString_Check(litem)) {
+ string = PyString_AsString(litem);
+ if (!strcmp(string, "End Parameter")) {
+ newpart->type = PARAM_END;
+ newpart->data.string = (u_char *)NULL;
+ }
+ else if (!strcmp(string, "Tab Stop")) {
+ newpart->type = TABSTOP;
+ }
+ else if (!strcmp(string, "Tab Forward")) {
+ newpart->type = TABFORWARD;
+ }
+ else if (!strcmp(string, "Tab Backward")) {
+ newpart->type = TABBACKWARD;
+ }
+ else if (!strcmp(string, "Return")) {
+ newpart->type = RETURN;
+ }
+ else if (!strcmp(string, "Subscript")) {
+ newpart->type = SUBSCRIPT;
+ }
+ else if (!strcmp(string, "Superscript")) {
+ newpart->type = SUPERSCRIPT;
+ }
+ else if (!strcmp(string, "Normalscript")) {
+ newpart->type = NORMALSCRIPT;
+ }
+ else if (!strcmp(string, "Underline")) {
+ newpart->type = UNDERLINE;
+ }
+ else if (!strcmp(string, "Overline")) {
+ newpart->type = OVERLINE;
+ }
+ else if (!strcmp(string, "No Line")) {
+ newpart->type = NOLINE;
+ }
+ else if (!strcmp(string, "Half Space")) {
+ newpart->type = HALFSPACE;
+ }
+ else if (!strcmp(string, "Quarter Space")) {
+ newpart->type = QTRSPACE;
+ }
+ else {
+ newpart->type = TEXT_STRING;
+ newpart->data.string = strdup(string);
+ }
+ }
+ }
+ return strptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert a stringpart* to a Python list */
+/*--------------------------------------------------------------*/
+
+PyObject *PyGetStringParts(stringpart *thisstring)
+{
+ PyObject *lstr, *sdict, *stup;
+ int i, llen;
+ stringpart *strptr;
+
+ llen = stringparts(thisstring);
+ lstr = PyList_New(llen);
+ for (strptr = thisstring, i = 0; strptr != NULL;
+ strptr = strptr->nextpart, i++) {
+ switch(strptr->type) {
+ case TEXT_STRING:
+ sdict = PyDict_New();
+ PyDict_SetItem(sdict, PyString_FromString("Text"),
+ PyString_FromString(strptr->data.string));
+ PyList_SetItem(lstr, i, sdict);
+ break;
+ case PARAM_START:
+ sdict = PyDict_New();
+ PyDict_SetItem(sdict, PyString_FromString("Parameter"),
+ PyString_FromString(strptr->data.string));
+ PyList_SetItem(lstr, i, sdict);
+ break;
+ case PARAM_END:
+ PyList_SetItem(lstr, i, PyString_FromString("End Parameter"));
+ break;
+ case FONT_NAME:
+ sdict = PyDict_New();
+ PyDict_SetItem(sdict, PyString_FromString("Font"),
+ PyString_FromString(fonts[strptr->data.font].psname));
+ PyList_SetItem(lstr, i, sdict);
+ break;
+ case FONT_SCALE:
+ sdict = PyDict_New();
+ PyDict_SetItem(sdict, PyString_FromString("Font Scale"),
+ PyFloat_FromDouble((double)strptr->data.scale));
+ PyList_SetItem(lstr, i, sdict);
+ break;
+ case KERN:
+ sdict = PyDict_New();
+ stup = PyTuple_New(2);
+ PyTuple_SetItem(stup, 0, PyInt_FromLong((long)strptr->data.kern[0]));
+ PyTuple_SetItem(stup, 1, PyInt_FromLong((long)strptr->data.kern[1]));
+ PyDict_SetItem(sdict, PyString_FromString("Kern"), stup);
+ PyList_SetItem(lstr, i, sdict);
+ break;
+ case FONT_COLOR:
+ stup = PyIndexToRGB(strptr->data.color);
+ if (stup != NULL) {
+ sdict = PyDict_New();
+ PyDict_SetItem(sdict, PyString_FromString("Color"), stup);
+ PyList_SetItem(lstr, i, sdict);
+ }
+ break;
+ case TABSTOP:
+ PyList_SetItem(lstr, i, PyString_FromString("Tab Stop"));
+ break;
+ case TABFORWARD:
+ PyList_SetItem(lstr, i, PyString_FromString("Tab Forward"));
+ break;
+ case TABBACKWARD:
+ PyList_SetItem(lstr, i, PyString_FromString("Tab Backward"));
+ break;
+ case RETURN:
+ PyList_SetItem(lstr, i, PyString_FromString("Return"));
+ break;
+ case SUBSCRIPT:
+ PyList_SetItem(lstr, i, PyString_FromString("Subscript"));
+ break;
+ case SUPERSCRIPT:
+ PyList_SetItem(lstr, i, PyString_FromString("Superscript"));
+ break;
+ case NORMALSCRIPT:
+ PyList_SetItem(lstr, i, PyString_FromString("Normalscript"));
+ break;
+ case UNDERLINE:
+ PyList_SetItem(lstr, i, PyString_FromString("Underline"));
+ break;
+ case OVERLINE:
+ PyList_SetItem(lstr, i, PyString_FromString("Overline"));
+ break;
+ case NOLINE:
+ PyList_SetItem(lstr, i, PyString_FromString("No Line"));
+ break;
+ case HALFSPACE:
+ PyList_SetItem(lstr, i, PyString_FromString("Half Space"));
+ break;
+ case QTRSPACE:
+ PyList_SetItem(lstr, i, PyString_FromString("Quarter Space"));
+ break;
+ }
+ }
+ return lstr;
+}
+
+/*--------------------------------------------------------------*/
+/* Check if the handle (integer) is an existing element */
+/*--------------------------------------------------------------*/
+
+genericptr *CheckHandle(PyObject *ehandle)
+{
+ genericptr *gelem;
+ int i, j;
+ long int eaddr;
+ objectptr thisobj;
+ Library *thislib;
+
+ eaddr = PyInt_AsLong(ehandle);
+ for (gelem = topobject->plist; gelem < topobject->plist +
+ topobject->parts; gelem++)
+ if ((long int)(*gelem) == eaddr) goto exists;
+
+ /* Okay, it isn't in topobject. Try all other pages. */
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst == NULL) continue;
+ thisobj = xobjs.pagelist[i]->pageinst->thisobject;
+ for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts; gelem++)
+ if ((long int)(*gelem) == eaddr) goto exists;
+ }
+
+ /* Still not found? Maybe in a library */
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ thislib = xobjs.userlibs + i;
+ for (j = 0; j < thislib->number; j++) {
+ thisobj = thislib->library[j];
+ for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts; gelem++)
+ if ((long int)(*gelem) == eaddr) goto exists;
+ }
+ }
+
+ /* Either in the delete list (where we don't want to go) or */
+ /* is an invalid number. */
+ return NULL;
+
+exists:
+ return gelem;
+}
+
+/*--------------------------------------------------------------*/
+/* Check if the handle (integer) is an existing page */
+/*--------------------------------------------------------------*/
+
+objectptr CheckPageHandle(PyObject *ehandle)
+{
+ int pageno;
+ long int eaddr;
+
+ eaddr = PyInt_AsLong(ehandle);
+ pageno = is_page((objectptr)eaddr);
+ if (pageno < 0) return NULL;
+ return (objectptr)eaddr;
+}
+
+/*--------------------------------------------------------------*/
+/* Form a 2-tuple from a pair of integers. */
+/*--------------------------------------------------------------*/
+
+static PyObject *make_pair(XPoint *thispoint)
+{
+ PyObject *dtup;
+
+ dtup = PyTuple_New(2);
+
+ PyTuple_SetItem(dtup, 0,
+ PyInt_FromLong((long)(thispoint->x)));
+ PyTuple_SetItem(dtup, 1,
+ PyInt_FromLong((long)(thispoint->y)));
+ return dtup;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the properties of a page (returned as a dictionary) */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getpage(PyObject *self, PyObject *args)
+{
+ Pagedata *thispage;
+ PyObject *rdict, *dlist;
+ int pageno = areawin->page + 1, i;
+
+ if (!PyArg_ParseTuple(args, "|d:getpage", &pageno))
+ return NULL;
+
+ if (pageno <= 0 || pageno > xobjs.pages) return NULL;
+ else pageno--;
+
+ thispage = xobjs.pagelist[pageno];
+
+ rdict = PyDict_New();
+
+ PyDict_SetItem(rdict, PyString_FromString("filename"),
+ PyString_FromString(thispage->filename));
+
+ PyDict_SetItem(rdict, PyString_FromString("page label"),
+ PyString_FromString(thispage->pageinst->thisobject->name));
+
+ PyDict_SetItem(rdict, PyString_FromString("output scale"),
+ PyFloat_FromDouble((double)thispage->outscale));
+
+ /* To be done: change these from internal units to "natural" units */
+
+ PyDict_SetItem(rdict, PyString_FromString("grid space"),
+ PyFloat_FromDouble((double)thispage->gridspace));
+
+ PyDict_SetItem(rdict, PyString_FromString("snap space"),
+ PyFloat_FromDouble((double)thispage->snapspace));
+
+ PyDict_SetItem(rdict, PyString_FromString("orientation"),
+ PyInt_FromLong((long)thispage->orient));
+
+ PyDict_SetItem(rdict, PyString_FromString("output mode"),
+ PyInt_FromLong((long)thispage->pmode));
+
+ PyDict_SetItem(rdict, PyString_FromString("coordinate style"),
+ PyInt_FromLong((long)thispage->coordstyle));
+
+ PyDict_SetItem(rdict, PyString_FromString("page size"),
+ make_pair(&(thispage->pagesize)));
+
+ PyDict_SetItem(rdict, PyString_FromString("drawing scale"),
+ make_pair(&(thispage->drawingscale)));
+
+ return rdict;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the properties of a library (returned as a dictionary) */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getlibrary(PyObject *self, PyObject *args)
+{
+ PyObject *rdict, *dlist;
+ const char *lname = NULL;
+ objectptr *curlib = NULL, thisobj;
+ char *errptr;
+ int i, lpage;
+ int curobjs;
+
+ if (!PyArg_ParseTuple(args, "s:getlibrary", &lname))
+ return NULL;
+
+ lpage = strtol(lname, &errptr, 10);
+ if (*lname != '\0' && *errptr == '\0' && lpage <= xobjs.numlibs &&
+ lpage > 0) { /* numerical */
+ curlib = xobjs.userlibs[lpage - 1].library;
+ }
+ else {
+ for (lpage = 0; lpage < xobjs.numlibs; lpage++) {
+ if (!strcmp(lname, xobjs.libtop[lpage + LIBRARY]->thisobject->name)) {
+ curlib = xobjs.userlibs[lpage - 1].library;
+ break;
+ }
+ else if (!strncmp(xobjs.libtop[lpage + LIBRARY]->thisobject->name,
+ "Library: ", 9)) {
+ if (!strcmp(lname, xobjs.libtop[lpage + LIBRARY]->thisobject->name + 9)) {
+ curlib = xobjs.userlibs[lpage - 1].library;
+ break;
+ }
+ }
+ }
+ }
+
+ if (curlib == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "getlibrary() 2nd argument must be a library page or name");
+ return NULL;
+ }
+ curobjs = xobjs.userlibs[lpage - 1].number;
+
+ /* Argument to getlibrary() can be a library name or library page # */
+
+ rdict = PyDict_New();
+
+ PyDict_SetItem(rdict, PyString_FromString("name"),
+ PyString_FromString(xobjs.libtop[lpage + LIBRARY]->thisobject->name));
+
+ if (curobjs > 0) {
+ dlist = PyList_New(curobjs);
+ for (i = 0; i < curobjs; i++) {
+ thisobj = *(curlib + i);
+ PyList_SetItem(dlist, i, PyString_FromString(thisobj->name));
+ }
+ PyDict_SetItem(rdict, PyString_FromString("objects"), dlist);
+ }
+ return rdict;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the properties of an object (returned as a dictionary) */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getobject(PyObject *self, PyObject *args)
+{
+ objectptr thisobj = NULL, *libobj;
+ oparamptr ops;
+ PyObject *rdict, *dlist, *tpos;
+ const char *oname;
+ int i, j, k, nparam;
+
+ if (!PyArg_ParseTuple(args, "s:getobject", &oname))
+ return NULL;
+
+ for (k = 0; k < xobjs.numlibs; k++) {
+ for (j = 0; j < xobjs.userlibs[k].number; j++) {
+ libobj = xobjs.userlibs[k].library + j;
+ if (!strcmp(oname, (*libobj)->name)) {
+ thisobj = *libobj;
+ break;
+ }
+ }
+ if (thisobj != NULL) break;
+ }
+
+ if (thisobj == NULL) { /* try the page objects */
+ for (k = 0; k < xobjs.pages; k++) {
+ if (xobjs.pagelist[k]->pageinst != NULL)
+ if (!strcmp(oname, xobjs.pagelist[k]->pageinst->thisobject->name))
+ break;
+ }
+ if (k == xobjs.pages) return NULL; /* not found */
+ }
+
+ /* return all the object's properties as a dictionary */
+
+ rdict = PyDict_New();
+
+ PyDict_SetItem(rdict, PyString_FromString("name"),
+ PyString_FromString(thisobj->name));
+ PyDict_SetItem(rdict, PyString_FromString("width"),
+ PyInt_FromLong((long)(thisobj->bbox.width)));
+ PyDict_SetItem(rdict, PyString_FromString("height"),
+ PyInt_FromLong((long)(thisobj->bbox.height)));
+ PyDict_SetItem(rdict, PyString_FromString("viewscale"),
+ PyFloat_FromDouble((double)(thisobj->viewscale)));
+
+ tpos = PyTuple_New(2);
+ PyTuple_SetItem(tpos, 0, PyInt_FromLong((long)thisobj->bbox.lowerleft.x));
+ PyTuple_SetItem(tpos, 1, PyInt_FromLong((long)thisobj->bbox.lowerleft.y));
+ PyDict_SetItem(rdict, PyString_FromString("boundingbox"), tpos);
+
+ tpos = PyTuple_New(2);
+ PyTuple_SetItem(tpos, 0, PyInt_FromLong((long)thisobj->pcorner.x));
+ PyTuple_SetItem(tpos, 1, PyInt_FromLong((long)thisobj->pcorner.y));
+ PyDict_SetItem(rdict, PyString_FromString("viewcorner"), tpos);
+
+ dlist = PyList_New(thisobj->parts);
+ for (i = 0; i < thisobj->parts; i++)
+ PyList_SetItem(dlist, i, PyInt_FromLong((long)(*(thisobj->plist + i))));
+ PyDict_SetItem(rdict, PyString_FromString("parts"), dlist);
+
+ nparam = get_num_params(thisobj);
+ if (nparam > 0) {
+ dlist = PyList_New(nparam);
+ i = 0;
+ for (ops = thisobj->params; ops != NULL; ops = ops->next) {
+ i++;
+ if (ops->type == XC_INT)
+ PyList_SetItem(dlist, i, PyInt_FromLong((long)(ops->parameter.ivalue)));
+ else if (ops->type == XC_FLOAT)
+ PyList_SetItem(dlist, i,
+ PyFloat_FromDouble((double)(ops->parameter.fvalue)));
+ else if (ops->type == XC_STRING)
+ PyList_SetItem(dlist, i, PyGetStringParts(ops->parameter.string));
+ }
+ PyDict_SetItem(rdict, PyString_FromString("parameters"), dlist);
+ }
+ return rdict;
+}
+
+/*--------------------------------------------------------------*/
+/* Reset the current page */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_reset()
+{
+ resetbutton(NULL, (pointertype)0, NULL);
+ return PyInt_FromLong(0L);
+}
+
+/*--------------------------------------------------------------*/
+/* Get a netlist */
+/*--------------------------------------------------------------*/
+
+extern PyObject *pyglobals(objectptr);
+extern PyObject *pytoplevel(objectptr);
+
+static PyObject *xc_netlist()
+{
+ PyObject *rdict = NULL;
+
+ if (updatenets(areawin->topinstance, FALSE) <= 0) {
+ PyErr_SetString(PyExc_TypeError, "Error: Check circuit for infinite recursion.");
+ return NULL;
+ }
+
+ rdict = PyDict_New();
+ PyDict_SetItem(rdict, PyString_FromString("globals"), pyglobals(topobject));
+ PyDict_SetItem(rdict, PyString_FromString("circuit"), pytoplevel(topobject));
+ return rdict;
+}
+
+/*--------------------------------------------------------------*/
+/* Load the specified file */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_load(PyObject *self, PyObject *args)
+{
+ char *filename;
+ int pageno = 0, savepage;
+
+ if (!PyArg_ParseTuple(args, "s|i:load", &filename, &pageno))
+ return PyInt_FromLong((long)areawin->page);
+
+ if (--pageno < 0) pageno = areawin->page;
+ savepage = areawin->page;
+
+ strcpy(_STR2, filename);
+ if (savepage != pageno) newpage(pageno);
+ startloadfile(-1);
+ if (savepage != pageno) newpage(savepage);
+
+ return PyString_FromString(filename);
+}
+
+/*--------------------------------------------------------------*/
+/* Go to the specified page */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_page(PyObject *self, PyObject *args)
+{
+ int pageno;
+
+ if (!PyArg_ParseTuple(args, "i:page", &pageno))
+ return PyInt_FromLong((long)areawin->page);
+
+ newpage(pageno - 1);
+ return PyInt_FromLong((long)pageno);
+}
+
+/*--------------------------------------------------------------*/
+/* Zoom */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_zoom(PyObject *self, PyObject *args)
+{
+ float factor, save;
+
+ if (!PyArg_ParseTuple(args, "f:zoom", &factor))
+ return NULL;
+
+ if (factor <= 0) {
+ PyErr_SetString(PyExc_TypeError, "Argument must be positive.");
+ return NULL;
+ }
+
+ save = areawin->zoomfactor;
+
+ if (factor < 1.0) {
+ areawin->zoomfactor = 1.0 / factor;
+ zoomout(0, 0); /* Needs to be fixed---give x, y for drag fn */
+ }
+ else {
+ areawin->zoomfactor = factor;
+ zoomin(0, 0); /* Needs to be fixed---see above */
+ }
+
+ areawin->zoomfactor = save;
+ return PyFloat_FromDouble((double)topobject->viewscale);
+}
+
+/*--------------------------------------------------------------*/
+/* Pan */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_pan(PyObject *self, PyObject *args)
+{
+ PyObject *cornerpos, *xobj, *yobj = NULL, *pval;
+ int x, y;
+ XPoint upoint, wpoint;
+
+ if (!PyArg_ParseTuple(args, "O|O:pan", &xobj, &yobj))
+ return NULL;
+
+ if (yobj == NULL) {
+ if (PyTuple_Check(xobj) && PyTuple_Size(xobj) == 2) {
+ if ((pval = PyTuple_GetItem(xobj, 0)) != NULL)
+ upoint.x = PyInt_AsLong(pval);
+ if ((pval = PyTuple_GetItem(xobj, 1)) != NULL)
+ upoint.y = PyInt_AsLong(pval);
+ }
+ else return NULL;
+ }
+ else {
+ upoint.x = PyInt_AsLong(xobj);
+ upoint.y = PyInt_AsLong(yobj);
+ }
+
+ user_to_window(upoint, &wpoint);
+ panbutton((u_int)5, wpoint.x, wpoint.y, 0.33); /* fixed fraction */
+
+ cornerpos = PyTuple_New(2);
+ PyTuple_SetItem(cornerpos, 0, PyInt_FromLong((long)areawin->pcorner.x));
+ PyTuple_SetItem(cornerpos, 1, PyInt_FromLong((long)areawin->pcorner.y));
+
+ return cornerpos;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the window size */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getwindow()
+{
+ PyObject *windowsize;
+
+ windowsize = PyTuple_New(2);
+ PyTuple_SetItem(windowsize, 0, PyInt_FromLong((long)areawin->width));
+ PyTuple_SetItem(windowsize, 1, PyInt_FromLong((long)areawin->height));
+
+ return windowsize;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the cursor position */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getcursor()
+{
+ PyObject *cursorpos;
+ XPoint newpos;
+
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+
+ cursorpos = PyTuple_New(2);
+ PyTuple_SetItem(cursorpos, 0, PyInt_FromLong((long)newpos.x));
+ PyTuple_SetItem(cursorpos, 1, PyInt_FromLong((long)newpos.y));
+
+ return cursorpos;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the properties of an element (returned as a dictionary) */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_getattr(PyObject *self, PyObject *args)
+{
+ genericptr *gelem;
+ PyObject *ehandle, *rdict, *dlist, *lstr, *sdict, *stup;
+ int i, llen;
+ char *tstr;
+ stringpart *strptr;
+
+
+ if (!PyArg_ParseTuple(args, "O:getattr", &ehandle))
+ return NULL;
+
+ /* Check to make sure that handle exists! */
+ if ((gelem = CheckHandle(ehandle)) == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "Argument must be a valid handle to an element.");
+ return NULL;
+ }
+
+ /* return the element's properties as a dictionary */
+
+ rdict = PyDict_New();
+ tstr = type_to_string((*gelem)->type);
+ if (tstr == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "Element type is unknown.");
+ return NULL;
+ }
+ PyDict_SetItem(rdict, PyString_FromString("type"),
+ PyString_FromString(tstr));
+ free(tstr);
+ lstr = PyIndexToRGB((*gelem)->color);
+ if (lstr != NULL)
+ PyDict_SetItem(rdict, PyString_FromString("color"), lstr);
+
+ switch(ELEMENTTYPE(*gelem)) {
+ case LABEL:
+ PyDict_SetItem(rdict, PyString_FromString("position"),
+ make_pair(&(TOLABEL(gelem)->position)));
+ PyDict_SetItem(rdict, PyString_FromString("rotation"),
+ PyInt_FromLong((long)TOLABEL(gelem)->rotation));
+ PyDict_SetItem(rdict, PyString_FromString("scale"),
+ PyFloat_FromDouble((double)TOLABEL(gelem)->scale));
+ PyDict_SetItem(rdict, PyString_FromString("justify"),
+ PyInt_FromLong((long)TOLABEL(gelem)->justify));
+ PyDict_SetItem(rdict, PyString_FromString("pin"),
+ PyInt_FromLong((long)TOLABEL(gelem)->pin));
+ lstr = PyGetStringParts(TOLABEL(gelem)->string);
+
+ PyDict_SetItem(rdict, PyString_FromString("string"), lstr);
+ break;
+ case POLYGON:
+ PyDict_SetItem(rdict, PyString_FromString("style"),
+ PyInt_FromLong((long)TOPOLY(gelem)->style));
+ PyDict_SetItem(rdict, PyString_FromString("linewidth"),
+ PyFloat_FromDouble((double)TOPOLY(gelem)->width));
+ dlist = PyList_New(TOPOLY(gelem)->number);
+ for (i = 0; i < TOPOLY(gelem)->number; i++) {
+ PyList_SetItem(dlist, i, make_pair(&(TOPOLY(gelem)->points[i])));
+ }
+ PyDict_SetItem(rdict, PyString_FromString("points"), dlist);
+ break;
+ case ARC:
+ PyDict_SetItem(rdict, PyString_FromString("style"),
+ PyInt_FromLong((long)TOARC(gelem)->style));
+ PyDict_SetItem(rdict, PyString_FromString("linewidth"),
+ PyFloat_FromDouble((double)TOARC(gelem)->width));
+ PyDict_SetItem(rdict, PyString_FromString("radius"),
+ PyInt_FromLong((long)TOARC(gelem)->radius));
+ PyDict_SetItem(rdict, PyString_FromString("minor axis"),
+ PyInt_FromLong((long)TOARC(gelem)->yaxis));
+ PyDict_SetItem(rdict, PyString_FromString("start angle"),
+ PyFloat_FromDouble((double)TOARC(gelem)->angle1));
+ PyDict_SetItem(rdict, PyString_FromString("end angle"),
+ PyFloat_FromDouble((double)TOARC(gelem)->angle2));
+ PyDict_SetItem(rdict, PyString_FromString("position"),
+ make_pair(&(TOARC(gelem)->position)));
+ break;
+ case SPLINE:
+ PyDict_SetItem(rdict, PyString_FromString("style"),
+ PyInt_FromLong((long)TOSPLINE(gelem)->style));
+ PyDict_SetItem(rdict, PyString_FromString("linewidth"),
+ PyFloat_FromDouble((double)TOSPLINE(gelem)->width));
+ dlist = PyList_New(4);
+ for (i = 0; i < 4; i++) {
+ PyList_SetItem(dlist, i, make_pair(&(TOSPLINE(gelem)->ctrl[i])));
+ }
+ PyDict_SetItem(rdict, PyString_FromString("control points"), dlist);
+ break;
+ case PATH:
+ PyDict_SetItem(rdict, PyString_FromString("style"),
+ PyInt_FromLong((long)TOPATH(gelem)->style));
+ PyDict_SetItem(rdict, PyString_FromString("linewidth"),
+ PyFloat_FromDouble((double)TOPATH(gelem)->width));
+ dlist = PyList_New(TOPATH(gelem)->parts);
+ for (i = 0; i < TOPATH(gelem)->parts; i++) {
+ PyList_SetItem(dlist, i,
+ PyInt_FromLong((long)(*(TOPATH(gelem)->plist + i))));
+ }
+ PyDict_SetItem(rdict, PyString_FromString("parts"), dlist);
+ break;
+ case OBJINST:
+ PyDict_SetItem(rdict, PyString_FromString("position"),
+ make_pair(&(TOOBJINST(gelem)->position)));
+ PyDict_SetItem(rdict, PyString_FromString("rotation"),
+ PyInt_FromLong((long)TOOBJINST(gelem)->rotation));
+ PyDict_SetItem(rdict, PyString_FromString("scale"),
+ PyFloat_FromDouble((double)TOOBJINST(gelem)->scale));
+ PyDict_SetItem(rdict, PyString_FromString("name"),
+ PyString_FromString(TOOBJINST(gelem)->thisobject->name));
+ break;
+ }
+ return rdict;
+}
+
+/*--------------------------------------------------------------*/
+/* Set properties of an element (supplied as a dictionary) */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_setattr(PyObject *self, PyObject *args)
+{
+ genericptr *gelem;
+ PyObject *ehandle, *attrdict, *dval, *pval, *qval;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "OO:setattr", &ehandle, &attrdict))
+ return NULL;
+
+ /* Check to make sure that handle exists! */
+ if ((gelem = CheckHandle(ehandle)) == NULL) return NULL;
+
+ /* Is the argument a dictionary? */
+ if (!PyDict_Check(attrdict)) {
+ PyErr_SetString(PyExc_TypeError,
+ "setatrr() 2nd argument must be a dictionary");
+ return NULL;
+ }
+
+ /* First, make sure no attempt is made to change the object type. */
+
+ if ((dval = PyDict_GetItemString(attrdict, "type")) != NULL) {
+ int dtype = string_to_type(PyString_AsString(dval));
+ if (dtype < 0) return NULL;
+ if (dtype != ELEMENTTYPE(*gelem)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Attempt to change the type of an object.");
+ return NULL;
+ }
+ }
+
+ /* Next, look for dictionary strings containing values which apply */
+ /* to a number of different elements (position, color, etc.) */
+
+ if ((dval = PyDict_GetItemString(attrdict, "color")) != NULL) {
+ (*gelem)->color = (short)PyRGBToIndex(dval);
+ }
+
+ if ((dval = PyDict_GetItemString(attrdict, "position")) != NULL) {
+ if (PyTuple_Check(dval) && PyTuple_Size(dval) == 2) {
+ if ((pval = PyTuple_GetItem(dval, 0)) != NULL) {
+ short xpos = (short)PyInt_AsLong(pval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case ARC:
+ TOARC(gelem)->position.x = xpos;
+ calcarc(TOARC(gelem));
+ break;
+ case LABEL:
+ TOLABEL(gelem)->position.x = xpos;
+ break;
+ case OBJINST:
+ TOOBJINST(gelem)->position.x = xpos;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set position on Spline, Polygon, or Path");
+ }
+ }
+
+ if ((pval = PyTuple_GetItem(dval, 1)) != NULL) {
+ short ypos = (short)PyInt_AsLong(pval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case ARC:
+ TOARC(gelem)->position.y = ypos;
+ calcarc(TOARC(gelem));
+ break;
+ case LABEL:
+ TOLABEL(gelem)->position.y = ypos;
+ break;
+ case OBJINST:
+ TOOBJINST(gelem)->position.y = ypos;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set position on Spline, Polygon, or Path");
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "position must be a tuple containing two integer values");
+ }
+ }
+
+ if ((dval = PyDict_GetItemString(attrdict, "style")) != NULL) {
+ short dstyle = (short)PyInt_AsLong(dval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case POLYGON:
+ TOPOLY(gelem)->style = dstyle;
+ break;
+ case PATH:
+ TOPATH(gelem)->style = dstyle;
+ break;
+ case ARC:
+ TOARC(gelem)->style = dstyle;
+ break;
+ case SPLINE:
+ TOSPLINE(gelem)->style = dstyle;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set style on an Object Instance or Label");
+ }
+ }
+
+ if ((dval = PyDict_GetItemString(attrdict, "linewidth")) != NULL) {
+ float dwidth = (float)PyFloat_AsDouble(dval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case POLYGON:
+ TOPOLY(gelem)->width = dwidth;
+ break;
+ case PATH:
+ TOPATH(gelem)->width = dwidth;
+ break;
+ case ARC:
+ TOARC(gelem)->width = dwidth;
+ break;
+ case SPLINE:
+ TOSPLINE(gelem)->width = dwidth;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set linewidth on an Object Instance or Label");
+ }
+ }
+
+ if ((dval = PyDict_GetItemString(attrdict, "scale")) != NULL) {
+ float dscale = (float)PyFloat_AsDouble(dval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case LABEL:
+ TOLABEL(gelem)->scale = dscale;
+ break;
+ case OBJINST:
+ TOOBJINST(gelem)->scale = dscale;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set scale on something not a Label or Object Instance");
+ }
+ }
+
+ if ((dval = PyDict_GetItemString(attrdict, "rotation")) != NULL) {
+ float drot = (float)PyFloat_AsDouble(dval);
+ switch(ELEMENTTYPE(*gelem)) {
+ case LABEL:
+ TOLABEL(gelem)->rotation = drot;
+ break;
+ case OBJINST:
+ TOOBJINST(gelem)->rotation = drot;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "attempt to set rotation on something not a Label or Object Instance");
+ }
+ }
+
+ /* Dictionary entries specific to certain xcircuit types */
+
+ switch(ELEMENTTYPE(*gelem)) {
+ case LABEL:
+ if ((dval = PyDict_GetItemString(attrdict, "justify")) != NULL) {
+ TOLABEL(gelem)->justify = PyInt_AsLong(dval);
+ }
+ if ((dval = PyDict_GetItemString(attrdict, "string")) != NULL) {
+ freelabel(TOLABEL(gelem)->string);
+ TOLABEL(gelem)->string = PySetStringParts(dval);
+ }
+ if ((dval = PyDict_GetItemString(attrdict, "pin")) != NULL) {
+ TOLABEL(gelem)->pin = PyInt_AsLong(dval);
+ }
+ break;
+ case ARC:
+ if ((dval = PyDict_GetItemString(attrdict, "start angle")) != NULL) {
+ TOARC(gelem)->angle1 = (float)PyFloat_AsDouble(dval);
+ }
+ if ((dval = PyDict_GetItemString(attrdict, "end angle")) != NULL) {
+ TOARC(gelem)->angle2 = (float)PyFloat_AsDouble(dval);
+ }
+ if ((dval = PyDict_GetItemString(attrdict, "radius")) != NULL) {
+ TOARC(gelem)->radius = PyInt_AsLong(dval);
+ }
+ if ((dval = PyDict_GetItemString(attrdict, "minor axis")) != NULL) {
+ TOARC(gelem)->yaxis = PyInt_AsLong(dval);
+ }
+ break;
+ case SPLINE:
+ if ((dval = PyDict_GetItemString(attrdict, "control points")) != NULL) {
+ if (PyList_Check(dval) && PyList_Size(dval) == 4) {
+ for (i = 0; i < 4; i++) {
+ pval = PyList_GetItem(dval, i);
+ if (PyTuple_Check(pval) && PyTuple_Size(pval) == 2) {
+ qval = PyTuple_GetItem(pval, 0);
+ TOSPLINE(gelem)->ctrl[i].x = (short)PyInt_AsLong(qval);
+ qval = PyTuple_GetItem(pval, 1);
+ TOSPLINE(gelem)->ctrl[i].y = (short)PyInt_AsLong(qval);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "must have a tuple of 2 values per point");
+ break;
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "must have 4 control points in a list");
+ break;
+ }
+ }
+ break;
+ case POLYGON:
+ if ((dval = PyDict_GetItemString(attrdict, "points")) != NULL) {
+ if (PyList_Check(dval)) {
+ int number = PyList_Size(dval);
+ if (TOPOLY(gelem)->number != number) {
+ TOPOLY(gelem)->points = (pointlist)realloc(
+ TOPOLY(gelem)->points, number * sizeof(XPoint));
+ TOPOLY(gelem)->number = number;
+ }
+ for (i = 0; i < number; i++) {
+ pval = PyList_GetItem(dval, i);
+ if (PyTuple_Check(pval) && PyTuple_Size(pval) == 2) {
+ qval = PyTuple_GetItem(pval, 0);
+ TOPOLY(gelem)->points[i].x = (short)PyInt_AsLong(qval);
+ qval = PyTuple_GetItem(pval, 1);
+ TOPOLY(gelem)->points[i].y = (short)PyInt_AsLong(qval);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "must have a tuple of 2 values per point");
+ break;
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "points must be in a list of tuples");
+ break;
+ }
+ }
+ break;
+ }
+
+ calcbbox(areawin->topinstance);
+ return PyInt_FromLong((long)(*gelem));
+}
+/*--------------------------------------------------------------*/
+/* Set various options through the "set" command. */
+/* "set <option> on|off" supercedes "enable|disable <option>" */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_set(PyObject *self, PyObject *args)
+{
+ const char *sarg1, *sarg2;
+ int i;
+ Boolean a = True;
+ short cpage = areawin->page;
+
+ if (!PyArg_ParseTuple(args, "ss:set", &sarg1, &sarg2))
+ return NULL;
+
+ if (!strcmp(sarg2, "On") || !strcmp(sarg2, "on") || !strcmp(sarg2, "True")
+ || !strcmp(sarg2, "true"))
+ a = False; /* has to be backwards; toggle() inverts the value! */
+
+ if (!strcmp(sarg1, "font")) {
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, sarg2)) break;
+
+ if (i == fontcount)
+ loadfontfile((char *)sarg2);
+
+ /* loadfontfile() may load multiple fonts, so we have to check again */
+ /* to see which one matches. */
+
+ for (i = 0; i < fontcount; i++) {
+ if (!strcmp(fonts[i].psname, sarg2)) {
+ areawin->psfont = i;
+ setdefaultfontmarks();
+ break;
+ }
+ }
+ }
+ else if (!strcmp(sarg1, "fontscale")) {
+ sscanf(sarg2, "%f", &areawin->textscale);
+ }
+ else if (!strcmp(sarg1, "axis") || !strcmp(sarg1, "axes")) {
+ areawin->axeson = a;
+ toggle(GridAxesButton, (pointertype)&areawin->axeson, NULL);
+ }
+ else if (!strcmp(sarg1, "grid")) {
+ areawin->gridon = a;
+ toggle(GridGridButton, (pointertype)&areawin->gridon, NULL);
+ }
+ else if (!strcmp(sarg1, "snap") || !strcmp(sarg1, "snap-to")) {
+ areawin->snapto = a;
+ toggle(SnaptoSnaptoButton, (pointertype)&areawin->snapto, NULL);
+ }
+ else if (!strcmp(sarg1, "gridspace")) {
+ sscanf(sarg2, "%f", &xobjs.pagelist[cpage]->gridspace);
+ }
+ else if (!strcmp(sarg1, "snapspace")) {
+ sscanf(sarg2, "%f", &xobjs.pagelist[cpage]->snapspace);
+ }
+ else if (!strcmp(sarg1, "pagestyle")) {
+ if (!strcmp(sarg2, "encapsulated") || !strcmp(sarg2, "eps"))
+ xobjs.pagelist[cpage]->pmode = 0;
+ else
+ xobjs.pagelist[cpage]->pmode = 1;
+ }
+ else if (!strcmp(sarg1, "boxedit")) {
+ if (!strcmp(sarg2, "rhomboid-x")) boxedit(NULL, RHOMBOIDX, NULL);
+ else if (!strcmp(sarg2, "rhomboid-y")) boxedit(NULL, RHOMBOIDY, NULL);
+ else if (!strcmp(sarg2, "rhomboid-a")) boxedit(NULL, RHOMBOIDA, NULL);
+ else if (!strcmp(sarg2, "manhattan")) boxedit(NULL, MANHATTAN, NULL);
+ else if (!strcmp(sarg2, "normal")) boxedit(NULL, NORMAL, NULL);
+ }
+ else if (!strcmp(sarg1, "linewidth")) {
+ sscanf(sarg2, "%f", &areawin->linewidth);
+ }
+ else if (!strcmp(sarg1, "colorscheme")) {
+ if (!strcmp(sarg2, "inverse"))
+ areawin->invert = False;
+ inversecolor(NULL, (pointertype)&areawin->invert, NULL);
+ }
+ else if (!strcmp(sarg1, "coordstyle")) {
+ if (!strcmp(sarg2, "cm") || !strcmp(sarg2, "centimeters")) {
+ xobjs.pagelist[cpage]->coordstyle = CM;
+ xobjs.pagelist[cpage]->pagesize.x = 595; /* A4 size */
+ xobjs.pagelist[cpage]->pagesize.y = 842;
+ togglegrid((u_short)xobjs.pagelist[cpage]->coordstyle);
+ }
+ }
+ else if (!strcmp(sarg1, "orient")) { /* "orient" or "orientation" */
+ if (!strcmp(sarg2, "landscape"))
+ xobjs.pagelist[cpage]->orient = 90; /* Landscape */
+ else
+ xobjs.pagelist[cpage]->orient = 0; /* Portrait */
+ }
+
+ else if (!strcmp(sarg1, "xschema") || !strcmp(sarg1, "schema")) {
+ /* Do nothing---retained for backward compatibility only */
+ }
+#ifdef HAVE_XPM
+ else if (!strcmp(sarg1, "toolbar")) {
+ areawin->toolbar_on = a;
+ dotoolbar(OptionsDisableToolbarButton, NULL, NULL);
+ }
+#endif
+
+ return PyString_FromString(sarg2);
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_override(PyObject *self, PyObject *args)
+{
+ const char *sarg1;
+
+ if (!PyArg_ParseTuple(args, "s:override", &sarg1))
+ return NULL;
+
+ if (!strcmp(sarg1, "library") || !strcmp(sarg1, "libraries"))
+ flags |= LIBOVERRIDE;
+ else if (!strcmp(sarg1, "color") || !strcmp(sarg1, "colors"))
+ flags |= COLOROVERRIDE;
+ else if (!strcmp(sarg1, "font") || !strcmp(sarg1, "fonts"))
+ flags |= FONTOVERRIDE;
+ if (!strcmp(sarg1, "key") || !strcmp(sarg1, "keybindings"))
+ flags |= KEYOVERRIDE;
+
+ return PyInt_FromLong(0L);
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_library(PyObject *self, PyObject *args)
+{
+ const char *libname;
+ int libnum = 1;
+
+ if (!PyArg_ParseTuple(args, "s|i:library", &libname, &libnum))
+ return NULL;
+
+ /* if loading of default libraries is not overridden, load them first */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
+ defaultscript();
+ flags |= LIBLOADED; /* Pass through a Python variable? */
+ }
+
+ if (libnum >= xobjs.numlibs || libnum < 0)
+ libnum = createlibrary(FALSE);
+ else
+ libnum += LIBRARY - 1;
+
+ strcpy(_STR, libname);
+ loadlibrary(libnum);
+ return PyInt_FromLong((long)libnum);
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_font(PyObject *self, PyObject *args)
+{
+ const char *fontname;
+
+ if (!PyArg_ParseTuple(args, "s:font", &fontname))
+ return NULL;
+
+ if (!(flags & FONTOVERRIDE)) {
+ loadfontfile("Helvetica");
+ flags |= FONTOVERRIDE;
+ }
+ loadfontfile((char *)fontname);
+ return PyString_FromString(fontname);
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_color(PyObject *self, PyObject *args)
+{
+ PyObject *pcolor;
+ int cidx;
+
+ if (!PyArg_ParseTuple(args, "O:color", &pcolor))
+ return NULL;
+
+ cidx = PyRGBToIndex(pcolor);
+ return PyIndexToRGB(cidx);
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_bind(PyObject *self, PyObject *args)
+{
+ const char *keyname = NULL;
+ const char *function = NULL;
+ PyObject *retobj;
+ int keywstate;
+
+ if (!PyArg_ParseTuple(args, "|ss:bind", &keyname, &function))
+ return NULL;
+
+ /* If we're in .xcircuitrc and we're not overriding the key */
+ /* bindings, then the first binding function should precipitate */
+ /* calling the defaults, then specify the bindings as overridden */
+ if (!(flags & KEYOVERRIDE)) {
+ default_keybindings();
+ flags |= KEYOVERRIDE;
+ }
+
+ /* No arguments? Return a dictionary of bound pairs */
+ if (!keyname) {
+ PyObject *key, *value;
+ char *keyname, *funcname;
+ keybinding *ksearch;
+
+ retobj = PyDict_New();
+ for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
+ keyname = key_to_string(ksearch->keywstate);
+ if (ksearch->value >= 0) {
+ funcname = malloc(strlen(func_to_string(ksearch->function)) + 5);
+ sprintf(funcname, "%s %d", func_to_string(ksearch->function),
+ ksearch->value);
+ }
+ else
+ funcname = func_to_string(ksearch->function);
+ key = PyString_FromString(keyname);
+ value = PyString_FromString(funcname);
+ PyDict_SetItem(retobj, key, value);
+ free(keyname);
+ if (ksearch->value >= 0) free(funcname);
+ }
+ }
+ /* One argument? Argument is a key or a function */
+ else if (!function) {
+ char *binding;
+ int func = -1;
+ keywstate = string_to_key(keyname);
+ if (keywstate == 0) { /* first argument (keyname) is function? */
+ keywstate = -1;
+ func = string_to_func(keyname, NULL);
+ }
+ if (keywstate == -1)
+ binding = function_binding_to_string(0, func);
+ else
+ binding = key_binding_to_string(0, keywstate);
+ retobj = PyString_FromString(binding);
+ free(binding);
+ }
+ else {
+ if (add_keybinding(0, keyname, function) < 0) {
+ /* Function may be a Python function, not a C function */
+ keywstate = string_to_key(keyname);
+ sprintf(_STR2, "keydict[%d] = %s\n", keywstate, function);
+ PyRun_SimpleString(_STR2);
+ }
+ retobj = PyString_FromString(keyname);
+ }
+ return retobj;
+}
+
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_unbind(PyObject *self, PyObject *args)
+{
+ const char *keyname = NULL;
+ const char *function = NULL;
+
+ if (!PyArg_ParseTuple(args, "ss:unbind", &keyname, &function))
+ return NULL;
+
+ /* If we're in .xcircuitrc and we're not overriding the key */
+ /* bindings, then the first binding function should precipitate */
+ /* calling the defaults, then specify the bindings as overridden */
+ if (!(flags & KEYOVERRIDE)) {
+ default_keybindings();
+ flags |= KEYOVERRIDE;
+ }
+
+ remove_keybinding(areawin->area, keyname, function);
+ return PyString_FromString(keyname);
+}
+
+/*--------------------------------------------------------------*/
+/* active delay */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_pause(PyObject *self, PyObject *args)
+{
+ float delay;
+
+ if (!PyArg_ParseTuple(args, "f:pause", &delay))
+ return NULL;
+
+ usleep((int)(1e6 * delay));
+ return PyInt_FromLong((int)(1e6 * delay));
+}
+
+/*--------------------------------------------------------------*/
+/* active refresh */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_refresh(PyObject *self, PyObject *args)
+{
+ XEvent event;
+
+ if (!PyArg_ParseTuple(args, ":refresh"))
+ return NULL;
+
+ refresh(NULL, NULL, NULL);
+
+ while (XCheckWindowEvent(dpy, areawin->window, ~NoEventMask, &event))
+ XtDispatchEvent(&event);
+
+ return PyInt_FromLong(0L);
+}
+
+/*--------------------------------------------------------------*/
+/* Callback procedure for Python-generated buttons */
+/*--------------------------------------------------------------*/
+
+int pybutton(Widget w, caddr_t clientdata, caddr_t calldata)
+{
+ int status;
+
+ sprintf(_STR2, "buttondict[%ld]()\n", (long int)w);
+ status = PyRun_SimpleString(_STR2);
+ refresh(NULL, NULL, NULL);
+ return status;
+}
+
+/*--------------------------------------------------------------*/
+/* Add a new button to the specified (by name) cascade menu */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_newbutton(PyObject *self, PyObject *args)
+{
+ const char *pname = NULL;
+ const char *newbname = NULL;
+ const char *pfunction = NULL;
+ int status;
+ Arg wargs[1];
+ int i, n = 0;
+ Widget newbutton, cascade, tbutton;
+
+ if (!PyArg_ParseTuple(args, "sss:newbutton", &pname, &newbname, &pfunction))
+ return NULL;
+
+ for (i = 0; i < MaxMenuWidgets; i++) {
+ tbutton = menuwidgets[i];
+ cascade = XtParent(tbutton);
+ if (!strcmp(XtName(cascade), pname)) break;
+ }
+ if (i == MaxMenuWidgets) {
+ Wprintf("Cannot find specified menu.");
+ return NULL;
+ }
+
+ XtnSetArg(XtNfont, appdata.xcfont);
+ newbutton = XtCreateWidget(newbname, XwmenubuttonWidgetClass,
+ cascade, wargs, n);
+
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)pybutton, newbutton);
+ XtManageChild(newbutton);
+
+ sprintf(_STR2, "buttondict[%ld] = %s\n", (long int)newbutton, pfunction);
+ status = PyRun_SimpleString(_STR2);
+ return PyInt_FromLong((long)status);
+}
+
+#ifdef HAVE_XPM
+
+/*--------------------------------------------------------------*/
+/* Callback procedure for Python-generated toolbar tool */
+/*--------------------------------------------------------------*/
+
+int pytool(Widget w, caddr_t clientdata, caddr_t calldata)
+{
+ int status;
+
+ sprintf(_STR2, "tooldict[%ld]()\n", (long int)w);
+ status = PyRun_SimpleString(_STR2);
+ refresh(NULL, NULL, NULL);
+ return status;
+}
+
+/*--------------------------------------------------------------*/
+/* Add a new tool to the toolbar */
+/*--------------------------------------------------------------*/
+
+static PyObject *xc_newtool(PyObject *self, PyObject *args)
+{
+ const char *thint = NULL;
+ const char *pixfile = NULL;
+ const char *newtname = NULL;
+ const char *pfunction = NULL;
+ int status;
+ Arg wargs[8];
+ int i, n = 0;
+ Widget newtool, cascade, tbutton;
+ XImage *iret;
+ XpmAttributes attr;
+
+ attr.valuemask = XpmSize | XpmCloseness;
+ attr.closeness = 65536;
+
+ if (!PyArg_ParseTuple(args, "sss|s:newtool", &newtname, &pfunction, &pixfile,
+ &thint))
+ return NULL;
+
+ if (XpmReadFileToImage(dpy, (char *)pixfile, &iret, NULL, &attr) < 0) {
+ Wprintf("Cannot find or open pixmap file \'%s\'", pixfile);
+ XpmCreateImageFromData(dpy, q_xpm, &iret, NULL, &attr);
+ }
+
+ XtnSetArg(XtNlabelType, XwIMAGE);
+ XtnSetArg(XtNlabelImage, iret);
+ XtnSetArg(XtNwidth, attr.width + 4);
+ XtnSetArg(XtNheight, attr.height + 4);
+ XtnSetArg(XtNborderWidth, TBBORDER);
+ XtnSetArg(XtNnoPad, True);
+ if (thint != NULL) {
+ XtnSetArg(XtNhint, thint);
+ XtnSetArg(XtNhintProc, Wprintf);
+ }
+ newtool = XtCreateWidget(newtname, XwmenubuttonWidgetClass, toolbar, wargs, n);
+
+ XtAddCallback (newtool, XtNselect, (XtCallbackProc)pybutton, newtool);
+ XtManageChild(newtool);
+
+ sprintf(_STR2, "tooldict[%ld] = %s\n", (long int)newtool, pfunction);
+ status = PyRun_SimpleString(_STR2);
+ return PyInt_FromLong((long)status);
+}
+
+/*------------------------------------------------------------------*/
+/* Return a list of the widgets in tooldict */
+/* (memory for list is allocated here and must be free'd elsewhere) */
+/*------------------------------------------------------------------*/
+
+Widget *pytoolbuttons(int *num_tools)
+{
+ Widget *ptools;
+ PyObject *rval;
+ int i;
+
+ if (xcmod == NULL) {
+ *num_tools = 0;
+ return NULL;
+ }
+ rval = PyRun_ObjString("len(tooldict)");
+ if (!rval) {
+ PyErr_Clear();
+ return NULL;
+ }
+ *num_tools = (int)PyInt_AsLong(rval);
+ Py_DECREF(rval);
+ /* fprintf(stderr, "num_tools = %d\n", *num_tools); */
+
+ if (*num_tools <= 0) return NULL;
+
+ ptools = (Widget *)malloc(*num_tools * sizeof(Widget));
+
+ for (i = 0; i < *num_tools; i++) {
+ sprintf(_STR2, "tooldict[%d]", i);
+ rval = PyRun_ObjString(_STR2);
+ if (!rval) {
+ PyErr_Clear();
+ return NULL;
+ }
+ ptools[i] = (Widget)PyInt_AsLong(rval);
+ Py_DECREF(rval);
+ }
+ return ptools;
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+/* Execute a python command from the key-function pair dictionary */
+/*----------------------------------------------------------------*/
+
+int python_key_command(int keystate)
+{
+ PyObject *rval;
+ int status;
+ sprintf(_STR2, "keydict[%d]\n", keystate);
+ rval = PyRun_ObjString(_STR2);
+ if (!rval) {
+ PyErr_Clear();
+ return -1;
+ }
+ Py_DECREF(rval);
+
+ sprintf(_STR2, "keydict[%d]()\n", keystate);
+ PyRun_SimpleString(_STR2);
+ refresh(NULL, NULL, NULL);
+ return 0;
+}
+
+/*--------------------------------------------------------------*/
+/* Declaration of the xcircuit Python functions */
+/*--------------------------------------------------------------*/
+
+static PyMethodDef xc_methods[] = {
+ {"set", xc_set, 1},
+ {"override", xc_override, 1},
+ {"library", xc_library, 1},
+ {"font", xc_font, 1},
+ {"color", xc_color, 1},
+ {"newelement", xc_new, 1},
+ {"getpage", xc_getpage, 1},
+ {"getlibrary", xc_getlibrary, 1},
+ {"getobject", xc_getobject, 1},
+ {"getattr", xc_getattr, 1},
+ {"setattr", xc_setattr, 1},
+ {"refresh", xc_refresh, 1},
+ {"pause", xc_pause, 1},
+ {"bind", xc_bind, 1},
+ {"unbind", xc_unbind, 1},
+ {"getcursor", xc_getcursor, 1},
+ {"getwindow", xc_getwindow, 1},
+ {"zoom", xc_zoom, 1},
+ {"pan", xc_pan, 1},
+ {"popupprompt", xc_popupprompt, 1},
+ {"filepopup", xc_filepopup, 1},
+ {"simplepopup", xc_simplepopup, 1},
+ {"newbutton", xc_newbutton, 1},
+ {"reset", xc_reset, 1},
+ {"page", xc_page, 1},
+ {"load", xc_load, 1},
+#ifdef HAVE_XPM
+ {"newtool", xc_newtool, 1},
+#endif
+ {"netlist", xc_netlist, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+/*--------------------------------------------------------------*/
+/* Initialize Python interpreter and load all xcircuit methods */
+/*--------------------------------------------------------------*/
+void init_interpreter()
+{
+ Py_SetProgramName("XCircuit");
+ Py_Initialize();
+ PyImport_AddModule("xc");
+ xcmod = Py_InitModule("xc", xc_methods);
+ PyRun_SimpleString("from xc import *\n");
+ PyRun_SimpleString("keydict = {}\n"); /* initialize key/function pairs */
+ PyRun_SimpleString("buttondict = {}\n"); /* initialize button/function pairs */
+ PyRun_SimpleString("tooldict = {}\n"); /* initialize tool/function pairs */
+ sprintf(_STR, "xc_version = %2.1f\n", PROG_VERSION);
+ PyRun_SimpleString(_STR);
+}
+
+/*--------------------------------------------------------------*/
+/* Exit the Python interpreter */
+/*--------------------------------------------------------------*/
+
+void exit_interpreter()
+{
+ Py_Exit(0);
+}
+
+/*--------------------------------------------------------------*/
+/* Replace the functions of the simple rcfile.c interpreter. */
+/*--------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Execute a single command from a script or from the command line */
+/*----------------------------------------------------------------------*/
+
+short execcommand(short pflags, char *cmdptr)
+{
+ flags = pflags;
+ PyRun_SimpleString(cmdptr);
+ refresh(NULL, NULL, NULL);
+ return flags;
+}
+
+/*----------------------------------------------------------------------*/
+/* Load the default script (like execscript() but don't allow recursive */
+/* loading of the startup script) */
+/*----------------------------------------------------------------------*/
+
+void defaultscript()
+{
+ FILE *fd;
+ char *tmp_s = getenv((const char *)"XCIRCUIT_SRC_DIR");
+
+ flags = LIBOVERRIDE | LIBLOADED | FONTOVERRIDE;
+
+ if (!tmp_s) tmp_s = SCRIPTS_DIR;
+ sprintf(_STR2, "%s/%s", tmp_s, STARTUP_FILE);
+
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ sprintf(_STR2, "%s/%s", SCRIPTS_DIR, STARTUP_FILE);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ Wprintf("Failed to open startup script \"%s\"\n", STARTUP_FILE);
+ return;
+ }
+ }
+ PyRun_SimpleFile(fd, _STR2);
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute a script */
+/*----------------------------------------------------------------------*/
+
+void execscript()
+{
+ FILE *fd;
+
+ flags = 0;
+
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) != NULL) {
+ PyRun_SimpleFile(fd, _STR2);
+ refresh(NULL, NULL, NULL);
+ }
+ else {
+ Wprintf("Failed to open script file \"%s\"\n", _STR2);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute the .xcircuitrc startup script */
+/*----------------------------------------------------------------------*/
+
+void loadrcfile()
+{
+ char *userdir = getenv((const char *)"HOME");
+ FILE *fd;
+ short i;
+
+ /* Initialize flags */
+
+ flags = 0;
+
+ sprintf(_STR2, "%s", USER_RC_FILE); /* Name imported from Makefile */
+
+ /* try first in current directory, then look in user's home directory */
+
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ if (userdir != NULL) {
+ sprintf(_STR2, "%s/%s", userdir, USER_RC_FILE);
+ fd = fopen(_STR2, "r");
+ }
+ }
+ if (fd != NULL)
+ PyRun_SimpleFile(fd, _STR2);
+
+ /* Add the default font if not loaded already */
+
+ if (!(flags & FONTOVERRIDE)) {
+ loadfontfile("Helvetica");
+ if (areawin->psfont == -1)
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, "Helvetica")) {
+ areawin->psfont = i;
+ break;
+ }
+ }
+
+ if (areawin->psfont == -1) areawin->psfont = 0;
+
+ setdefaultfontmarks();
+
+ /* arrange the loaded libraries */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED)))
+ defaultscript();
+
+ /* Add the default colors */
+
+ if (!(flags & COLOROVERRIDE)) {
+ addnewcolorentry(xc_alloccolor("Gray40"));
+ addnewcolorentry(xc_alloccolor("Gray60"));
+ addnewcolorentry(xc_alloccolor("Gray80"));
+ addnewcolorentry(xc_alloccolor("Gray90"));
+ addnewcolorentry(xc_alloccolor("Red"));
+ addnewcolorentry(xc_alloccolor("Blue"));
+ addnewcolorentry(xc_alloccolor("Green2"));
+ addnewcolorentry(xc_alloccolor("Yellow"));
+ addnewcolorentry(xc_alloccolor("Purple"));
+ addnewcolorentry(xc_alloccolor("SteelBlue2"));
+ addnewcolorentry(xc_alloccolor("Red3"));
+ addnewcolorentry(xc_alloccolor("Tan"));
+ addnewcolorentry(xc_alloccolor("Brown"));
+ }
+
+ /* These colors must be enabled whether or not colors are overridden, */
+ /* because they are needed by the schematic capture system. */
+
+ addnewcolorentry(xc_getlayoutcolor(LOCALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(GLOBALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(INFOLABELCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(RATSNESTCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(BBOXCOLOR));
+
+ if (!(flags & KEYOVERRIDE))
+ default_keybindings();
+}
+
+#endif
+/* #endif HAVE_PYTHON and !TCL_WRAPPER */
+/*--------------------------------------------------------------*/
diff --git a/rcfile.c b/rcfile.c
new file mode 100644
index 0000000..e97c2dd
--- /dev/null
+++ b/rcfile.c
@@ -0,0 +1,521 @@
+/*-------------------------------------------------------------------------*/
+/* rcfile.c --- Load initialization variables from the .xcircuitrc file */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/* This file is made obsolete by the Python interpreter, if compiled in */
+#if !defined(HAVE_PYTHON) && !defined(TCL_WRAPPER)
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 9/9/96 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h> /* for usleep() */
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "menudep.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* External variable declarations */
+/*----------------------------------------------------------------------*/
+
+extern char _STR2[250], _STR[150];
+extern fontinfo *fonts;
+extern short fontcount;
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern short beeper;
+extern int *appcolors;
+extern Widget menuwidgets[];
+extern Display *dpy;
+
+/*----------------------------------------------------------------------*/
+
+#define LIBOVERRIDE 1
+#define LIBLOADED 2
+#define COLOROVERRIDE 4
+#define FONTOVERRIDE 8
+#define KEYOVERRIDE 16
+
+/*----------------------------------------------------------------------*/
+/* Execute a single command from a script or from the command line */
+/*----------------------------------------------------------------------*/
+
+short execcommand(short pflags, char *cmdptr)
+{
+ short flags = pflags;
+ Boolean a;
+ char type[50], value[50];
+ char *argptr;
+ short cpage = areawin->page;
+
+ /* Note: areawin->page is set to 0 before loading the .xcircuitrc */
+ /*file, so .xcircuitrc file commands act on page 0 only; from the */
+ /* command line they act on the current page. */
+
+ for(argptr = cmdptr; isspace(*argptr); argptr++)
+ if (*argptr == '\0') return flags;
+ cmdptr = argptr;
+
+ for(argptr = cmdptr; (!isspace(*argptr)) && (*argptr != '\0'); argptr++);
+ *argptr++ = '\0';
+ while(isspace(*argptr)) argptr++;
+
+ /* very liberal about comment line characters */
+
+ if (*cmdptr == '#' || *cmdptr == '%' || *cmdptr == ';');
+
+ /* startup configuration: enables/disables */
+
+ else if (!(a = strcmp(cmdptr, "enable")) || !strcmp(cmdptr, "disable")) {
+ sscanf(argptr, "%149s", _STR);
+ if (!strncmp(_STR, "grid", 4)) {
+ areawin->gridon = a ? True : False;
+ toggle(GridGridButton, (pointertype)&areawin->gridon, NULL);
+ }
+ else if (!strncmp(_STR, "snap", 4) || !strncmp(_STR, "snap-to", 4)) {
+ areawin->snapto = a ? True : False;
+ toggle(SnaptoSnaptoButton, (pointertype)&areawin->snapto, NULL);
+ }
+ else if (!strcmp(_STR, "axis") || !strcmp(_STR, "axes")) {
+ areawin->axeson = a ? True : False;
+ toggle(GridAxesButton, (pointertype)&areawin->axeson, NULL);
+ }
+ else if (!strcmp(_STR, "xschema") || !strcmp(_STR, "schema")) {
+ /* Do nothing---retained for backward compatibility only */
+ }
+#ifdef HAVE_XPM
+ else if (!strcmp(_STR, "toolbar")) {
+ areawin->toolbar_on = a ? True : False;
+ dotoolbar(OptionsDisableToolbarButton, NULL, NULL);
+ }
+#endif
+ }
+
+ /* startup configuration: overrides */
+
+ else if (!strcmp(cmdptr, "override")) {
+
+ /* "default" is now considered redundant */
+ if (!strncmp(argptr, "default", 7)) {
+ argptr += 7;
+ while (isspace(*argptr) && (*argptr != '\0')) argptr++;
+ if (*argptr == '\0') return flags; /* bad syntax */
+ }
+
+ sscanf(argptr, "%49s", value);
+ if (!strcmp(value, "library") || !strcmp(value, "libraries")) {
+ flags |= LIBOVERRIDE;
+ }
+ else if (!strcmp(value, "color") || !strcmp(value, "colors")) {
+ flags |= COLOROVERRIDE;
+ }
+ else if (!strcmp(value, "font") || !strcmp(value, "fonts")) {
+ flags |= FONTOVERRIDE;
+ }
+ else if (!strcmp(value, "key") || !strcmp(value, "keybindings")) {
+ flags |= KEYOVERRIDE;
+ }
+ }
+
+ /* load extra files */
+
+ else if (!strcmp(cmdptr, "load")) {
+ int pageno = areawin->page;
+ int savepage = areawin->page;
+ if (sscanf(argptr, "%249s %d", _STR, &pageno) >= 1) {
+ if (pageno != savepage) newpage(pageno);
+ startloadfile(-1);
+ if (pageno != savepage) newpage(savepage);
+ }
+ else
+ Wprintf("Error in load statement.");
+ }
+
+ /* load builtin libraries */
+
+ else if (!strcmp(cmdptr, "library")) {
+ int libnum;
+
+ /* if loading of default libraries is not overridden, load them first */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
+ defaultscript();
+ flags |= LIBLOADED;
+ }
+
+ /* Optional third argument is the library number */
+ if (sscanf(argptr, "%149s %d", _STR, &libnum) == 1)
+ libnum = LIBRARY;
+ else {
+ if (libnum >= xobjs.numlibs)
+ libnum = createlibrary(FALSE);
+ else
+ libnum += LIBRARY - 1;
+ }
+ loadlibrary(libnum);
+ }
+
+ /* load extra fonts */
+
+ else if (!strncmp(cmdptr, "font", 4)) {
+
+ /* if default font is not overridden, load it first */
+
+ if (!(flags & FONTOVERRIDE)) {
+ loadfontfile("Helvetica");
+ flags |= FONTOVERRIDE;
+ }
+ if (sscanf(argptr, "%149s", _STR) == 1)
+ loadfontfile(_STR);
+ else
+ Wprintf("Error in font statement.");
+ }
+
+ /* load extra colors */
+
+ else if (!strcmp(cmdptr, "color")) {
+ sscanf(argptr, "%249s", _STR2);
+ addnewcolorentry(xc_alloccolor(_STR2));
+ }
+
+ /* create macro */
+
+ else if (!strcmp(cmdptr, "bind")) {
+ int args;
+ char *sptr;
+
+ if (!(flags & KEYOVERRIDE)) {
+ default_keybindings();
+ flags |= KEYOVERRIDE;
+ }
+ if ((args = sscanf(argptr, "%149s", _STR)) == 1) {
+ char *binding;
+ int func = -1, keywstate;
+ keywstate = string_to_key(_STR);
+ if (keywstate == 0) { /* Perhaps 1st arg is a function? */
+ keywstate = -1;
+ func = string_to_func(_STR, NULL);
+ }
+ if (keywstate == -1)
+ binding = function_binding_to_string(0, func);
+ else
+ binding = key_binding_to_string(0, keywstate);
+ Wprintf("%s", binding);
+ free(binding);
+ }
+ else if (args == 0)
+ Wprintf("See help window for list of bindings");
+ else {
+ /* Use entire line after 1st argument, so multiple words are allowed */
+ sptr = argptr + strlen(_STR);
+ if (add_keybinding(areawin->area, _STR, sptr) < 0) {
+ Wprintf("Function \"%s\" is not known\n", sptr);
+ }
+ }
+ }
+
+ /* destroy macro */
+
+ else if (!strcmp(cmdptr, "unbind")) {
+ if (!(flags & KEYOVERRIDE)) {
+ default_keybindings();
+ flags |= KEYOVERRIDE;
+ }
+ sscanf(argptr, "%149s %249s", _STR, _STR2);
+ remove_keybinding(areawin->area, _STR, _STR2);
+ }
+
+ /* beep mode */
+
+ else if (!strcmp(cmdptr, "beep")) {
+ sscanf(argptr, "%49s", type);
+ beeper = (!strcmp(type, "off")) ? 0 : 1;
+ }
+
+ /* active delay */
+
+ else if (!strcmp(cmdptr, "pause")) {
+ float dval = 0;
+ sscanf(argptr, "%f", &dval);
+ usleep((int)(1e6 * dval));
+ }
+
+ /* active refresh */
+
+ else if (!strcmp(cmdptr, "refresh")) {
+ XEvent event;
+
+ refresh(NULL, NULL, NULL);
+
+ while(XCheckWindowEvent(dpy, areawin->window, ~NoEventMask, &event))
+ XtDispatchEvent(&event);
+ }
+
+ /* set variables */
+
+ else if (!strcmp(cmdptr, "set") || !strcmp(cmdptr, "select")) {
+
+ /* "default" is now considered redundant, but accepted for */
+ /* backward compatibility. */
+
+ if (!strncmp(argptr, "default", 7)) {
+ argptr += 7;
+ while (isspace(*argptr) && (*argptr != '\0')) argptr++;
+ if (*argptr == '\0') return flags; /* bad syntax */
+ }
+
+ if (!strncmp(argptr, "font", 4)) {
+ short i;
+ if (strstr(argptr + 4, "scale")) {
+ sscanf(argptr + 4, "%*s %f", &areawin->textscale);
+ }
+ else {
+ sscanf(argptr, "%*s %49s", value);
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, value)) break;
+
+ if (i == fontcount) {
+ loadfontfile(value);
+ }
+ areawin->psfont = i;
+ setdefaultfontmarks();
+ }
+ }
+ else if (!strncmp(argptr, "boxedit", 7)) {
+ sscanf(argptr, "%*s %49s", value);
+ if (!strcmp(value, "rhomboid-x")) boxedit(NULL, RHOMBOIDX, NULL);
+ else if (!strcmp(value, "rhomboid-y")) boxedit(NULL, RHOMBOIDY, NULL);
+ else if (!strcmp(value, "rhomboid-a")) boxedit(NULL, RHOMBOIDA, NULL);
+ else if (!strcmp(value, "manhattan")) boxedit(NULL, MANHATTAN, NULL);
+ else if (!strcmp(value, "normal")) boxedit(NULL, NORMAL, NULL);
+ }
+ else if (!strncmp(argptr, "line", 4)) {
+ if (strstr(argptr + 4, "width")) {
+ sscanf(argptr + 4, "%*s %f", &areawin->linewidth);
+ }
+ }
+ else if (!strncmp(argptr, "colorscheme", 11)) {
+ sscanf(argptr, "%*s %49s", value);
+ if (!strcmp(value, "inverse") || !strcmp(value, "2"))
+ areawin->invert = False;
+ inversecolor(NULL, (pointertype)&areawin->invert, NULL);
+ }
+ else if (!strncmp(argptr, "coordstyle", 10)) {
+ sscanf(argptr, "%*s %49s", value);
+ if (!strcmp(value, "cm") || !strcmp(value, "centimeters")) {
+ xobjs.pagelist[cpage]->coordstyle = CM;
+ xobjs.pagelist[cpage]->pagesize.x = 595; /* A4 size */
+ xobjs.pagelist[cpage]->pagesize.y = 842;
+ togglegrid((u_short)xobjs.pagelist[cpage]->coordstyle);
+ }
+ }
+ else if (!strncmp(argptr, "orient", 6)) { /* "orient" or "orientation" */
+ sscanf(argptr, "%*s %49s", value);
+ if (!strncmp(value, "land", 4))
+ xobjs.pagelist[cpage]->orient = 90; /* Landscape */
+ else
+ xobjs.pagelist[cpage]->orient = 0; /* Portrait */
+ }
+ else if (!strncmp(argptr, "page", 4)) {
+ if (strstr(argptr + 4, "type") || strstr(argptr + 4, "style")) {
+ sscanf(argptr + 4, "%*s %49s", value);
+ if (!strcmp(value, "encapsulated") || !strcmp(value, "eps"))
+ xobjs.pagelist[cpage]->pmode = 0;
+ else
+ xobjs.pagelist[cpage]->pmode = 1;
+ }
+ }
+ else if (!strncmp(argptr, "grid", 4)) {
+ if (strstr(argptr + 4, "space")) {
+ sscanf(argptr + 4, "%*s %f", &xobjs.pagelist[cpage]->gridspace);
+ }
+ }
+ else if (!strncmp(argptr, "snap", 4)) {
+ if (strstr(argptr + 4, "space")) {
+ sscanf(argptr + 4, "%*s %f", &xobjs.pagelist[cpage]->snapspace);
+ }
+ }
+ }
+ return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+#define TEMPLEN 128
+
+short readcommand(short mode, FILE *fd)
+{
+ char *temp, *tmpptr, *endptr;
+ short templen = TEMPLEN, tempmax = TEMPLEN;
+ short flags = (mode == 0) ? 0 : LIBOVERRIDE | LIBLOADED | FONTOVERRIDE;
+
+ temp = (char *)malloc(templen);
+ tmpptr = temp;
+
+ while (fgets(tmpptr, templen, fd) != NULL) {
+ endptr = tmpptr;
+ while ((*endptr != '\0') && (*endptr != '\\')) {
+ if (*endptr == '\n') {
+ endptr = temp;
+ templen = tempmax;
+ flags = execcommand(flags, temp);
+ break;
+ }
+ endptr++;
+ templen--;
+ }
+ if (templen == 0) {
+ templen = (int)(endptr - temp);
+ tempmax += TEMPLEN;
+ temp = (char *)realloc(temp, tempmax);
+ tmpptr = temp + templen;
+ templen = TEMPLEN;
+ }
+ else
+ tmpptr = endptr;
+ }
+
+ free(temp);
+ fclose(fd);
+ return flags;
+}
+
+/*----------------------------------------------------------------------*/
+/* Load the default script (like execscript() but don't allow recursive */
+/* loading of the startup script) */
+/*----------------------------------------------------------------------*/
+
+void defaultscript()
+{
+ FILE *fd;
+ char *tmp_s = getenv((const char *)"XCIRCUIT_SRC_DIR");
+
+ if (!tmp_s) tmp_s = SCRIPTS_DIR;
+ sprintf(_STR2, "%s/%s", tmp_s, STARTUP_FILE);
+
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ sprintf(_STR2, "%s/%s", SCRIPTS_DIR, STARTUP_FILE);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ Wprintf("Failed to open startup script \"%s\"\n", STARTUP_FILE);
+ return;
+ }
+ }
+ readcommand(1, fd);
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute a script */
+/*----------------------------------------------------------------------*/
+
+void execscript()
+{
+ FILE *fd;
+
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) != NULL) readcommand(0, fd);
+ else {
+ Wprintf("Failed to open script file \"%s\"\n", _STR2);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute the .xcircuitrc startup script */
+/*----------------------------------------------------------------------*/
+
+void loadrcfile()
+{
+ char *userdir = getenv((const char *)"HOME");
+ FILE *fd;
+ short i, flags = 0;
+
+ sprintf(_STR2, "%s", USER_RC_FILE); /* Name imported from Makefile */
+
+ /* try first in current directory, then look in user's home directory */
+
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ if (userdir != NULL) {
+ sprintf(_STR2, "%s/%s", userdir, USER_RC_FILE);
+ fd = fopen(_STR2, "r");
+ }
+ }
+ if (fd != NULL) flags = readcommand(0, fd);
+
+ /* Add the default font if not loaded already */
+
+ if (!(flags & FONTOVERRIDE)) {
+ loadfontfile("Helvetica");
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, "Helvetica")) areawin->psfont = i;
+ }
+ setdefaultfontmarks();
+
+ /* arrange the loaded libraries */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED)))
+ defaultscript();
+
+ /* Add the default colors */
+
+ if (!(flags & COLOROVERRIDE)) {
+ addnewcolorentry(xc_alloccolor("Gray40"));
+ addnewcolorentry(xc_alloccolor("Gray60"));
+ addnewcolorentry(xc_alloccolor("Gray80"));
+ addnewcolorentry(xc_alloccolor("Gray90"));
+ addnewcolorentry(xc_alloccolor("Red"));
+ addnewcolorentry(xc_alloccolor("Blue"));
+ addnewcolorentry(xc_alloccolor("Green2"));
+ addnewcolorentry(xc_alloccolor("Yellow"));
+ addnewcolorentry(xc_alloccolor("Purple"));
+ addnewcolorentry(xc_alloccolor("SteelBlue2"));
+ addnewcolorentry(xc_alloccolor("Red3"));
+ addnewcolorentry(xc_alloccolor("Tan"));
+ addnewcolorentry(xc_alloccolor("Brown"));
+ }
+
+ /* These colors must be enabled whether or not colors are overridden, */
+ /* because they are needed by the schematic capture system. */
+
+ addnewcolorentry(xc_getlayoutcolor(LOCALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(GLOBALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(INFOLABELCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(RATSNESTCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(BBOXCOLOR));
+
+
+ /* Add the default key bindings */
+
+ if (!(flags & KEYOVERRIDE))
+ default_keybindings();
+}
+
+#endif
+/* #endif for if !defined(HAVE_PYTHON) && !defined(TCL_WRAPPER) */
+/*-------------------------------------------------------------------------*/
diff --git a/render.c b/render.c
new file mode 100644
index 0000000..faa8d87
--- /dev/null
+++ b/render.c
@@ -0,0 +1,779 @@
+/*----------------------------------------------------------------------*/
+/* render.c --- Ghostscript rendering of background PostScript files */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/* These routines work only if ghostscript is on the system. */
+/*----------------------------------------------------------------------*/
+
+/* We use OpenGL functions to read and scale images if OpenGL is enabled */
+#ifndef OPENGL
+
+/* #undef GS_DEBUG */
+#define GS_DEBUG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef XC_WIN32
+#include <termios.h>
+#include <unistd.h>
+#endif
+#include <time.h>
+#ifndef XC_WIN32
+#include <sys/wait.h> /* for waitpid() */
+#endif
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xatom.h>
+#else
+#ifdef TCL_WRAPPER
+#include <X11/Xatom.h>
+#endif
+#endif
+
+/*------------------------------------------------------------------------*/
+/* Local includes */
+/*------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+extern char _STR2[250], _STR[150];
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern Display *dpy;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern Cursor appcursors[NUM_CURSORS];
+
+Pixmap bbuf = (Pixmap)NULL; /* background buffer */
+#ifdef DOUBLEBUFFER
+extern Pixmap dbuf;
+#endif
+
+#ifndef HAVE_VFORK
+#define vfork fork
+#endif
+
+int gs_state; /* Track state of the renderer */
+
+#define GS_INIT 0 /* Initial state; gs is idle. */
+#define GS_PENDING 1 /* Drawing in progress; gs is busy. */
+#define GS_READY 2 /* Drawing done; gs is waiting for "next". */
+
+/*------------------------------------------------------*/
+/* Global variable definitions */
+/*------------------------------------------------------*/
+
+Atom gv, gvc, gvpage, gvnext, gvdone;
+#ifndef _MSC_VER
+pid_t gsproc = -1; /* ghostscript process */
+#else
+HANDLE gsproc = INVALID_HANDLE_VALUE;
+#endif
+int fgs[2]; /* stdin pipe pair for ghostscript */
+Window mwin = 0; /* "false" window hack to get gs */
+ /* process to capture ClientMessage */
+ /* events. */
+
+/*--------------------------------------------------------------*/
+/* Preliminary in allowing generic PostScript backgrounds */
+/* via the ghostscript interpreter: Set the GHOSTVIEW and */
+/* GHOSTVIEW atoms, and set the GHOSTVIEW environtment */
+/* variable. */
+/*--------------------------------------------------------------*/
+
+void ghostinit_local()
+{
+ sprintf(_STR, "%ld %d %d %d %d %d %g %g %d %d %d %d",
+ 0L, 0, 0, 0,
+ areawin->width * 75 / 72,
+ areawin->height * 75 / 72,
+ 75.0, 75.0, 0, 0, 0, 0);
+ XChangeProperty(dpy, areawin->window, gv, XA_STRING, 8, PropModeReplace,
+ _STR, strlen(_STR));
+ sprintf(_STR, "%s %d %d", "Color", (int)FOREGROUND, (int)BACKGROUND);
+ XChangeProperty(dpy, areawin->window, gvc, XA_STRING, 8, PropModeReplace,
+ _STR, strlen(_STR));
+ XSync(dpy, False);
+
+ gs_state = GS_INIT;
+}
+
+/*------------------------------------------------------*/
+/* Client message handler. Called by either the Tk */
+/* client message handler (see below) or the Xt handler */
+/* (see xcircuit.c). */
+/* */
+/* Returns True if a client message was received from */
+/* the ghostscript process, False if not. */
+/*------------------------------------------------------*/
+
+Boolean render_client(XEvent *eventPtr)
+{
+ if (eventPtr->xclient.message_type == gvpage) {
+#ifdef GS_DEBUG
+ fprintf(stdout, "Xcircuit: Received PAGE message from ghostscript\n");
+#endif
+ mwin = eventPtr->xclient.data.l[0];
+ Wprintf("Background finished.");
+ XDefineCursor(dpy, areawin->window, DEFAULTCURSOR);
+
+ /* Mark this as the most recently rendered background, so we don't */
+ /* have to render more than necessary. */
+ areawin->lastbackground = xobjs.pagelist[areawin->page]->background.name;
+ gs_state = GS_READY;
+ drawarea(areawin->area, NULL, NULL);
+ }
+ else if (eventPtr->xclient.message_type == gvdone) {
+#ifdef GS_DEBUG
+ fprintf(stdout, "Xcircuit: Received DONE message from ghostscript\n");
+#endif
+ mwin = 0;
+ gs_state = GS_INIT;
+ }
+ else {
+ char *atomname;
+
+ atomname = XGetAtomName(dpy, eventPtr->xclient.message_type);
+ if (atomname != NULL) {
+ fprintf(stderr, "Received client message using atom \"%s\"\n", atomname);
+ XFree(atomname);
+ }
+ return False;
+ }
+ return True;
+}
+
+/*------------------------------------------------------*/
+/* Tk client handler procedure for the above routine. */
+/*------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void handle_client(ClientData clientData, XEvent *eventPtr)
+{
+ if (render_client(eventPtr) == False)
+ fprintf(stderr, "Xcircuit: Received unknown client message\n");
+}
+
+#endif
+
+/*------------------------------------------------------*/
+/* Global initialization */
+/*------------------------------------------------------*/
+
+void ghostinit()
+{
+ gv = XInternAtom(dpy, "GHOSTVIEW", False);
+ gvc = XInternAtom(dpy, "GHOSTVIEW_COLORS", False);
+ gvpage = XInternAtom(dpy, "PAGE", False);
+ gvnext = XInternAtom(dpy, "NEXT", False);
+ gvdone = XInternAtom(dpy, "DONE", False);
+
+ ghostinit_local();
+
+#ifdef TCL_WRAPPER
+ Tk_CreateClientMessageHandler((Tk_ClientMessageProc *)handle_client);
+#endif
+}
+
+/*------------------------------------------------------*/
+/* Send a ClientMessage event */
+/*------------------------------------------------------*/
+
+void send_client(Atom msg)
+{
+ XEvent event;
+
+ if (mwin == 0) return; /* Have to wait for gs */
+ /* to give us window # */
+
+ event.xclient.type = ClientMessage;
+ event.xclient.display = dpy;
+ event.xclient.window = areawin->window;
+ event.xclient.message_type = msg;
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = mwin;
+ event.xclient.data.l[1] = bbuf;
+ XSendEvent(dpy, mwin, False, 0, &event);
+ XFlush(dpy);
+}
+
+/*------------------------------------------------------*/
+/* Ask ghostscript to produce the next page. */
+/*------------------------------------------------------*/
+
+void ask_for_next()
+{
+ if (gs_state != GS_READY) {
+ /* If we're in the middle of rendering something, halt */
+ /* immediately and start over. */
+ if (gs_state == GS_PENDING)
+ reset_gs();
+ return;
+ }
+ XSync(dpy, False);
+ gs_state = GS_PENDING;
+ send_client(gvnext);
+#ifdef GS_DEBUG
+ fprintf(stdout, "Xcircuit: Sent NEXT message to ghostscript\n");
+#endif
+}
+
+/*--------------------------------------------------------*/
+/* Start a ghostscript process and arrange the I/O pipes */
+/* (Commented lines cause ghostscript to relay its stderr */
+/* to xcircuit's stderr) */
+/*--------------------------------------------------------*/
+
+void start_gs()
+{
+ int std_out[2], std_err[2], ret;
+#ifdef XC_WIN32
+ unsigned int pipe_size = 8196;
+ int pipe_mode = _O_BINARY;
+#endif
+#ifdef HAVE_PUTENV
+ static char env_str1[128], env_str2[64];
+#endif
+
+#ifdef TCL_WRAPPER
+ if (bbuf != (Pixmap)NULL) Tk_FreePixmap(dpy, bbuf);
+#ifdef DOUBLEBUFFER
+ bbuf = Tk_GetPixmap(dpy, dbuf, areawin->width, areawin->height,
+ Tk_Depth(areawin->area));
+#else
+ bbuf = Tk_GetPixmap(dpy, (Drawable)areawin->window,
+ areawin->width, areawin->height,
+ Tk_Depth(areawin->area));
+#endif
+
+#else /* !TCL_WRAPPER */
+ if (bbuf != (Pixmap)NULL) XFreePixmap(dpy, bbuf);
+#ifdef DOUBLEBUFFER
+ bbuf = XCreatePixmap(dpy, dbuf, areawin->width, areawin->height,
+ DefaultDepthOfScreen(xcScreen(areawin->area)));
+#else
+ bbuf = XCreatePixmap(dpy, areawin->window,
+ areawin->width, areawin->height,
+ DefaultDepthOfScreen(xcScreen(areawin->area)));
+#endif /* DOUBLEBUFFER */
+#endif /* TCL_WRAPPER */
+
+ XSync(dpy, False);
+
+#ifndef XC_WIN32
+ ret = pipe(fgs);
+ ret = pipe(std_out);
+#else
+ ret = _pipe(fgs, pipe_size, pipe_mode);
+ ret = _pipe(std_out, pipe_size, pipe_mode);
+#endif
+#ifndef GS_DEBUG
+#ifndef XC_WIN32
+ ret = pipe(std_err);
+#else
+ ret = _pipe(srd_err, pipe_size, pipe_mode);
+#endif /* XC_WIN32 */
+#endif
+
+ /* We need a complicated pipe here, with input going from xcircuit */
+ /* to gs to provide scale/position information, and input going from */
+ /* the background file to gs for rendering. */
+ /* Here is not the place to do it. Set up gs to take stdin as input.*/
+
+#ifdef _MSC_VER
+ if (gsproc == INVALID_HANDLE_VALUE) {
+ STARTUPINFO st_info;
+ PROCESS_INFORMATION pr_info;
+ char cmd[4096];
+
+#ifdef HAVE_PUTENV
+ sprintf(env_str1, "DISPLAY=%s", XDisplayString(dpy));
+ putenv(env_str1);
+#ifdef DOUBLEBUFFER
+ sprintf(env_str2, "GHOSTVIEW=%ld %ld", (long)areawin->window, (long)bbuf);
+ putenv(env_str2);
+#else
+ sprintf(env_str2, "GHOSTVIEW=%ld", (long)areawin->window);
+ putenv(env_str2);
+#endif
+#else
+ setenv("DISPLAY", XDisplayString(dpy), True);
+#ifdef DOUBLEBUFFER
+ sprintf(_STR, "%ld %ld", (long)areastruct.areawin, (long)bbuf);
+ setenv("GHOSTVIEW", _STR, True);
+#else
+ sprintf(_STR, "%ld", (long)areastruct.areawin);
+ setenv("GHOSTVIEW", _STR, True);
+#endif
+#endif
+
+ SetHandleInformation((HANDLE)_get_osfhandle(fgs[1]), HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation((HANDLE)_get_osfhandle(std_out[0]), HANDLE_FLAG_INHERIT, 0);
+#ifndef GS_DEBUG
+ SetHandleInformation((HANDLE)_get_osfhandle(std_err[0]), HANDLE_FLAG_INHERIT, 0);
+#endif
+
+ ZeroMemory(&st_info, sizeof(STARTUPINFO));
+ ZeroMemory(&pr_info, sizeof(PROCESS_INFORMATION));
+ st_info.cb = sizeof(STARTUPINFO);
+ st_info.dwFlags = STARTF_USESTDHANDLES;
+ st_info.hStdOutput = (HANDLE)_get_osfhandle(std_out[1]);
+ st_info.hStdInput = (HANDLE)_get_osfhandle(fgs[0]);
+#ifndef GS_DEBUG
+ st_info.hStdError = (HANDLE)_get_osfhandle(std_err[1]);
+#endif
+
+ snprintf(cmd, 4095, "%s -dNOPAUSE -", GS_EXEC);
+ if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &st_info, &pr_info) == 0) {
+ Wprintf("Error: ghostscript not running");
+ return;
+ }
+ CloseHandle(pr_info.hThread);
+ gsproc = pr_info.hProcess;
+ }
+#else
+ if (gsproc < 0) { /* Ghostscript is not running yet */
+ gsproc = vfork();
+ if (gsproc == 0) { /* child process (gs) */
+#ifdef GS_DEBUG
+ fprintf(stdout, "Calling %s\n", GS_EXEC);
+#endif
+ close(std_out[0]);
+#ifndef GS_DEBUG
+ close(std_err[0]);
+#endif
+ dup2(fgs[0], 0);
+ close(fgs[0]);
+ dup2(std_out[1], 1);
+ close(std_out[1]);
+#ifndef GS_DEBUG
+ dup2(std_err[1], 2);
+ close(std_err[1]);
+#endif
+
+#ifdef HAVE_PUTENV
+ sprintf(env_str1, "DISPLAY=%s", XDisplayString(dpy));
+ putenv(env_str1);
+#ifdef DOUBLEBUFFER
+ sprintf(env_str2, "GHOSTVIEW=%ld %ld", (long)areawin->window, (long)bbuf);
+ putenv(env_str2);
+#else
+ sprintf(env_str2, "GHOSTVIEW=%ld", (long)areawin->window);
+ putenv(env_str2);
+#endif
+#else
+ setenv("DISPLAY", XDisplayString(dpy), True);
+#ifdef DOUBLEBUFFER
+ sprintf(_STR, "%ld %ld", (long)areawin->window, (long)bbuf);
+ setenv("GHOSTVIEW", _STR, True);
+#else
+ sprintf(_STR, "%ld", (long)areawin->window);
+ setenv("GHOSTVIEW", _STR, True);
+#endif
+#endif
+ Flush(stderr);
+ execlp(GS_EXEC, "gs", "-dNOPAUSE", "-", (char *)NULL);
+ gsproc = -1;
+ fprintf(stderr, "Exec of gs failed\n");
+ return;
+ }
+ else if (gsproc < 0) {
+ Wprintf("Error: ghostscript not running");
+ return; /* error condition */
+ }
+ }
+#endif
+}
+
+/*--------------------------------------------------------*/
+/* Parse the background file for Bounding Box information */
+/*--------------------------------------------------------*/
+
+void parse_bg(FILE *fi, FILE *fbg) {
+ char *bbptr;
+ Boolean bflag = False;
+ int llx, lly, urx, ury;
+ char line_in[256];
+ float psscale;
+
+ psscale = getpsscale(xobjs.pagelist[areawin->page]->outscale, areawin->page);
+
+ for(;;) {
+ if (fgets(line_in, 255, fi) == NULL) {
+ Wprintf("Error: end of file before end of insert.");
+ return;
+ }
+ else if (strstr(line_in, "end_insert") != NULL) break;
+
+ if (!bflag) {
+ if ((bbptr = strstr(line_in, "BoundingBox:")) != NULL) {
+ if (strstr(line_in, "(atend)") == NULL) {
+ bflag = True;
+ sscanf(bbptr + 12, "%d %d %d %d", &llx, &lly, &urx, &ury);
+ /* compute user coordinate bounds from PostScript bounds */
+#ifdef GS_DEBUG
+ fprintf(stdout, "BBox %d %d %d %d PostScript coordinates\n",
+ llx, lly, urx, ury);
+#endif
+ llx = (int)((float)llx / psscale);
+ lly = (int)((float)lly / psscale);
+ urx = (int)((float)urx / psscale);
+ ury = (int)((float)ury / psscale);
+#ifdef GS_DEBUG
+ fprintf(stdout, "BBox %d %d %d %d XCircuit coordinates\n",
+ llx, lly, urx, ury);
+#endif
+
+ xobjs.pagelist[areawin->page]->background.bbox.lowerleft.x = llx;
+ xobjs.pagelist[areawin->page]->background.bbox.lowerleft.y = lly;
+ xobjs.pagelist[areawin->page]->background.bbox.width = (urx - llx);
+ xobjs.pagelist[areawin->page]->background.bbox.height = (ury - lly);
+ if (fbg == (FILE *)NULL) break;
+ }
+ }
+ }
+ if (fbg != (FILE *)NULL) fputs(line_in, fbg);
+ }
+}
+
+/*-------------------------------------------------------*/
+/* Get bounding box information from the background file */
+/*-------------------------------------------------------*/
+
+void bg_get_bbox()
+{
+ FILE *fi;
+ char *fname;
+
+ fname = xobjs.pagelist[areawin->page]->background.name;
+ if ((fi = fopen(fname, "r")) == NULL) {
+ fprintf(stderr, "Failure to open background file to get bounding box info\n");
+ return;
+ }
+ parse_bg(fi, (FILE *)NULL);
+ fclose(fi);
+}
+
+/*------------------------------------------------------------*/
+/* Adjust object's bounding box based on the background image */
+/*------------------------------------------------------------*/
+
+void backgroundbbox(int mpage)
+{
+ int llx, lly, urx, ury, tmp;
+ objectptr thisobj = xobjs.pagelist[mpage]->pageinst->thisobject;
+ psbkground *thisbg = &xobjs.pagelist[mpage]->background;
+
+ llx = thisobj->bbox.lowerleft.x;
+ lly = thisobj->bbox.lowerleft.y;
+ urx = thisobj->bbox.width + llx;
+ ury = thisobj->bbox.height + lly;
+
+ if (thisbg->bbox.lowerleft.x < llx) llx = thisbg->bbox.lowerleft.x;
+ if (thisbg->bbox.lowerleft.y < lly) lly = thisbg->bbox.lowerleft.y;
+ tmp = thisbg->bbox.width + thisbg->bbox.lowerleft.x;
+ if (tmp > urx) urx = tmp;
+ tmp = thisbg->bbox.height + thisbg->bbox.lowerleft.y;
+ if (tmp > ury) ury = tmp;
+
+ thisobj->bbox.lowerleft.x = llx;
+ thisobj->bbox.lowerleft.y = lly;
+ thisobj->bbox.width = urx - llx;
+ thisobj->bbox.height = ury - lly;
+}
+
+/*------------------------------------------------------*/
+/* Read a background PostScript image from a file and */
+/* store in a temporary file, passing that filename to */
+/* the background property of the page. */
+/*------------------------------------------------------*/
+
+void readbackground(FILE *fi)
+{
+ FILE *fbg = (FILE *)NULL;
+ int tfd;
+ char *file_in = (char *)malloc(9 + strlen(xobjs.tempdir));
+
+ /* "@" denotes a temporary file */
+ sprintf(file_in, "@%s/XXXXXX", xobjs.tempdir);
+
+#ifdef _MSC_VER
+ tfd = mktemp(file_in + 1);
+#else
+ tfd = mkstemp(file_in + 1);
+#endif
+ if (tfd == -1) fprintf(stderr, "Error generating temporary filename\n");
+ else {
+ if ((fbg = fdopen(tfd, "w")) == NULL) {
+ fprintf(stderr, "Error opening temporary file \"%s\"\n", file_in + 1);
+ }
+ }
+
+ /* Read the file to the restore directive or end_insertion */
+ /* Skip restore directive and end_insertion command */
+
+ parse_bg(fi, fbg);
+
+ if (fbg != (FILE *)NULL) {
+ fclose(fbg);
+ register_bg(file_in);
+ }
+ free(file_in);
+}
+
+/*------------------------------------------------------*/
+/* Save a background PostScript image to the output */
+/* file by streaming directly from the background file */
+/*------------------------------------------------------*/
+
+void savebackground(FILE *fo, char *psfilename)
+{
+ FILE *psf;
+ char *fname = psfilename;
+ char line_in[256];
+
+ if (fname[0] == '@') fname++;
+
+ if ((psf = fopen(fname, "r")) == NULL) {
+ fprintf(stderr, "Error opening background file \"%s\" for reading.\n", fname);
+ return;
+ }
+
+ for(;;) {
+ if (fgets(line_in, 255, psf) == NULL)
+ break;
+ else
+ fputs(line_in, fo);
+ }
+ fclose(psf);
+}
+
+/*--------------------------------------------------------------*/
+/* Set up a page to render a PostScript image when redrawing. */
+/* This includes starting the ghostscript process if it has */
+/* not already been started. This routine does not draw the */
+/* image, which is done on refresh. */
+/*--------------------------------------------------------------*/
+
+void register_bg(char *gsfile)
+{
+ if (gsproc < 0)
+ start_gs();
+ else
+ reset_gs();
+
+ xobjs.pagelist[areawin->page]->background.name =
+ (char *) malloc(strlen(gsfile) + 1);
+ strcpy(xobjs.pagelist[areawin->page]->background.name, gsfile);
+}
+
+/*------------------------------------------------------*/
+/* Load a generic (non-xcircuit) postscript file as the */
+/* background for the page. This function is called */
+/* by the file import routine, and so it completes by */
+/* running zoomview(), which redraws the image and */
+/* the page. */
+/*------------------------------------------------------*/
+
+void loadbackground()
+{
+ register_bg(_STR2);
+ bg_get_bbox();
+ updatepagebounds(topobject);
+ zoomview(areawin->area, NULL, NULL);
+}
+
+/*------------------------------------------------------*/
+/* Send text to the ghostscript renderer */
+/*------------------------------------------------------*/
+
+void send_to_gs(char *text)
+{
+#ifndef XC_WIN32
+ write(fgs[1], text, strlen(text));
+ tcflush(fgs[1], TCOFLUSH);
+#else
+ _write(fgs[1], text, (unsigned int)strlen(text));
+#endif
+#ifdef GS_DEBUG
+ fprintf(stdout, "writing: %s", text);
+#endif
+}
+
+/*------------------------------------------------------*/
+/* Call ghostscript to render the background into the */
+/* pixmap buffer. */
+/*------------------------------------------------------*/
+
+int renderbackground()
+{
+ char *bgfile;
+ float psnorm, psxpos, psypos, defscale;
+ float devres = 0.96; /* = 72.0 / 75.0, ps_units/in : screen_dpi */
+
+ if (gsproc < 0) return -1;
+
+ defscale = (xobjs.pagelist[areawin->page]->coordstyle == CM) ?
+ CMSCALE : INCHSCALE;
+
+ psnorm = areawin->vscale * (1.0 / defscale) * devres;
+
+ psxpos = (float)(-areawin->pcorner.x) * areawin->vscale * devres;
+ psypos = (float)(-areawin->pcorner.y) * areawin->vscale * devres
+ + ((float)areawin->height / 12.0);
+
+ /* Conditions for re-rendering: Must have a background specified */
+ /* and must be on the page, not a library or other object. */
+
+ if (xobjs.pagelist[areawin->page]->background.name == (char *)NULL)
+ return -1;
+ else if (areawin->lastbackground
+ == xobjs.pagelist[areawin->page]->background.name) {
+ return 0;
+ }
+
+ if (is_page(topobject) == -1)
+ return -1;
+
+ bgfile = xobjs.pagelist[areawin->page]->background.name;
+ if (*bgfile == '@') bgfile++;
+
+ /* Ask ghostscript to produce the next page */
+ ask_for_next();
+
+ /* Set the last background name to NULL; this will get the */
+ /* value when the rendering is done. */
+
+ areawin->lastbackground = NULL;
+
+ /* write scale and position to ghostscript */
+ /* and tell ghostscript to run the requested file */
+
+ send_to_gs("/GSobj save def\n");
+ send_to_gs("/setpagedevice {pop} def\n");
+ send_to_gs("gsave\n");
+ sprintf(_STR, "%3.2f %3.2f translate\n", psxpos, psypos);
+ send_to_gs(_STR);
+ sprintf(_STR, "%3.2f %3.2f scale\n", psnorm, psnorm);
+ send_to_gs(_STR);
+ sprintf(_STR, "(%s) run\n", bgfile);
+ send_to_gs(_STR);
+ send_to_gs("GSobj restore\n");
+ send_to_gs("grestore\n");
+
+#ifdef GS_DEBUG
+ fprintf(stdout, "Rendering background from file \"%s\"\n", bgfile);
+#endif
+ Wprintf("Rendering background image.");
+ XDefineCursor(dpy, areawin->window, WAITFOR);
+
+ /* The page will be refreshed when we receive confirmation */
+ /* from ghostscript that the buffer has been rendered. */
+
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Copy the rendered background pixmap to the window. */
+/*------------------------------------------------------*/
+
+int copybackground()
+{
+ /* Don't copy if the buffer is not ready to use */
+ if (gs_state != GS_READY)
+ return -1;
+
+ /* Only draw on a top-level page */
+ if (is_page(topobject) == -1)
+ return -1;
+
+#ifdef DOUBLEBUFFER
+ XCopyArea(dpy, bbuf, dbuf, areawin->gc, 0, 0,
+ areawin->width, areawin->height, 0, 0);
+#else
+ XCopyArea(dpy, bbuf, areawin->window, areawin->gc, 0, 0,
+ areawin->width, areawin->height, 0, 0);
+#endif
+
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Exit ghostscript. . . not so gently */
+/*------------------------------------------------------*/
+
+int exit_gs()
+{
+#ifdef _MSC_VER
+ if (gsproc == INVALID_HANDLE_VALUE) return -1; /* gs not running */
+#else
+ if (gsproc < 0) return -1; /* gs not running */
+#endif
+
+#ifdef GS_DEBUG
+ fprintf(stdout, "Waiting for gs to exit\n");
+#endif
+#ifndef _MSC_VER
+ kill(gsproc, SIGKILL);
+ waitpid(gsproc, NULL, 0);
+#else
+ TerminateProcess(gsproc, -1);
+#endif
+#ifdef GS_DEBUG
+ fprintf(stdout, "gs has exited\n");
+#endif
+
+ mwin = 0;
+#ifdef _MSC_VER
+ gsproc = INVALID_HANDLE_VALUE;
+#else
+ gsproc = -1;
+#endif
+ gs_state = GS_INIT;
+
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Restart ghostscript */
+/*------------------------------------------------------*/
+
+int reset_gs()
+{
+#ifdef _MSC_VER
+ if (gsproc == INVALID_HANDLE_VALUE) return -1;
+#else
+ if (gsproc < 0) return -1;
+#endif
+
+ exit_gs();
+ ghostinit_local();
+ start_gs();
+
+ return 0;
+}
+
+#endif /* !OPENGL */
+
+/*----------------------------------------------------------------------*/
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..0850dcb
--- /dev/null
+++ b/resource.h
@@ -0,0 +1,55 @@
+#ifndef RESOURCE_H
+#define RESOURCE_H
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by dialogs.rc
+//
+#define IDD_INPUTDIALOG 101
+#define IDD_HELPDLG 103
+#define IDD_OUTPUTDLG 104
+#define IDC_EDIT1 1000
+#define IDC_INFOTEXT 1001
+#define IDC_HELPPIX 1003
+#define IDC_PAGENUM 1004
+#define IDC_FILENAME 1005
+#define IDC_APPLY1 1006
+#define IDC_PAGELABEL 1007
+#define IDC_APPLY2 1008
+#define IDC_SCALE 1009
+#define IDC_APPLY3 1010
+#define IDC_WIDTH 1011
+#define IDC_APPLY4 1012
+#define IDC_HEIGHT 1013
+#define IDC_APPLY5 1014
+#define IDC_APPLY6 1015
+#define IDC_ORIENTATION 1018
+#define IDC_AUTOFIT 1019
+#define IDC_MODE 1020
+#define IDC_FPEDIT 1021
+#define IDC_PSINFO 1022
+#define IDC_STATIC1 1023
+#define IDC_STATIC2 1024
+#define IDC_STATIC3 1025
+#define IDC_STATIC4 1026
+#define IDC_STATIC5 1027
+#define IDC_STATIC6 1028
+#define IDC_STATIC7 1029
+#define IDC_FILEOPEN 1030
+
+#define IDR_XCIRCUIT 2001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+#define IDR_A 2001
+
+#endif /* RESOURCE_H */
diff --git a/resources.rc b/resources.rc
new file mode 100644
index 0000000..868755c
--- /dev/null
+++ b/resources.rc
@@ -0,0 +1,82 @@
+#include <windows.h>
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icons
+//
+
+xcircuit ICON DISCARDABLE "lib\\pixmaps\\xcircuit.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_INPUTDIALOG DIALOG DISCARDABLE 0, 0, 186, 63
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "XCircuit"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,7,42,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,42,50,14
+ LTEXT "Static",IDC_INFOTEXT,7,7,172,8
+ EDITTEXT IDC_EDIT1,7,20,172,12,ES_AUTOHSCROLL
+END
+
+IDD_HELPDLG DIALOG DISCARDABLE 0, 0, 186, 332
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Help"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,67,311,50,14
+ CONTROL "",IDC_HELPPIX,"XcHelp",WS_VSCROLL,7,7,160,297
+END
+
+IDD_OUTPUTDLG DIALOG DISCARDABLE 0, 0, 272, 193
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Output"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Write File",IDOK,206,172,59,14
+ PUSHBUTTON "Cancel",IDCANCEL,7,172,50,14
+ LTEXT "Postscript output properties:",IDC_PSINFO,7,7,127,12,
+ SS_CENTERIMAGE
+ CONTROL "Pages",IDC_PAGENUM,"Button",BS_AUTOCHECKBOX | NOT
+ WS_VISIBLE | WS_TABSTOP,144,7,74,12
+ EDITTEXT IDC_FILENAME,49,27,146,12,ES_AUTOHSCROLL
+ LTEXT "Filename:",IDC_STATIC1,7,29,41,8
+ PUSHBUTTON "Apply",IDC_APPLY1,215,26,50,14
+ EDITTEXT IDC_PAGELABEL,49,47,158,12,ES_AUTOHSCROLL
+ LTEXT "Page label:",IDC_STATIC2,7,49,41,8
+ PUSHBUTTON "Apply",IDC_APPLY2,215,46,50,14
+ EDITTEXT IDC_SCALE,49,67,158,12,ES_AUTOHSCROLL
+ LTEXT "Scale:",IDC_STATIC3,7,69,40,8
+ PUSHBUTTON "Apply",IDC_APPLY3,215,66,50,14
+ EDITTEXT IDC_WIDTH,49,87,158,12,ES_AUTOHSCROLL
+ LTEXT "Width:",IDC_STATIC4,7,89,40,8
+ PUSHBUTTON "Apply",IDC_APPLY4,215,86,50,14
+ EDITTEXT IDC_HEIGHT,49,107,158,12,ES_AUTOHSCROLL
+ LTEXT "Height:",IDC_STATIC5,7,109,40,8
+ PUSHBUTTON "Apply",IDC_APPLY5,215,106,50,14
+ LTEXT "Orientation:",IDC_STATIC6,7,130,42,8
+ COMBOBOX IDC_ORIENTATION,49,128,77,52,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_TABSTOP
+ CONTROL "Auto-fit",IDC_AUTOFIT,"Button",BS_AUTOCHECKBOX | NOT
+ WS_VISIBLE | WS_TABSTOP,135,129,38,10
+ LTEXT "Mode:",IDC_STATIC7,7,149,41,8
+ COMBOBOX IDC_MODE,49,147,77,52,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_TABSTOP
+ PUSHBUTTON "Apply",IDC_APPLY6,215,146,50,14,NOT WS_VISIBLE
+ EDITTEXT IDC_FPEDIT,135,147,72,12,ES_AUTOHSCROLL | NOT WS_VISIBLE
+ PUSHBUTTON "...",IDC_FILEOPEN,195,27,12,12,NOT WS_TABSTOP
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+#ifdef USE_WIN32_COM
+1 TYPELIB "XCCom.tlb"
+#endif
diff --git a/schema.c b/schema.c
new file mode 100644
index 0000000..ba6faf7
--- /dev/null
+++ b/schema.c
@@ -0,0 +1,1152 @@
+/*-------------------------------------------------------------------------*/
+/* schema.c --- xcircuit routines specific to the schematic capture system */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 10/13/97 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#include "Xw/MenuBtn.h"
+#endif
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "colordefs.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern int *appcolors;
+extern xcWidget menuwidgets[];
+extern xcWidget netbutton;
+extern char _STR[150];
+extern char _STR2[250];
+
+/*-------------------------------------------------------------------------*/
+
+extern xcWidget wsymb, wschema;
+
+/*--------------------------------------------------------*/
+/* Menu calls (procedure wrappers) */
+/*--------------------------------------------------------*/
+
+void callwritenet(xcWidget w, pointertype mode, caddr_t calldata)
+{
+ switch(mode) {
+ case 0:
+ writenet(topobject, "spice", "spc");
+ break;
+ case 1:
+ writenet(topobject, "flatsim", "sim");
+ break;
+ case 2:
+ writenet(topobject, "pcb", "pcbnet");
+ break;
+ case 3:
+ writenet(topobject, "flatspice", "fspc");
+ break;
+ case 4:
+ /* Auto-numbering: no output generated */
+ writenet(topobject, "indexpcb", "");
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the page object and instance with the indicated name. */
+/*----------------------------------------------------------------------*/
+
+objectptr NameToPageObject(char *objname, objinstptr *ret_inst, int *ret_page)
+{
+ int i;
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst == NULL) continue;
+ if (!strcmp(objname, xobjs.pagelist[i]->pageinst->thisobject->name)) {
+ if (ret_inst) *ret_inst = xobjs.pagelist[i]->pageinst;
+ if (ret_page) *ret_page = i;
+ return xobjs.pagelist[i]->pageinst->thisobject;
+ }
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the canonical name of an object (the part without the */
+/* technology prefix, if any). */
+/*--------------------------------------------------------------*/
+
+char *GetCanonicalName(char *fullname)
+{
+ char *canonname = strstr(fullname, "::");
+ if (canonname == NULL) return fullname;
+ return canonname + 2;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the object with the indicated name. */
+/* */
+/* WARNING: If no library technology is given, XCircuit will return */
+/* the first object with the name "objname". If there are multiple */
+/* objects of the same name in different technologies, then the one */
+/* returned may not be the one expected! */
+/*----------------------------------------------------------------------*/
+
+objectptr NameToObject(char *objname, objinstptr *ret_inst, Boolean dopages)
+{
+ int i;
+ liblistptr spec;
+ Boolean notech = FALSE;
+ char *techptr;
+
+ if (strstr(objname, "::") == NULL) notech = TRUE;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (spec = xobjs.userlibs[i].instlist; spec != NULL; spec = spec->next) {
+ techptr = spec->thisinst->thisobject->name;
+ if (notech)
+ techptr = GetCanonicalName(spec->thisinst->thisobject->name);
+ if (!strcmp(objname, techptr)) {
+ if (ret_inst) *ret_inst = spec->thisinst;
+ return spec->thisinst->thisobject;
+ }
+ }
+ }
+
+ if (dopages)
+ return NameToPageObject(objname, ret_inst, NULL);
+ else
+ return NULL;
+}
+
+/*------------------------------------------------------------------------*/
+/* Ensure that a page name is unique (required for schematic association) */
+/*------------------------------------------------------------------------*/
+
+int checkpagename(objectptr thispageobj)
+{
+ int p, thispage;
+ /* char *objname = thispageobj->name; (jdk) */
+ Boolean changed;
+ Boolean update = False;
+ char *clnptr = NULL;
+ int n;
+
+ /* Check for ":n" suffix and prepare for possible update */
+ clnptr = strrchr(thispageobj->name, ':');
+ if (clnptr != NULL)
+ if (sscanf(clnptr + 1, "%d", &n) != 1)
+ clnptr = NULL;
+
+ /* Find the page number of this page object */
+ for (p = 0; p < xobjs.pages; p++) {
+ if (xobjs.pagelist[p]->pageinst != NULL) {
+ if (xobjs.pagelist[p]->pageinst->thisobject == thispageobj) {
+ thispage = p;
+ break;
+ }
+ }
+ }
+ if (p == xobjs.pages) {
+ Fprintf(stderr, "Error: Object is not a page object!\n");
+ return 0;
+ }
+
+ /* Look for any other pages with the same name */
+ do {
+ changed = False;
+ for (p = 0; p < xobjs.pages; p++) {
+ if (p == thispage) continue;
+ if (xobjs.pagelist[p]->pageinst != NULL) {
+ if (!filecmp(xobjs.pagelist[p]->pageinst->thisobject->name,
+ thispageobj->name)) {
+ /* append ":2" to name or update suffix to ensure uniqueness */
+ if (clnptr == NULL)
+ sprintf(thispageobj->name, "%s:2", thispageobj->name);
+ else
+ sprintf(clnptr + 1, "%d", n + 1);
+ changed = True;
+ update = True;
+ break;
+ }
+ }
+ }
+ } while (changed);
+ if (update) {
+ renamepage(thispage);
+ return -1;
+ }
+ return 0;
+}
+
+/*--------------------------------------*/
+/* Find connectivity of a selection */
+/*--------------------------------------*/
+
+void startconnect(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ if (areawin->selects > 0)
+ connectivity(button, clientdata, calldata);
+}
+
+/*----------------------------------------------------------------------*/
+/* connectivity(): Find electrical connections into a node. */
+/* (does recursive search on object heirarchy) */
+/*----------------------------------------------------------------------*/
+
+void connectivity(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ short *gsel = NULL;
+ selection *rselect = NULL, *nextselect;
+ genericptr ggen = NULL;
+ Genericlist *netlist = NULL;
+ int depth, lbus, netid, subnetid;
+ buslist *sbus;
+ pushlistptr seltop, nextptr;
+ objectptr nettop, pschem; /* thisobj, (jdk) */
+ char *snew;
+ stringpart *ppin;
+
+ /* erase any existing highlighted network */
+ highlightnetlist(topobject, areawin->topinstance, 0);
+
+ seltop = (pushlistptr)malloc(sizeof(pushlist));
+ seltop->thisinst = areawin->topinstance;
+ seltop->next = NULL;
+
+ /* pick the first selection that looks like a valid network part */
+
+ if (areawin->selects > 0) {
+ for (gsel = areawin->selectlist; gsel < areawin->selectlist +
+ areawin->selects; gsel++) {
+ ggen = *(topobject->plist + *gsel);
+ if (SELECTTYPE(gsel) == LABEL) {
+ labelptr glab = SELTOLABEL(gsel);
+ if (glab->pin == LOCAL || glab->pin == GLOBAL) break;
+ }
+ else if (SELECTTYPE(gsel) == POLYGON) {
+ polyptr gpoly = SELTOPOLY(gsel);
+ if (!nonnetwork(gpoly)) break;
+ }
+ }
+ }
+ if ((areawin->selects == 0) || (gsel == areawin->selectlist
+ + areawin->selects)) {
+ rselect = recurselect(POLYGON | LABEL | OBJINST, MODE_CONNECT, &seltop);
+ /* Should look at the top scorer, when scoring has been implemented */
+ if (rselect && (rselect->selects > 0)) {
+ for (nextselect = rselect; (nextselect->next != NULL) &&
+ (nextselect->selects > 0); nextselect = nextselect->next);
+ ggen = *(nextselect->thisinst->thisobject->plist + *(nextselect->selectlist));
+ while (rselect != NULL) {
+ nextselect = rselect->next;
+ free(rselect->selectlist);
+ free(rselect);
+ rselect = nextselect;
+ }
+ }
+ }
+
+ /* Determine the net and the topmost object in which that */
+ /* net appears. Then build the transformation matrix down */
+ /* to that object. highlightnet() should end by popping the */
+ /* entire matrix stack. */
+
+ if (ggen != NULL) {
+ if (checkvalid(topobject) == -1) {
+ destroynets(topobject);
+ createnets(areawin->topinstance, FALSE);
+ }
+ if ((netlist = is_resolved(&ggen, seltop, &nettop)) != NULL) {
+ depth = pushnetwork(seltop, nettop);
+ /* Fprintf(stdout, ">> Pushed network %d levels deep\n", depth); */
+ nextptr = seltop;
+ while (nextptr->thisinst->thisobject != nettop)
+ nextptr = nextptr->next;
+
+ nextptr->thisinst->thisobject->highlight.netlist = netlist;
+ nextptr->thisinst->thisobject->highlight.thisinst = nextptr->thisinst;
+ highlightnetlist(nettop, nextptr->thisinst, 1);
+
+ /* pop the matrix stack */
+ while (depth-- > 0)
+ UPopCTM();
+
+ /* get the primary schematic */
+ pschem = (nettop->schemtype == SECONDARY) ? nettop->symschem : nettop;
+
+ /* print the net name to the message window */
+
+ if (netlist->subnets == 0) {
+ ppin = nettopin(netlist->net.id, pschem, NULL);
+ snew = textprint(ppin, areawin->topinstance);
+ sprintf(_STR2, "Network is \"%s\" in %s", snew, nettop->name);
+ free(snew);
+ }
+ else {
+ char *sptr;
+ sprintf(_STR2, "Network(s): ");
+ sptr = _STR2 + strlen(_STR2);
+ for (lbus = 0; lbus < netlist->subnets; lbus++) {
+ sbus = netlist->net.list + lbus;
+ netid = sbus->netid;
+ subnetid = sbus->subnetid;
+ ppin = nettopin(netid, pschem, NULL);
+ snew = textprintsubnet(ppin, areawin->topinstance, subnetid);
+ sprintf(sptr, "%s ", snew);
+ sptr += strlen(snew) + 1;
+ free(snew);
+ }
+ sprintf(sptr, "in %s", nettop->name);
+ }
+ Wprintf("%s", _STR2);
+
+#ifdef TCL_WRAPPER
+ Tcl_SetObjResult(xcinterp, Tcl_NewStringObj(snew, strlen(snew)));
+#endif
+ }
+ else
+ Wprintf("Selected element is not part of a valid network.");
+ }
+ else {
+ Wprintf("No networks found near the cursor position");
+ netid = 0;
+ }
+
+ /* free up linked list */
+
+ while (seltop != NULL) {
+ nextptr = seltop->next;
+ free(seltop);
+ seltop = nextptr;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Set object type to FUNDAMENTAL if it contains one or more */
+/* info labels and is not associated with a schematic/symbol. */
+/* */
+/* Return TRUE if the object has electrically relevant */
+/* networks, FALSE if not. */
+/*--------------------------------------------------------------*/
+
+Boolean setobjecttype(objectptr cschem)
+{
+ genericptr *cgen;
+ labelptr clab;
+
+ /* If networks are specifically prohibited. . . */
+ if (cschem->schemtype == NONETWORK) return False;
+
+ /* Apply only to schematic objects */
+
+ if ((cschem->schemtype != PRIMARY) && (cschem->schemtype != SECONDARY)) {
+ if (cschem->schemtype == FUNDAMENTAL)
+ cschem->schemtype = SYMBOL;
+ if (cschem->symschem == NULL) {
+ for (cgen = cschem->plist; cgen < cschem->plist + cschem->parts; cgen++) {
+ if (IS_LABEL(*cgen)) {
+ clab = TOLABEL(cgen);
+ if (clab->pin == INFO) {
+ cschem->schemtype = FUNDAMENTAL;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ((cschem->symschem != NULL) && (cschem->schemtype == SYMBOL))
+ return False;
+ else if ((cschem->schemtype == TRIVIAL) || (cschem->schemtype == FUNDAMENTAL))
+ return False;
+
+ return True;
+}
+
+/*------------------------------------------------------*/
+/* Pin conversion subroutine for dopintype() */
+/*------------------------------------------------------*/
+
+void pinconvert(labelptr thislab, pointertype mode)
+{
+ thislab->pin = mode;
+ switch (mode) {
+ case NORMAL:
+ thislab->color = DEFAULTCOLOR; /* nominally black */
+ break;
+ case GLOBAL:
+ thislab->color = GLOBALPINCOLOR; /* orange */
+ break;
+ case LOCAL:
+ thislab->color = LOCALPINCOLOR; /* red */
+ break;
+ case INFO:
+ thislab->color = INFOLABELCOLOR; /* green */
+ break;
+ }
+}
+
+/*---------------------------------------------------------*/
+/* Change a label's type to NORMAL, GLOBAL, INFO, or LOCAL */
+/*---------------------------------------------------------*/
+
+void dopintype(xcWidget w, pointertype mode, caddr_t calldata)
+{
+ short *gsel;
+ char typestr[40];
+ short savetype = -1;
+
+ if (areawin->selects == 0) {
+ Wprintf("Must first select a label to change type");
+ return;
+ }
+
+ strcpy(typestr, "Changed label to ");
+ switch(mode) {
+ case NORMAL:
+ strcat(typestr, "normal label");
+ break;
+ case GLOBAL:
+ strcat(typestr, "global pin");
+ break;
+ case LOCAL:
+ strcat(typestr, "local pin");
+ break;
+ case INFO:
+ strcat(typestr, "info-label");
+ break;
+ }
+
+ for (gsel = areawin->selectlist; gsel < areawin->selectlist +
+ areawin->selects; gsel++)
+ if (SELECTTYPE(gsel) == LABEL) {
+ labelptr glab = SELTOLABEL(gsel);
+ savetype = glab->pin;
+ pinconvert(glab, mode);
+ setobjecttype(topobject);
+ }
+
+ if (savetype >= 0) {
+ unselect_all();
+ drawarea(NULL, NULL, NULL);
+ Wprintf("%s", typestr);
+ }
+ else {
+ Wprintf("No labels selected.");
+ }
+}
+
+/*----------------------------------------------------------*/
+/* Set colors on the symbol/schematic buttons appropriately */
+/*----------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void setsymschem()
+{
+ XcInternalTagCall(xcinterp, 1, "schematic");
+}
+
+#else
+
+void setsymschem()
+{
+ Arg aargs[2], bargs[2];
+
+ /* Set menu items appropriately for this object */
+
+ if (topobject->symschem != NULL) {
+ if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY) {
+ XtSetArg(aargs[0], XtNlabel, "Go To Symbol");
+ XtSetArg(bargs[0], XtNlabel, "Disassociate Symbol");
+ }
+ else {
+ XtSetArg(aargs[0], XtNlabel, "Go To Schematic");
+ XtSetArg(bargs[0], XtNlabel, "Disassociate Schematic");
+ }
+ }
+ else {
+ if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY) {
+ XtSetArg(aargs[0], XtNlabel, "Make Matching Symbol");
+ XtSetArg(bargs[0], XtNlabel, "Associate with Symbol");
+ }
+ else {
+ XtSetArg(aargs[0], XtNlabel, "Make Matching Schematic");
+ XtSetArg(bargs[0], XtNlabel, "Associate with Schematic");
+ }
+ }
+ XtSetValues(NetlistMakeMatchingSymbolButton, aargs, 1);
+ XtSetValues(NetlistAssociatewithSymbolButton, bargs, 1);
+
+ /* Set colors on the symbol and schematic buttons */
+
+ if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY) {
+ if (topobject->symschem == NULL) {
+ XtSetArg(aargs[0], XtNbackground, OFFBUTTONCOLOR);
+ XtSetArg(aargs[1], XtNforeground, OFFBUTTONCOLOR);
+ }
+ else {
+ XtSetArg(aargs[0], XtNbackground, BACKGROUND);
+ XtSetArg(aargs[1], XtNforeground, FOREGROUND);
+ }
+
+ XtSetArg(bargs[1], XtNforeground, FOREGROUND);
+ XtSetArg(bargs[0], XtNbackground, SNAPCOLOR);
+ }
+ else {
+ if (topobject->symschem != NULL) {
+ XtSetArg(bargs[0], XtNbackground, BACKGROUND);
+ XtSetArg(bargs[1], XtNforeground, FOREGROUND);
+ }
+ else {
+ XtSetArg(bargs[0], XtNbackground, OFFBUTTONCOLOR);
+ XtSetArg(bargs[1], XtNforeground, OFFBUTTONCOLOR);
+ }
+
+ XtSetArg(aargs[1], XtNforeground, FOREGROUND);
+ if (topobject->schemtype == FUNDAMENTAL)
+ XtSetArg(aargs[0], XtNbackground, AUXCOLOR);
+ else if (topobject->schemtype == TRIVIAL || topobject->symschem != NULL)
+ XtSetArg(aargs[0], XtNbackground, SNAPCOLOR);
+ else {
+ XtSetArg(aargs[0], XtNbackground, OFFBUTTONCOLOR);
+ XtSetArg(aargs[1], XtNforeground, OFFBUTTONCOLOR);
+ XtSetArg(bargs[0], XtNbackground, BBOXCOLOR);
+ XtSetArg(bargs[1], XtNforeground, FOREGROUND);
+ }
+ }
+
+ XtSetValues(wsymb, aargs, 2);
+ XtSetValues(wschema, bargs, 2);
+}
+
+#endif
+
+/*--------------------------------------------------------*/
+/* Find the page number for an object */
+/*--------------------------------------------------------*/
+
+int findpageobj(objectptr pobj)
+{
+ int tpage;
+
+ for (tpage = 0; tpage < xobjs.pages; tpage++)
+ if (xobjs.pagelist[tpage]->pageinst != NULL)
+ if (xobjs.pagelist[tpage]->pageinst->thisobject == pobj)
+ return tpage;
+
+ return -1;
+}
+
+/*------------------------------------------------------*/
+/* Enumerate all of the pages which are subschematics */
+/* of "toppage" and return the result in the list */
+/* passed as a pointer. The list is assumed to be */
+/* already allocated, and equal to the total number of */
+/* pages (xobjs.pages). */
+/* */
+/* Avoid possible recursion problems by limiting the */
+/* number of recursion levels. Presumably no circuit */
+/* would have more than several hundred hierarchical */
+/* levels. */
+/* */
+/* If "dolinks" is TRUE, ennumerate and follow pages */
+/* that are descendents of the top level when the */
+/* calling symbol instance has a "link" parameter and */
+/* that parameter points to the same filename as the */
+/* page. This indicates a multiple-file project; the */
+/* pages keep separate records of changes, and are */
+/* saved independently, and loaded through the link */
+/* dependency method. */
+/*------------------------------------------------------*/
+
+int findsubschems(int toppage, objectptr cschem, int level, short *pagelist,
+ Boolean dolinks)
+{
+ genericptr *cgen;
+
+ if (level == HIERARCHY_LIMIT) return -1; /* sanity check */
+
+ for (cgen = cschem->plist; cgen < cschem->plist + cschem->parts; cgen++) {
+ if (IS_OBJINST(*cgen)) {
+ objinstptr cinst = TOOBJINST(cgen);
+ objectptr cobj = cinst->thisobject;
+
+ if (cobj->symschem != NULL) {
+ int pageno = findpageobj(cobj->symschem);
+
+ if ((pageno >= 0) && (pageno < xobjs.pages)) {
+
+ /* Look for a "link" parameter */
+ if (dolinks == FALSE) {
+ oparamptr ops;
+ ops = find_param(cinst, "link");
+ if ((ops != NULL) && (ops->type == XC_STRING)) {
+ char *filename = textprint(ops->parameter.string, cinst);
+ if (!strcmp(filename, "%n") || !strcmp(filename, "%N") ||
+ !strcmp(filename, xobjs.pagelist[pageno]->filename)) {
+ free(filename);
+ continue;
+ }
+ free(filename);
+ }
+ }
+
+ /* Add this page to the list */
+ pagelist[pageno]++;
+ }
+
+ /* A symbol on its own schematic page is allowed for clarity */
+ /* of the schematic, but this cannot be a functional part of */
+ /* the schematic circuit! */
+
+ if (cobj->symschem != cschem) {
+ if (findsubschems(toppage, cobj->symschem,
+ level + 1, pagelist, dolinks) == -1)
+ return -1;
+ }
+ }
+ else if (cobj->schemtype != FUNDAMENTAL && cobj->schemtype != TRIVIAL) {
+ /* Check symbols acting as their own schematics */
+ if (findsubschems(toppage, cobj, level + 1, pagelist, dolinks) == -1)
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*------------------------------------------------------*/
+/* Recursively find all sub-circuits associated with */
+/* the top-level circuit. For each schematic that does */
+/* not have a valid filename, set the filename equal to */
+/* the filename of the "toppage" schematic. */
+/*------------------------------------------------------*/
+
+void collectsubschems(int toppage)
+{
+ int loctop;
+ objectptr cschem;
+ short *pagelist, pageno;
+ Pagedata *curpage;
+
+ loctop = toppage;
+ curpage = xobjs.pagelist[loctop];
+ if (curpage->pageinst == NULL) return;
+ cschem = curpage->pageinst->thisobject;
+ if (cschem->schemtype == SECONDARY) {
+ cschem = cschem->symschem;
+ loctop = is_page(cschem);
+ if (loctop < 0) return;
+ curpage = xobjs.pagelist[loctop];
+ }
+
+ pagelist = (short *)malloc(xobjs.pages * sizeof(short));
+
+ for (pageno = 0; pageno < xobjs.pages; pageno++)
+ pagelist[pageno] = 0;
+
+ findsubschems(loctop, cschem, 0, pagelist, FALSE);
+
+ for (pageno = 0; pageno < xobjs.pages; pageno++) {
+ if (pageno == loctop) continue;
+ if (pagelist[pageno] > 0) {
+ if (xobjs.pagelist[pageno]->filename != NULL)
+ free(xobjs.pagelist[pageno]->filename);
+ xobjs.pagelist[pageno]->filename =
+ strdup(xobjs.pagelist[loctop]->filename);
+ }
+ }
+ free((char *)pagelist);
+}
+
+/*------------------------------------------------------*/
+/* compare_qualified(str1, str2) --- */
+/* */
+/* String comparison for technology-qualified */
+/* names. str2" must be a fully-qualified name. */
+/* "str1" may be qualified or unqualified. If */
+/* unqualified, compare_qualified will return TRUE */
+/* for any "str2" that matches the name part of */
+/* the technology::name format. */
+/* */
+/* Return value: TRUE if match, FALSE if not. */
+/*------------------------------------------------------*/
+
+Boolean compare_qualified(char *str1, char *str2)
+{
+ char *sptr1, *sptr2;
+ Boolean qual1, qual2;
+
+ sptr2 = strstr(str2, "::");
+ qual2 = (sptr2 == NULL) ? FALSE : TRUE;
+
+ if (!qual2) return (!strcmp(str1, str2));
+
+ sptr1 = strstr(str1, "::");
+ qual1 = (sptr1 == NULL) ? FALSE : TRUE;
+
+ if (qual1) return (!strcmp(str1, str2));
+
+ sptr2 += 2;
+ return (!strcmp(str1, sptr2));
+}
+
+/*-------------------------------------------------------*/
+/* Check if top-level page is the same name as a library */
+/* object; if so, connect it. */
+/* Note that it is not an error not to find the matching */
+/* symbol/schematic. "is_schematic" and "is_symbol" */
+/* comments in the .ps file are complementary, so the */
+/* first one encountered will always fail, and the other */
+/* will succeed. */
+/*-------------------------------------------------------*/
+
+int checkschem(objectptr thisobj, char *cname)
+{
+ objectptr *tlib;
+ short i, j;
+
+ if (thisobj->symschem != NULL) return 0;
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ for (j = 0; j < xobjs.userlibs[i].number; j++) {
+ tlib = xobjs.userlibs[i].library + j;
+
+ if (compare_qualified(cname, (*tlib)->name)) {
+ thisobj->symschem = (*tlib);
+ thisobj->schemtype = PRIMARY;
+ (*tlib)->symschem = thisobj;
+ (*tlib)->schemtype = SYMBOL;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------*/
+/* Complement to the above routine: If a library object */
+/* name is the same as a top-level page, connect them. */
+/*--------------------------------------------------------*/
+
+int checksym(objectptr symobj, char *cname)
+{
+ short cpage;
+ objectptr checkpage;
+
+ if (symobj->symschem != NULL) return 0;
+
+ for (cpage = 0; cpage < xobjs.pages; cpage++) {
+ if (xobjs.pagelist[cpage]->pageinst != NULL) {
+ checkpage = xobjs.pagelist[cpage]->pageinst->thisobject;
+ if (compare_qualified(cname, checkpage->name)) {
+ symobj->symschem = checkpage;
+ symobj->schemtype = SYMBOL;
+ checkpage->symschem = symobj;
+ checkpage->schemtype = PRIMARY;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find location of corresponding pin in symbol/schematic and change it */
+/* to the text of the indicated label. */
+/* */
+/* Return the number of other pins changed. zero indicates that no */
+/* corresponding pins were found, and therefore nothing was changed. */
+/*----------------------------------------------------------------------*/
+
+int changeotherpins(labelptr newlabel, stringpart *oldstring)
+{
+ objectptr other = topobject->symschem;
+ genericptr *tgen;
+ labelptr tlab;
+ int rval = 0;
+
+ if (other == NULL) return rval;
+
+ for (tgen = other->plist; tgen < other->plist + other->parts; tgen++) {
+ if (IS_LABEL(*tgen)) {
+ tlab = TOLABEL(tgen);
+ if (tlab->pin != LOCAL) continue;
+ if (!stringcomp(tlab->string, oldstring)) {
+ if (newlabel != NULL) {
+ free(tlab->string);
+ tlab->string = stringcopy(newlabel->string);
+ rval++;
+ }
+ }
+ }
+ }
+ return rval;
+}
+
+/*----------------------------------------------------------------------*/
+/* Xt wrapper for swapschem() */
+/*----------------------------------------------------------------------*/
+
+void xlib_swapschem(xcWidget w, pointertype mode, caddr_t calldata)
+{
+ swapschem((int)mode, -1, NULL);
+}
+
+/*----------------------------------------------------------------------*/
+/* Swap object schematic and symbol pages. */
+/* allow_create = 0 disallows creation of a new schematic or symbol; */
+/* i.e., if there is no corresponding schematic/symbol, nothing */
+/* happens. */
+/*----------------------------------------------------------------------*/
+
+void swapschem(int allow_create, int libnum, char *fullname)
+{
+ objectptr savepage = topobject;
+ labelptr *pinlab;
+ genericptr *plab;
+ Boolean lflag;
+ pushlistptr stacktop;
+ short loclibnum = libnum;
+ char *canonname;
+
+ if (libnum == -1) loclibnum = USERLIB - LIBRARY;
+
+ /* Create symbol or schematic, if allowed by allow_create */
+
+ if ((topobject->symschem == NULL) && (allow_create != 0)
+ && (topobject->schemtype != SECONDARY)) {
+
+ if (topobject->schemtype != PRIMARY) {
+ int tpage;
+
+ /* create a new page for the new schematic */
+
+ for (tpage = 0; tpage < xobjs.pages; tpage++)
+ if (xobjs.pagelist[tpage]->pageinst == NULL) break;
+
+ /* Push the current instance onto the push stack */
+ /* Change the page without destroying the pushlist */
+
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+ stacktop = areawin->stack;
+ areawin->stack = NULL;
+ changepage(tpage);
+ areawin->stack = stacktop;
+ }
+ else {
+ objectptr *newobject;
+
+ /* create a new library object for the new symbol */
+
+ xobjs.userlibs[loclibnum].library = (objectptr *)
+ realloc(xobjs.userlibs[loclibnum].library,
+ ++xobjs.userlibs[loclibnum].number * sizeof(objectptr));
+ newobject = xobjs.userlibs[loclibnum].library
+ + xobjs.userlibs[loclibnum].number - 1;
+ *newobject = (objectptr) malloc(sizeof(object));
+ initmem(*newobject);
+ (*newobject)->schemtype = SYMBOL;
+ (*newobject)->hidden = False;
+
+ incr_changes(*newobject);
+
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE)
+ standard_element_delete(ERASE);
+
+ /* Generate a library instance for this object and set the */
+ /* top instance to point to it. */
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+ areawin->topinstance = addtoinstlist(loclibnum, *newobject, FALSE);
+
+ /* Generate the default bounding box for a size-zero object */
+ calcbbox(areawin->topinstance);
+ }
+
+ /* set links between the two objects */
+
+ savepage->symschem = topobject;
+ topobject->symschem = savepage;
+
+ /* Make the name of the new object equal to that of the old, */
+ /* except that symbols get the full name while schematics */
+ /* get the canonical name (without the technology prefix) */
+
+ if (fullname == NULL)
+ canonname = GetCanonicalName(savepage->name);
+ else {
+ canonname = strstr(fullname, "::");
+ if ((canonname == NULL) || (topobject->schemtype != PRIMARY))
+ canonname = fullname;
+ else
+ canonname += 2;
+ }
+ strcpy(topobject->name, canonname);
+ checkname(topobject);
+
+ /* copy all pin labels into the new object */
+
+ for (plab = savepage->plist; plab < savepage->plist + savepage->parts;
+ plab++) {
+ if (IS_LABEL(*plab)) {
+ genericptr *tgen;
+ labelptr tlab, lpin = (labelptr)*plab;
+
+ if (lpin->pin == LOCAL) {
+
+ /* Only make one copy of each pin name */
+
+ lflag = False;
+ for (tgen = topobject->plist; tgen <
+ topobject->plist + topobject->parts; tgen++) {
+ if (IS_LABEL(*tgen)) {
+ tlab = TOLABEL(tgen);
+ if (!stringcomp(tlab->string, lpin->string)) lflag = True;
+ }
+ }
+ if (lflag == True) continue;
+
+ NEW_LABEL(pinlab, topobject);
+ (*pinlab)->pin = lpin->pin;
+ (*pinlab)->color = lpin->color;
+ (*pinlab)->rotation = 0;
+ (*pinlab)->scale = 1.0;
+ (*pinlab)->justify = areawin->justify;
+ (*pinlab)->position.x = 0;
+ (*pinlab)->position.y = topobject->parts * (TEXTHEIGHT + 10);
+ (*pinlab)->passed = NULL;
+ u2u_snap(&((*pinlab)->position));
+ (*pinlab)->string = stringcopy(lpin->string);
+ incr_changes(topobject);
+ }
+ }
+ }
+ calcbbox(areawin->topinstance);
+
+ /* Recreate the user library with the new symbol */
+ if (savepage->schemtype != SYMBOL) composelib(loclibnum + LIBRARY);
+ }
+ else if (topobject->symschem != NULL) {
+
+ /* If symschem matches the last entry on the push stack, then we */
+ /* pop; otherwise, we push. */
+
+ if (areawin->stack && areawin->stack->thisinst->thisobject
+ == topobject->symschem) {
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = areawin->stack->thisinst;
+ pop_stack(&areawin->stack);
+ }
+ else {
+ int p;
+ objinstptr syminst = NULL;
+ liblistptr symlist;
+
+ /* If symschem is a schematic, find the appropriate page */
+
+ for (p = 0; p < xobjs.pages; p++) {
+ syminst = xobjs.pagelist[p]->pageinst;
+ if (syminst != NULL)
+ if (syminst->thisobject == topobject->symschem)
+ break;
+ }
+ if (p == xobjs.pages) {
+
+ /* If symschem is a symbol, and it wasn't on the push stack, */
+ /* get the library default symbol and go there. */
+
+ for (p = 0; p < xobjs.numlibs; p++) {
+ for (symlist = xobjs.userlibs[p].instlist; symlist != NULL;
+ symlist = symlist->next) {
+ syminst = symlist->thisinst;
+ if (syminst->thisobject == topobject->symschem &&
+ symlist->virtual == FALSE)
+ break;
+ }
+ if (symlist != NULL) break;
+ }
+ if (p == xobjs.numlibs) {
+ Fprintf(stderr, "swapschem(): BAD SYMSCHEM\n");
+ return;
+ }
+ }
+
+ if (eventmode == MOVE_MODE || eventmode == COPY_MODE)
+ delete_for_xfer(NORMAL, areawin->selectlist, areawin->selects);
+
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ push_stack(&areawin->stack, areawin->topinstance, NULL);
+ areawin->topinstance = syminst;
+ }
+ }
+
+ /* If there was no action, then there is nothing more to do. */
+
+ if (topobject == savepage) return;
+
+ setpage(TRUE);
+ transferselects();
+ refresh(NULL, NULL, NULL);
+ setsymschem();
+}
+
+#ifndef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Wrapper for swapschem() when generating a new symbol. */
+/*----------------------------------------------------------------------*/
+
+void makesymbol(xcWidget w, caddr_t calldata)
+{
+ /* copy name from popup prompt buffer and check */
+
+ swapschem(1, -1, _STR2);
+}
+
+/*----------------------------------------------------------------------*/
+/* Check name before doing a swap: If name begins with "Page", prompt */
+/* for the object name, as you would when doing selectsave(). */
+/*----------------------------------------------------------------------*/
+
+void dobeforeswap(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *popdata = (buttonsave *)malloc(sizeof(buttonsave));
+
+ /* Check for requirement to change the name before creating the symbol */
+
+ if ((topobject->symschem == NULL) && (topobject->schemtype == PRIMARY)
+ && (strstr(topobject->name, "Page ") != NULL)) {
+
+ /* Get a name for the new object */
+
+ eventmode = NORMAL_MODE;
+ popdata->dataptr = NULL;
+ popdata->button = NULL; /* indicates that no button is assc'd w/ the popup */
+ popupprompt(w, "Enter name for new object:", "\0", makesymbol, popdata, NULL);
+ }
+ else
+ swapschem(1, -1, NULL);
+}
+
+#endif /* !TCL_WRAPPER */
+
+/*------------------------------------------*/
+/* Disassociate a symbol from its schematic */
+/*------------------------------------------*/
+
+void schemdisassoc()
+{
+ if (eventmode != NORMAL) {
+ Wprintf("Cannot disassociate schematics in this mode");
+ }
+ else {
+ topobject->symschem->symschem = NULL;
+ topobject->symschem = NULL;
+ setsymschem();
+ Wprintf("Schematic and symbol are now unlinked.");
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Schematic<-->symbol association. Determine whether action */
+/* acts on a symbol or a schematic from context. */
+/* mode == 0 associate only. */
+/* mode == 1 determine action (associate or disassociate) from */
+/* context (toggle) */
+/*--------------------------------------------------------------*/
+
+void startschemassoc(xcWidget w, pointertype mode, caddr_t calldata)
+{
+ if ((topobject->symschem != NULL) && (mode == 1))
+ schemdisassoc();
+ else if ((topobject->symschem != NULL) && (mode == 0)) {
+ Wprintf("Refusing to undo current association.");
+ }
+ else if (topobject->schemtype == SECONDARY) {
+ Wprintf("Cannot attach symbol to a secondary schematic page.");
+ }
+ else {
+ eventmode = ASSOC_MODE;
+ if (topobject->schemtype == PRIMARY) {
+ /* Find a symbol to associate */
+ startcatalog(w, LIBLIB, NULL);
+ Wprintf("Select library page, then symbol to associate.");
+ }
+ else {
+ /* Find a schematic (page) to associate */
+ startcatalog(w, PAGELIB, NULL);
+ Wprintf("Select schematic page to associate.");
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Callback procedures on the schematic/symbol buttons. */
+/*--------------------------------------------------------------*/
+
+Boolean schemassoc(objectptr schemobj, objectptr symbolobj)
+{
+ if (schemobj->symschem != NULL || symbolobj->symschem != NULL) {
+ Wprintf("Both objects must be disassociated first.");
+#if TCL_WRAPPER
+ Tcl_SetResult(xcinterp, "Both objects must be disassociated first.", NULL);
+#endif
+ return False;
+ }
+ else {
+ schemobj->symschem = symbolobj;
+ symbolobj->symschem = schemobj;
+ if (symbolobj->schemtype == TRIVIAL)
+ symbolobj->schemtype = SYMBOL;
+
+ /* Schematic takes the name of its associated symbol, by default */
+ /* Don't copy any technology prefix. */
+ strcpy(schemobj->name, GetCanonicalName(symbolobj->name));
+
+ /* Ensure that schematic (page) name is unique */
+ while (checkpagename(schemobj) < 0);
+ setsymschem(); /* Set buttons and menu items appropriately */
+ }
+ return True;
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/selection.c b/selection.c
new file mode 100644
index 0000000..e500f7b
--- /dev/null
+++ b/selection.c
@@ -0,0 +1,1761 @@
+/*-------------------------------------------------------------------------*/
+/* selection.c --- xcircuit routines handling element selection etc. */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/13/93 */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#endif
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Local includes */
+/*-------------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "colordefs.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Exported Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern int *appcolors;
+extern Cursor appcursors[NUM_CURSORS];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern char _STR[150];
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Prevent a list of elements from being selected. */
+/*----------------------------------------------------------------------*/
+
+void disable_selects(objectptr thisobject, short *selectlist, int selects)
+{
+ genericptr genptr;
+ short *i;
+
+ for (i = selectlist; i < selectlist + selects; i++) {
+ genptr = *(thisobject->plist + *i);
+ genptr->type |= SELECT_HIDE;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Allow a list of elements to be selected, if they were disabled using */
+/* the disable_selects() routine. */
+/*----------------------------------------------------------------------*/
+
+void enable_selects(objectptr thisobject, short *selectlist, int selects)
+{
+ genericptr genptr;
+ short *i;
+
+ for (i = selectlist; i < selectlist + selects; i++) {
+ genptr = *(thisobject->plist + *i);
+ genptr->type &= ~(SELECT_HIDE);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Change filter to determine what types can be selected */
+/*----------------------------------------------------------------------*/
+
+void selectfilter(xcWidget w, pointertype value, caddr_t calldata)
+{
+ short bitwise = (short)value;
+ Boolean bval = (areawin->filter & bitwise) ? True : False;
+
+ if (bval)
+ areawin->filter &= ~bitwise;
+ else
+ areawin->filter |= bitwise;
+
+#ifndef TCL_WRAPPER
+ toggle(w, (pointertype)&bval, calldata);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/* Look at select stack to see if there are any selects; call select, */
+/* if not. If draw_selected is True, then the selected items are drawn */
+/* in the select color. Otherwise, they are not redrawn. */
+/*----------------------------------------------------------------------*/
+
+Boolean checkselect_draw(short value, Boolean draw_selected)
+{
+ short *check, savemode;
+
+ value &= areawin->filter; /* apply the selection filter */
+
+ if (areawin->selects == 0) {
+ savemode = eventmode;
+ if (!draw_selected) eventmode = PENDING_MODE;
+ select_element(value);
+ eventmode = savemode;
+ }
+ if (areawin->selects == 0) return False;
+ for (check = areawin->selectlist; check < areawin->selectlist +
+ areawin->selects; check++)
+ if (SELECTTYPE(check) & value) break;
+ if (check == areawin->selectlist + areawin->selects) return False;
+ else return True;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Look at select stack to see if there are any selects; call select, if not. */
+/*----------------------------------------------------------------------------*/
+
+Boolean checkselect(short value)
+{
+ return checkselect_draw(value, False);
+}
+
+/*--------------------------------------------------------------*/
+/* Select list numbering revision when an element is deleted */
+/* from an object. */
+/*--------------------------------------------------------------*/
+
+void reviseselect(short *slist, int selects, short *removed)
+{
+ short *chkselect;
+
+ for (chkselect = slist; chkselect < slist + selects; chkselect++)
+ if (*chkselect > *removed) (*chkselect)--;
+}
+
+/*----------------------*/
+/* Draw a selected item */
+/*----------------------*/
+
+void geneasydraw(short instance, int mode, objectptr curobj, objinstptr curinst)
+{
+ genericptr elementptr = *(curobj->plist + instance);
+
+ // Note: Setting areawin->clipped to -1 prevents the clipmask from being
+ // applied to elements,
+ areawin->clipped = -1;
+
+ switch (ELEMENTTYPE(*(curobj->plist + instance))) {
+ case ARC:
+ UDrawArc((arcptr)elementptr, xobjs.pagelist[areawin->page]->wirewidth);
+ break;
+ case POLYGON:
+ UDrawPolygon((polyptr)elementptr, xobjs.pagelist[areawin->page]->wirewidth);
+ break;
+ case SPLINE:
+ UDrawSpline((splineptr)elementptr, xobjs.pagelist[areawin->page]->wirewidth);
+ break;
+ case PATH:
+ UDrawPath((pathptr)elementptr, xobjs.pagelist[areawin->page]->wirewidth);
+ break;
+ case LABEL:
+ UDrawString((labelptr)elementptr, mode, curinst);
+ break;
+ case OBJINST:
+ UDrawObject((objinstptr)elementptr, SINGLE, mode,
+ xobjs.pagelist[areawin->page]->wirewidth, NULL);
+ break;
+ case GRAPHIC:
+ UDrawGraphic((graphicptr)elementptr);
+ break;
+ }
+ areawin->clipped = 0;
+}
+
+/*-------------------------------------------------*/
+/* Draw a selected item, including selection color */
+/*-------------------------------------------------*/
+
+void gendrawselected(short *newselect, objectptr curobj, objinstptr curinst)
+{
+ /* Don't draw selection color when selecting for edit */
+ if (eventmode == PENDING_MODE) return;
+
+ if (*newselect >= curobj->parts) return; // Safety check
+
+ XcSetFunction(GXcopy);
+ XcSetForeground(BACKGROUND);
+ geneasydraw(*newselect, DOFORALL, curobj, curinst);
+ indicateparams(*(curobj->plist + *newselect));
+
+ XcSetFunction(GXxor);
+ XcSetForeground(SELECTCOLOR ^ BACKGROUND);
+ geneasydraw(*newselect, DOFORALL, curobj, curinst);
+
+ SetForeground(dpy, areawin->gc, AUXCOLOR ^ BACKGROUND);
+ indicateparams(*(curobj->plist + *newselect));
+
+ SetForeground(dpy, areawin->gc, areawin->gccolor);
+ SetFunction(dpy, areawin->gc, areawin->gctype);
+}
+
+/*---------------------------------------------------*/
+/* Allocate or reallocate memory for a new selection */
+/*---------------------------------------------------*/
+
+short *allocselect()
+{
+ short *newselect;
+
+ if (areawin->selects == 0)
+ areawin->selectlist = (short *) malloc(sizeof(short));
+ else
+ areawin->selectlist = (short *) realloc(areawin->selectlist,
+ (areawin->selects + 1) * sizeof(short));
+
+ newselect = areawin->selectlist + areawin->selects;
+ areawin->selects++;
+
+ return newselect;
+}
+
+/*-------------------------------------------------*/
+/* Set Options menu according to 1st selection */
+/*-------------------------------------------------*/
+
+void setoptionmenu()
+{
+ short *mselect;
+ labelptr mlabel;
+
+ if (areawin->selects == 0) {
+ setallstylemarks(areawin->style);
+ setcolormark(areawin->color);
+ setdefaultfontmarks();
+ setparammarks(NULL);
+ return;
+ }
+
+ for (mselect = areawin->selectlist; mselect < areawin->selectlist +
+ areawin->selects; mselect++) {
+ setcolormark(SELTOCOLOR(mselect));
+ setparammarks(SELTOGENERIC(mselect));
+ switch(SELECTTYPE(mselect)) {
+ case ARC:
+ setallstylemarks(SELTOARC(mselect)->style);
+ return;
+ case POLYGON:
+ setallstylemarks(SELTOPOLY(mselect)->style);
+ return;
+ case SPLINE:
+ setallstylemarks(SELTOSPLINE(mselect)->style);
+ return;
+ case PATH:
+ setallstylemarks(SELTOPATH(mselect)->style);
+ return;
+ case LABEL:
+ mlabel = SELTOLABEL(mselect);
+ setfontmarks(mlabel->string->data.font, mlabel->justify);
+ return;
+ }
+ }
+}
+
+/*-------------------------------------*/
+/* Test of point being inside of a box */
+/*-------------------------------------*/
+
+int test_insideness(int tx, int ty, XPoint *boxpoints)
+{
+ int i, stval = 0;
+ XPoint *pt1, *pt2;
+ int stdir;
+
+ for (i = 0; i < 4; i++) {
+ pt1 = boxpoints + i;
+ pt2 = boxpoints + ((i + 1) % 4);
+ stdir = (pt2->x - pt1->x) * (ty - pt1->y)
+ - (pt2->y - pt1->y) * (tx - pt1->x);
+ stval += sign(stdir);
+ }
+ return (abs(stval) == 4) ? 1 : 0;
+}
+
+/*--------------------------------------------*/
+/* Search for selection among path components */
+/*--------------------------------------------*/
+
+#define RANGE_NARROW 11.5
+#define RANGE_WIDE 50
+
+Boolean pathselect(genericptr *curgen, short class, float range)
+{
+ /*----------------------------------------------------------------------*/
+ /* wirelim is the distance, in user-space units, at which an element is */
+ /* considered for selection. */
+ /* */
+ /* wirelim = A + B / (scale + C) */
+ /* */
+ /* where A = minimum possible distance (expands range at close scale) */
+ /* C = minimum possible scale (contract range at far scale) */
+ /* B makes wirelim approx. 25 at default scale of 0.5, which */
+ /* is an empirical result. */
+ /*----------------------------------------------------------------------*/
+
+ float wirelim = 2 + range / (areawin->vscale + 0.05);
+ long sqrwirelim = (int)(wirelim * wirelim);
+
+ long newdist;
+ Boolean selected = False;
+
+ class &= areawin->filter; /* apply the selection filter */
+
+ if ((*curgen)->type == (class & ARC)) {
+
+ /* look among the arcs */
+
+ fpointlist currentpt;
+ XPoint nearpt[3];
+
+ nearpt[2].x = nearpt[0].x = (short)(TOARC(curgen)->points[0].x);
+ nearpt[2].y = nearpt[0].y = (short)(TOARC(curgen)->points[0].y);
+ for (currentpt = TOARC(curgen)->points + 1; currentpt < TOARC(curgen)->points
+ + TOARC(curgen)->number; currentpt++) {
+ nearpt[1].x = nearpt[0].x;
+ nearpt[1].y = nearpt[0].y;
+ nearpt[0].x = (short)(currentpt->x);
+ nearpt[0].y = (short)(currentpt->y);
+ newdist = finddist(&nearpt[0], &nearpt[1], &areawin->save);
+ if (newdist <= sqrwirelim) break;
+ }
+ if ((!(TOARC(curgen)->style & UNCLOSED)) && (newdist > sqrwirelim))
+ newdist = finddist(&nearpt[0], &nearpt[2], &areawin->save);
+
+ if (newdist <= sqrwirelim) selected = True;
+ }
+
+ else if ((*curgen)->type == (class & SPLINE)) {
+
+ /* look among the splines --- look at polygon representation */
+
+ fpointlist currentpt;
+ XPoint nearpt[2];
+
+ nearpt[0].x = (short)(TOSPLINE(curgen)->points[0].x);
+ nearpt[0].y = (short)(TOSPLINE(curgen)->points[0].y);
+ newdist = finddist(&(TOSPLINE(curgen)->ctrl[0]), &(nearpt[0]),
+ &areawin->save);
+ if (newdist > sqrwirelim) {
+ for (currentpt = TOSPLINE(curgen)->points; currentpt <
+ TOSPLINE(curgen)->points + INTSEGS; currentpt++) {
+ nearpt[1].x = nearpt[0].x;
+ nearpt[1].y = nearpt[0].y;
+ nearpt[0].x = (short)(currentpt->x);
+ nearpt[0].y = (short)(currentpt->y);
+ newdist = finddist(&nearpt[0], &nearpt[1], &areawin->save);
+ if (newdist <= sqrwirelim) break;
+ }
+ if (newdist > sqrwirelim) {
+ newdist = finddist(&nearpt[0], &(TOSPLINE(curgen)->ctrl[3]),
+ &areawin->save);
+ if ((!(TOSPLINE(curgen)->style & UNCLOSED)) && (newdist > sqrwirelim))
+ newdist = finddist(&(TOSPLINE(curgen)->ctrl[0]),
+ &(TOSPLINE(curgen)->ctrl[3]), &areawin->save);
+ }
+ }
+
+ if (newdist <= sqrwirelim) selected = True;
+ }
+
+ else if ((*curgen)->type == (class & POLYGON)) {
+
+ /* finally, look among the polygons */
+
+ pointlist currentpt;
+
+ for (currentpt = TOPOLY(curgen)->points; currentpt < TOPOLY(curgen)
+ ->points + TOPOLY(curgen)->number - 1; currentpt++) {
+ newdist = finddist(currentpt, currentpt + 1, &areawin->save);
+ if (newdist <= sqrwirelim) break;
+ }
+ if ((!(TOPOLY(curgen)->style & UNCLOSED)) && (newdist > sqrwirelim))
+ newdist = finddist(currentpt, TOPOLY(curgen)->points,
+ &areawin->save);
+
+ if (newdist <= sqrwirelim) selected = True;
+ }
+ return selected;
+}
+
+/*------------------------------------------------------*/
+/* Check to see if any selection has registered cycles */
+/*------------------------------------------------------*/
+
+Boolean checkforcycles(short *selectlist, int selects)
+{
+ genericptr pgen;
+ pointselect *cycptr;
+ short *ssel;
+
+ for (ssel = selectlist; ssel < selectlist + selects; ssel++) {
+ pgen = SELTOGENERIC(ssel);
+ switch(pgen->type) {
+ case POLYGON:
+ cycptr = ((polyptr)pgen)->cycle;
+ break;
+ case ARC:
+ cycptr = ((arcptr)pgen)->cycle;
+ break;
+ case SPLINE:
+ cycptr = ((splineptr)pgen)->cycle;
+ break;
+ case LABEL:
+ cycptr = ((labelptr)pgen)->cycle;
+ break;
+ }
+ if (cycptr != NULL)
+ if (cycptr->number != -1)
+ return True;
+ }
+ return False;
+}
+
+/*--------------------------------------------------------------*/
+/* Copy a cycle selection list from one element to another */
+/*--------------------------------------------------------------*/
+
+void copycycles(pointselect **new, pointselect **old)
+{
+ pointselect *pptr;
+ short cycles = 0;
+
+ if (*old == NULL) {
+ *new = NULL;
+ return;
+ }
+
+ for (pptr = *old; !(pptr->flags & LASTENTRY); pptr++, cycles++);
+ cycles += 2;
+ *new = (pointselect *)malloc(cycles * sizeof(pointselect));
+ memcpy(*new, *old, cycles * sizeof(pointselect));
+}
+
+/*--------------------------------------------------------------*/
+/* Create a selection record of selected points in an element. */
+/* If a record already exists, and "cycle" is not already in */
+/* the list, add it. */
+/* "flags" may be set to EDITX or EDITY. If "flags" is zero, */
+/* then flags = EDITX | EDITY is assumed. */
+/*--------------------------------------------------------------*/
+
+pointselect *addcycle(genericptr *pgen, short cycle, u_char flags)
+{
+ polyptr ppoly;
+ arcptr parc;
+ splineptr pspline;
+ labelptr plabel;
+ pointselect *pptr, **cycptr;
+ short cycles = 0;
+
+ switch((*pgen)->type) {
+ case POLYGON:
+ ppoly = TOPOLY(pgen);
+ cycptr = &ppoly->cycle;
+ break;
+ case ARC:
+ parc = TOARC(pgen);
+ cycptr = &parc->cycle;
+ break;
+ case SPLINE:
+ pspline = TOSPLINE(pgen);
+ cycptr = &pspline->cycle;
+ break;
+ case LABEL:
+ plabel = TOLABEL(pgen);
+ cycptr = &plabel->cycle;
+ break;
+ }
+
+ switch((*pgen)->type) {
+ case POLYGON:
+ case ARC:
+ case SPLINE:
+ case LABEL: // To-do: Handle labels separately
+
+ if (*cycptr == NULL) {
+ *cycptr = (pointselect *)malloc(sizeof(pointselect));
+ pptr = *cycptr;
+ pptr->number = cycle;
+ pptr->flags = (flags == 0) ? EDITX | EDITY : flags;
+ pptr->flags |= LASTENTRY;
+ }
+ else {
+ for (pptr = *cycptr; !(pptr->flags & LASTENTRY); pptr++, cycles++) {
+ if (pptr->number == cycle)
+ break;
+ pptr->flags &= ~LASTENTRY;
+ }
+ if (pptr->number != cycle) {
+ pptr->flags &= ~LASTENTRY;
+ *cycptr = (pointselect *)realloc(*cycptr,
+ (cycles + 2) * sizeof(pointselect));
+ pptr = *cycptr + cycles + 1;
+ pptr->number = cycle;
+ pptr->flags = (flags == 0) ? EDITX | EDITY : flags;
+ pptr->flags |= LASTENTRY;
+ }
+ else {
+ pptr->flags |= (flags == 0) ? EDITX | EDITY : flags;
+ }
+ }
+ break;
+ }
+ return pptr;
+}
+
+/*--------------------------------------------------------------*/
+/* If we edit the position of a control point, and the global */
+/* pathedit mode is set to TANGENTS, then we track the angle of */
+/* the adjoining curve, if there is one, by settings its cycle */
+/* flags to ANTIXY. */
+/*--------------------------------------------------------------*/
+
+void addanticycle(pathptr thispath, splineptr thisspline, short cycle)
+{
+ genericptr *ggen, *rgen;
+ splineptr otherspline;
+
+ if (areawin->pathedit == TANGENTS) {
+ for (ggen = thispath->plist; ggen < thispath->plist + thispath->parts;
+ ggen++)
+ if (*ggen == (genericptr)thisspline) break;
+
+ if (*ggen != (genericptr)thisspline) return; /* Something went wrong */
+
+ if (cycle == 1) {
+ if (ggen > thispath->plist) {
+ if (ELEMENTTYPE(*(ggen - 1)) == SPLINE) {
+ addcycle(ggen - 1, 2, ANTIXY);
+ }
+ }
+ else if (!(thispath->style & UNCLOSED)) {
+ rgen = thispath->plist + thispath->parts - 1;
+ if (ELEMENTTYPE(*rgen) == SPLINE) {
+ otherspline = TOSPLINE(rgen);
+ if (thisspline->ctrl[0].x == otherspline->ctrl[3].x &&
+ thisspline->ctrl[0].y == otherspline->ctrl[3].y)
+ addcycle(rgen, 2, ANTIXY);
+ }
+ }
+ }
+ else if (cycle == 2) { /* cycle should be only 1 or 2 */
+ if (ggen < thispath->plist + thispath->parts - 1) {
+ if (ELEMENTTYPE(*(ggen + 1)) == SPLINE) {
+ addcycle(ggen + 1, 1, ANTIXY);
+ }
+ }
+ else if (!(thispath->style & UNCLOSED)) {
+ rgen = thispath->plist;
+ if (ELEMENTTYPE(*rgen) == SPLINE) {
+ otherspline = TOSPLINE(rgen);
+ if (thisspline->ctrl[3].x == otherspline->ctrl[0].x &&
+ thisspline->ctrl[3].y == otherspline->ctrl[0].y)
+ addcycle(rgen, 1, ANTIXY);
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Find the cycle numbered "cycle", and mark it as the */
+/* reference point. */
+/*--------------------------------------------------------------*/
+
+void makerefcycle(pointselect *cycptr, short cycle)
+{
+ pointselect *pptr, *sptr;
+
+ for (pptr = cycptr;; pptr++) {
+ if (pptr->flags & REFERENCE) {
+ pptr->flags &= ~REFERENCE;
+ break;
+ }
+ if (pptr->flags & LASTENTRY) break;
+ }
+
+ for (sptr = cycptr;; sptr++) {
+ if (sptr->number == cycle) {
+ sptr->flags |= REFERENCE;
+ break;
+ }
+ if (sptr->flags & LASTENTRY) break;
+ }
+
+ /* If something went wrong, revert to the original reference */
+
+ if (!(sptr->flags & REFERENCE)) {
+ pptr->flags |= REFERENCE;
+ }
+}
+
+/* Original routine, used 1st entry as reference (deprecated) */
+
+void makefirstcycle(pointselect *cycptr, short cycle)
+{
+ pointselect *pptr, tmpp;
+
+ for (pptr = cycptr;; pptr++) {
+ if (pptr->number == cycle) {
+ /* swap with first entry */
+ tmpp = *cycptr;
+ *cycptr = *pptr;
+ *pptr = tmpp;
+ if (cycptr->flags & LASTENTRY) {
+ cycptr->flags &= ~LASTENTRY;
+ pptr->flags |= LASTENTRY;
+ }
+ return;
+ }
+ if (pptr->flags & LASTENTRY) break;
+ }
+}
+
+/*------------------------------------------------------------------------------*/
+/* Advance a cycle (point) selection from value "cycle" to value "newvalue" */
+/* If "newvalue" is < 0 then remove the cycle. */
+/* */
+/* If there is only one cycle point on the element, then advance its point */
+/* number. If there are multiple points on the element, then change the */
+/* reference point by moving the last item in the list to the front. */
+/*------------------------------------------------------------------------------*/
+
+void advancecycle(genericptr *pgen, short newvalue)
+{
+ polyptr ppoly;
+ arcptr parc;
+ splineptr pspline;
+ labelptr plabel;
+ pointselect *pptr, *endptr, *fcycle, **cycptr, tmpcyc;
+ short cycles = 0;
+
+ if (newvalue < 0) {
+ removecycle(pgen);
+ return;
+ }
+
+ switch((*pgen)->type) {
+ case POLYGON:
+ ppoly = TOPOLY(pgen);
+ cycptr = &ppoly->cycle;
+ break;
+ case ARC:
+ parc = TOARC(pgen);
+ cycptr = &parc->cycle;
+ break;
+ case SPLINE:
+ pspline = TOSPLINE(pgen);
+ cycptr = &pspline->cycle;
+ break;
+ case LABEL:
+ plabel = TOLABEL(pgen);
+ cycptr = &plabel->cycle;
+ break;
+ }
+ if (*cycptr == NULL) return;
+
+ /* Remove any cycles that have only X or Y flags set. */
+ /* "Remove" them by shuffling them to the end of the list, */
+ /* and marking the one in front as the last entry. */
+
+ for (endptr = *cycptr; !(endptr->flags & LASTENTRY); endptr++);
+ pptr = *cycptr;
+ while (pptr < endptr) {
+ if ((pptr->flags & (EDITX | EDITY)) != (EDITX | EDITY)) {
+ tmpcyc = *endptr;
+ *endptr = *pptr;
+ *pptr = tmpcyc;
+ pptr->flags &= ~LASTENTRY;
+ pptr->number = -1;
+ endptr--;
+ endptr->flags |= LASTENTRY;
+ }
+ else
+ pptr++;
+ }
+
+ if (pptr->flags & LASTENTRY) {
+ if ((pptr->flags & (EDITX | EDITY)) != (EDITX | EDITY)) {
+ pptr->flags &= ~LASTENTRY;
+ pptr->number = -1;
+ endptr--;
+ endptr->flags |= LASTENTRY;
+ }
+ }
+
+ /* Now advance the cycle */
+
+ pptr = *cycptr;
+ if (pptr->flags & LASTENTRY) {
+ pptr->number = newvalue;
+ }
+ else {
+ fcycle = *cycptr;
+ for (pptr = fcycle + 1;; pptr++) {
+ if (pptr->flags & (EDITX | EDITY))
+ fcycle = pptr;
+ if (pptr->flags & LASTENTRY) break;
+ }
+ makerefcycle(*cycptr, fcycle->number);
+ }
+}
+
+/*--------------------------------------*/
+/* Remove a cycle (point) selection */
+/*--------------------------------------*/
+
+void removecycle(genericptr *pgen)
+{
+ polyptr ppoly;
+ pathptr ppath;
+ arcptr parc;
+ splineptr pspline;
+ labelptr plabel;
+ pointselect *pptr, **cycptr = NULL;
+ genericptr *pathgen;
+
+ switch((*pgen)->type) {
+ case POLYGON:
+ ppoly = TOPOLY(pgen);
+ cycptr = &ppoly->cycle;
+ break;
+ case ARC:
+ parc = TOARC(pgen);
+ cycptr = &parc->cycle;
+ break;
+ case SPLINE:
+ pspline = TOSPLINE(pgen);
+ cycptr = &pspline->cycle;
+ break;
+ case LABEL:
+ plabel = TOLABEL(pgen);
+ cycptr = &plabel->cycle;
+ break;
+ case PATH:
+ ppath = TOPATH(pgen);
+ for (pathgen = ppath->plist; pathgen < ppath->plist + ppath->parts;
+ pathgen++)
+ removecycle(pathgen);
+ break;
+ }
+ if (cycptr == NULL) return;
+ if (*cycptr == NULL) return;
+ free(*cycptr);
+ *cycptr = NULL;
+}
+
+/*--------------------------------------*/
+/* Remove cycles from all parts of a */
+/* path other than the one passed */
+/*--------------------------------------*/
+
+void removeothercycles(pathptr ppath, genericptr pathpart)
+{
+ genericptr *pathgen;
+ for (pathgen = ppath->plist; pathgen < ppath->plist + ppath->parts;
+ pathgen++)
+ if (*pathgen != pathpart)
+ removecycle(pathgen);
+}
+
+/*--------------------------------------*/
+/* Select one of the elements on-screen */
+/*--------------------------------------*/
+
+selection *genselectelement(short class, u_char mode, objectptr selobj,
+ objinstptr selinst)
+{
+ selection *rselect = NULL;
+ /* short *newselect; (jdk) */
+ genericptr *curgen;
+ XPoint newboxpts[4];
+ Boolean selected;
+ float range = RANGE_NARROW;
+
+ if (mode == MODE_RECURSE_WIDE)
+ range = RANGE_WIDE;
+
+ /* Loop through all elements found underneath the cursor */
+
+ for (curgen = selobj->plist; curgen < selobj->plist + selobj->parts; curgen++) {
+
+ selected = False;
+
+ /* Check among polygons, arcs, and curves */
+
+ if (((*curgen)->type == (class & POLYGON)) ||
+ ((*curgen)->type == (class & ARC)) ||
+ ((*curgen)->type == (class & SPLINE))) {
+ selected = pathselect(curgen, class, range);
+ }
+
+ else if ((*curgen)->type == (class & LABEL)) {
+
+ /* Look among the labels */
+
+ labelptr curlab = TOLABEL(curgen);
+
+ /* Don't select temporary labels from schematic capture system */
+ if (curlab->string->type != FONT_NAME) continue;
+
+ labelbbox(curlab, newboxpts, selinst);
+
+ /* Need to check for zero-size boxes or test_insideness() */
+ /* fails. Zero-size boxes happen when labels are parameters */
+ /* set to a null string. */
+
+ if ((newboxpts[0].x != newboxpts[1].x) || (newboxpts[0].y !=
+ newboxpts[1].y)) {
+
+ /* check for point inside bounding box, as for objects */
+
+ selected = test_insideness(areawin->save.x, areawin->save.y,
+ newboxpts);
+ if (selected) areawin->textpos = areawin->textend = 0;
+ }
+ }
+
+ else if ((*curgen)->type == (class & GRAPHIC)) {
+
+ /* Look among the graphic images */
+
+ graphicptr curg = TOGRAPHIC(curgen);
+ graphicbbox(curg, newboxpts);
+
+ /* check for point inside bounding box, as for objects */
+ selected = test_insideness(areawin->save.x, areawin->save.y,
+ newboxpts);
+ }
+
+ else if ((*curgen)->type == (class & PATH)) {
+
+ /* Check among the paths */
+
+ genericptr *pathp;
+
+ /* Accept path if any subcomponent of the path is accepted */
+
+ for (pathp = TOPATH(curgen)->plist; pathp < TOPATH(curgen)->plist +
+ TOPATH(curgen)->parts; pathp++)
+ if (pathselect(pathp, SPLINE|ARC|POLYGON, range)) {
+ selected = True;
+ break;
+ }
+ }
+
+ else if ((*curgen)->type == (class & OBJINST)) {
+
+ objinstbbox(TOOBJINST(curgen), newboxpts, range);
+
+ /* Look for an intersect of the boundingbox and pointer position. */
+ /* This is a simple matter of rotating the pointer position with */
+ /* respect to the origin of the bounding box segment, as if the */
+ /* segment were rotated to 0 degrees. The sign of the resulting */
+ /* point's y-position is the same for all bbox segments if the */
+ /* pointer position is inside the bounding box. */
+
+ selected = test_insideness(areawin->save.x, areawin->save.y,
+ newboxpts);
+ }
+
+ /* Add this object to the list of things found under the cursor */
+
+ if (selected) {
+ if (rselect == NULL) {
+ rselect = (selection *)malloc(sizeof(selection));
+ rselect->selectlist = (short *)malloc(sizeof(short));
+ rselect->selects = 0;
+ rselect->thisinst = selinst;
+ rselect->next = NULL;
+ }
+ else {
+ rselect->selectlist = (short *)realloc(rselect->selectlist,
+ (rselect->selects + 1) * sizeof(short));
+ }
+ *(rselect->selectlist + rselect->selects) = (short)(curgen -
+ selobj->plist);
+ rselect->selects++;
+ }
+ }
+ return rselect;
+}
+
+/*----------------------------------------------------------------*/
+/* select arc, curve, and polygon objects from a defined box area */
+/*----------------------------------------------------------------*/
+
+Boolean areaelement(genericptr *curgen, XPoint *boxpts, Boolean is_path, short level)
+{
+ Boolean selected;
+ pointlist currentpt;
+ short cycle;
+
+ switch(ELEMENTTYPE(*curgen)) {
+
+ case(ARC):
+ /* check center of arcs */
+
+ selected = test_insideness(TOARC(curgen)->position.x,
+ TOARC(curgen)->position.y, boxpts);
+ break;
+
+ case(POLYGON):
+ /* check each point of the polygons */
+
+ selected = False;
+ cycle = 0;
+ for (currentpt = TOPOLY(curgen)->points; currentpt <
+ TOPOLY(curgen)->points + TOPOLY(curgen)->number;
+ currentpt++, cycle++) {
+ if (test_insideness(currentpt->x, currentpt->y, boxpts)) {
+ selected = True;
+ if (level == 0) addcycle(curgen, cycle, 0);
+ }
+ }
+ break;
+
+ case(SPLINE):
+ /* check each control point of the spline */
+
+ selected = False;
+ if (test_insideness(TOSPLINE(curgen)->ctrl[0].x,
+ TOSPLINE(curgen)->ctrl[0].y, boxpts)) {
+ selected = True;
+ if (level == 0) addcycle(curgen, 0, 0);
+ }
+
+ if (test_insideness(TOSPLINE(curgen)->ctrl[3].x,
+ TOSPLINE(curgen)->ctrl[3].y, boxpts)) {
+ selected = True;
+ if (level == 0) addcycle(curgen, 3, 0);
+ }
+ break;
+ }
+ return selected;
+}
+
+/*--------------------------------------------*/
+/* select all objects from a defined box area */
+/*--------------------------------------------*/
+
+Boolean selectarea(objectptr selobj, XPoint *boxpts, short level)
+{
+ short *newselect;
+ genericptr *curgen, *pathgen;
+ Boolean selected;
+ stringpart *strptr;
+ int locpos, cx, cy, hwidth, hheight;
+ objinstptr curinst;
+ XPoint newboxpts[4];
+
+ if (selobj == topobject) {
+ areawin->textpos = areawin->textend = 0;
+ }
+
+ for (curgen = selobj->plist; curgen < selobj->plist + selobj->parts; curgen++) {
+
+ /* apply the selection filter */
+ if (!((*curgen)->type & areawin->filter)) continue;
+
+ switch(ELEMENTTYPE(*curgen)) {
+ case(OBJINST):
+ curinst = TOOBJINST(curgen);
+
+ /* An object instance is selected if any part of it is */
+ /* selected on a recursive area search. */
+
+ InvTransformPoints(boxpts, newboxpts, 4, curinst->position,
+ curinst->scale, curinst->rotation);
+ selected = selectarea(curinst->thisobject, newboxpts, level + 1);
+ break;
+
+ case(GRAPHIC):
+ /* check for graphic image center point inside area box */
+ selected = test_insideness(TOGRAPHIC(curgen)->position.x,
+ TOGRAPHIC(curgen)->position.y, boxpts);
+ break;
+
+ case(LABEL): {
+ XPoint adj;
+ labelptr slab = TOLABEL(curgen);
+ short j, state, isect, tmpl1, tmpl2;
+ TextExtents tmpext;
+
+ selected = False;
+
+ /* Ignore temporary labels created by the netlist generator */
+ if (slab->string->type != FONT_NAME) break;
+
+ /* Ignore info and pin labels that are not on the top level */
+ if ((selobj != topobject) && (slab->pin != False)) break;
+
+ /* translate select box into the coordinate system of the label */
+ InvTransformPoints(boxpts, newboxpts, 4, slab->position,
+ slab->scale, slab->rotation);
+
+ if (slab->pin) {
+ for (j = 0; j < 4; j++)
+ pinadjust(slab->justify, &(newboxpts[j].x),
+ &(newboxpts[j].y), -1);
+ }
+
+ tmpext = ULength(slab, areawin->topinstance, 0, NULL);
+ adj.x = (slab->justify & NOTLEFT ? (slab->justify & RIGHT ?
+ tmpext.maxwidth : tmpext.maxwidth >> 1) : 0);
+ adj.y = (slab->justify & NOTBOTTOM ? (slab->justify & TOP ?
+ tmpext.ascent : (tmpext.ascent + tmpext.base) >> 1)
+ : tmpext.base);
+
+ /* Label selection: For each character in the label string, */
+ /* do an insideness test with the select box. */
+
+ state = tmpl2 = 0;
+ for (j = 0; j < stringlength(slab->string, True, areawin->topinstance); j++) {
+ strptr = findstringpart(j, &locpos, slab->string, areawin->topinstance);
+ if (locpos < 0) continue; /* only look at printable characters */
+ if (strptr->type == RETURN) tmpl2 = 0;
+ tmpl1 = tmpl2;
+ tmpext = ULength(slab, areawin->topinstance, j + 1, NULL);
+ tmpl2 = tmpext.maxwidth;
+ isect = test_insideness(((tmpl1 + tmpl2) >> 1) - adj.x,
+ (tmpext.base + (BASELINE >> 1)) - adj.y, newboxpts);
+
+ /* tiny state machine */
+ if (state == 0) {
+ if (isect) {
+ state = 1;
+ selected = True;
+ areawin->textend = j;
+ if ((areawin->textend > 1) && strptr->type != TEXT_STRING)
+ areawin->textend--;
+ }
+ }
+ else {
+ if (!isect) {
+ areawin->textpos = j;
+ state = 2;
+ break;
+ }
+ }
+ }
+ if (state == 1) areawin->textpos = j; /* selection goes to end of string */
+
+ /* If a label happens to be empty (can happen in the case of */
+ /* a label with parameters that are all empty strings), then */
+ /* check if the bounding box surrounds the label position. */
+
+ else if (tmpext.width == 0) {
+ isect = test_insideness(0, 0, newboxpts);
+ if (isect) {
+ selected = True;
+ areawin->textend = 1;
+ }
+ }
+
+ } break;
+
+ case(PATH):
+ /* check position point of each subpart of the path */
+
+ selected = False;
+ for (pathgen = TOPATH(curgen)->plist; pathgen < TOPATH(curgen)->plist
+ + TOPATH(curgen)->parts; pathgen++) {
+ if (areaelement(pathgen, boxpts, True, level)) selected = True;
+ }
+ break;
+
+ default:
+ selected = areaelement(curgen, boxpts, False, level);
+ break;
+ }
+
+ /* on recursive searches, return as soon as we find something */
+
+ if ((selobj != topobject) && selected) return TRUE;
+
+ /* check if this part has already been selected */
+
+ if (selected)
+ for (newselect = areawin->selectlist; newselect <
+ areawin->selectlist + areawin->selects; newselect++)
+ if (*newselect == (short)(curgen - topobject->plist))
+ selected = False;
+
+ /* add to list of selections */
+
+ if (selected) {
+ newselect = allocselect();
+ *newselect = (short)(curgen - topobject->plist);
+ }
+ }
+ if (selobj != topobject) return FALSE;
+ setoptionmenu();
+
+ /* if none or > 1 label has been selected, cancel any textpos placement */
+
+ if (!checkselect(LABEL) || areawin->selects != 1 ||
+ (areawin->selects == 1 && SELECTTYPE(areawin->selectlist) != LABEL)) {
+ areawin->textpos = areawin->textend = 0;
+ }
+
+ /* Register the selection as an undo event */
+ register_for_undo(XCF_Select, UNDO_DONE, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+
+ /* Drawing of selected objects will take place when drawarea() is */
+ /* executed after the button release. */
+
+#ifdef TCL_WRAPPER
+ if (xobjs.suspend < 0)
+ XcInternalTagCall(xcinterp, 2, "select", "here");
+#endif
+
+ return selected;
+}
+
+/*------------------------*/
+/* start deselection mode */
+/*------------------------*/
+
+void startdesel(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ if (eventmode == NORMAL_MODE) {
+ if (areawin->selects == 0)
+ Wprintf("Nothing to deselect!");
+ else if (areawin->selects == 1)
+ unselect_all();
+ }
+}
+
+/*------------------------------------------------------*/
+/* Redraw all the selected objects in the select color. */
+/*------------------------------------------------------*/
+
+void draw_all_selected()
+{
+ int j;
+
+ if (areawin->hierstack != NULL) return;
+
+ for (j = 0; j < areawin->selects; j++)
+ gendrawselected(areawin->selectlist + j, topobject, areawin->topinstance);
+}
+
+/*---------------------------------------------------------*/
+/* Redraw all the selected objects in their normal colors. */
+/*---------------------------------------------------------*/
+
+void draw_normal_selected(objectptr thisobj, objinstptr thisinst)
+{
+ short saveselects;
+
+ if (areawin->selects == 0) return;
+ else if (areawin->hierstack != NULL) return;
+
+ saveselects = areawin->selects;
+
+ /* reset the graphics state */
+ SetFunction(dpy, areawin->gc, GXcopy);
+
+ areawin->selects = 0;
+ drawarea(NULL, NULL, NULL);
+ areawin->selects = saveselects;
+}
+
+/*----------------------------------------------------------------------*/
+/* Free a selection linked-list structure */
+/* (don't confuse with freeselects) */
+/*----------------------------------------------------------------------*/
+
+static void freeselection(selection *rselect)
+{
+ selection *nextselect;
+
+ while (rselect != NULL) {
+ nextselect = rselect->next;
+ free(rselect->selectlist);
+ free(rselect);
+ rselect = nextselect;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Free memory from the previous selection list, copy the */
+/* current selection list to the previous selection list, and */
+/* zero out the current selection list. */
+/* Normally one would use clearselects(); use freeselects() */
+/* only if the menu/toolbars are going to be updated later in */
+/* the call. */
+/*--------------------------------------------------------------*/
+
+void freeselects()
+{
+ if (areawin->selects > 0)
+ free(areawin->selectlist);
+ areawin->selects = 0;
+ free_stack(&areawin->hierstack);
+}
+
+/*--------------------------------------------------------------*/
+/* Free memory from the selection list and set menu/toolbar */
+/* items back to default values. */
+/*--------------------------------------------------------------*/
+
+void clearselects_noundo()
+{
+ if (areawin->selects > 0) {
+ reset_cycles();
+ freeselects();
+ if (xobjs.suspend < 0) {
+ setallstylemarks(areawin->style);
+ setcolormark(areawin->color);
+ setdefaultfontmarks();
+ setparammarks(NULL);
+ }
+
+#ifdef TCL_WRAPPER
+ if (xobjs.suspend < 0)
+ XcInternalTagCall(xcinterp, 2, "unselect", "all");
+#endif
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Same as above, but registers an undo event. */
+/*--------------------------------------------------------------*/
+
+void clearselects()
+{
+ if (areawin->selects > 0) {
+ register_for_undo(XCF_Select, UNDO_DONE, areawin->topinstance,
+ NULL, 0);
+ clearselects_noundo();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Unselect all the selected elements and free memory from the */
+/* selection list. */
+/*--------------------------------------------------------------*/
+
+void unselect_all()
+{
+ if (xobjs.suspend < 0)
+ draw_normal_selected(topobject, areawin->topinstance);
+ clearselects();
+
+}
+
+/*----------------------------------------------------------------------*/
+/* Select the nearest element, searching the hierarchy if necessary. */
+/* Return an pushlist pointer to a linked list containing the */
+/* hierarchy of objects, with the topmost pushlist also containing a */
+/* pointer to the polygon found. */
+/* Allocates memory for the returned linked list which must be freed by */
+/* the calling routine. */
+/*----------------------------------------------------------------------*/
+
+selection *recurselect(short class, u_char mode, pushlistptr *seltop)
+{
+ selection *rselect, *rcheck, *lastselect;
+ genericptr rgen;
+ short i;
+ objectptr selobj;
+ objinstptr selinst;
+ XPoint savesave, tmppt;
+ pushlistptr selnew;
+ short j, unselects;
+ u_char locmode = (mode == MODE_CONNECT) ? UNDO_DONE : mode;
+ u_char recmode = (mode != MODE_CONNECT) ? MODE_RECURSE_WIDE : MODE_RECURSE_NARROW;
+
+ if (*seltop == NULL) {
+ Fprintf(stderr, "Error: recurselect called with NULL pushlist pointer\n");
+ return NULL;
+ }
+
+ selinst = (*seltop)->thisinst;
+ selobj = selinst->thisobject;
+
+ class &= areawin->filter; /* apply the selection filter */
+
+ unselects = 0;
+ rselect = genselectelement(class, locmode, selobj, selinst);
+ if (rselect == NULL) return NULL;
+
+ for (i = 0; i < rselect->selects; i++) {
+ rgen = *(selobj->plist + (*(rselect->selectlist + i)));
+ if (rgen->type == OBJINST) {
+ selinst = TOOBJINST(selobj->plist + (*(rselect->selectlist + i)));
+
+ /* Link hierarchy information to the pushlist linked list */
+ selnew = (pushlistptr)malloc(sizeof(pushlist));
+ selnew->thisinst = selinst;
+ selnew->next = NULL;
+ (*seltop)->next = selnew;
+
+ /* Translate areawin->save into object's own coordinate system */
+ savesave.x = areawin->save.x;
+ savesave.y = areawin->save.y;
+ InvTransformPoints(&areawin->save, &tmppt, 1, selinst->position,
+ selinst->scale, selinst->rotation);
+ areawin->save.x = tmppt.x;
+ areawin->save.y = tmppt.y;
+ /* Fprintf(stdout, "objinst %s found in object %s; searching recursively\n",
+ selinst->thisobject->name, selobj->name); */
+ /* Fprintf(stdout, "cursor position originally (%d, %d); "
+ "in new object is (%d, %d)\n",
+ savesave.x, savesave.y,
+ areawin->save.x, areawin->save.y); */
+
+ rcheck = recurselect(ALL_TYPES, recmode, &selnew);
+ areawin->save.x = savesave.x;
+ areawin->save.y = savesave.y;
+
+ /* If rgen is NULL, remove selected object from the list, and */
+ /* remove the last entry from the pushlist stack. */
+
+ if (rcheck == NULL) {
+ *(rselect->selectlist + i) = -1;
+ unselects++;
+ (*seltop)->next = NULL;
+ if (selnew->next != NULL)
+ Fprintf(stderr, "Error: pushstack was freed, but was not empty!\n");
+ free(selnew);
+ }
+ else {
+ for (lastselect = rselect; lastselect->next != NULL; lastselect =
+ lastselect->next);
+ lastselect->next = rcheck;
+ }
+ }
+ }
+
+ /* Modify the selection list */
+
+ for (i = 0, j = 0; i < rselect->selects; i++) {
+ if (*(rselect->selectlist + i) >= 0) {
+ if (i != j)
+ *(rselect->selectlist + j) = *(rselect->selectlist + i);
+ j++;
+ }
+ }
+ rselect->selects -= unselects;
+ if (rselect->selects == 0) {
+ freeselection(rselect);
+ rselect = NULL;
+ }
+ return rselect;
+}
+
+/*----------------------------------*/
+/* Start drawing a select area box. */
+/*----------------------------------*/
+
+void startselect()
+{
+ eventmode = SELAREA_MODE;
+ areawin->origin.x = areawin->save.x;
+ areawin->origin.y = areawin->save.y;
+ UDrawBox(areawin->origin, areawin->save);
+
+#ifdef TCL_WRAPPER
+ Tk_CreateEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, (Tk_EventProc *)xctk_drag,
+ NULL);
+#else
+ xcAddEventHandler(areawin->area, ButtonMotionMask |
+ PointerMotionMask, False, (xcEventHandler)xlib_drag,
+ NULL);
+#endif
+
+}
+
+/*-------------------------*/
+/* Track a select area box */
+/*-------------------------*/
+
+void trackselarea()
+{
+ XPoint newpos;
+ /* u_int nullui; (jdk) */
+
+ newpos = UGetCursorPos();
+ if (newpos.x == areawin->save.x && newpos.y == areawin->save.y) return;
+
+ UDrawBox(areawin->origin, areawin->save);
+ UDrawBox(areawin->origin, newpos);
+
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+}
+
+/*----------------------*/
+/* Track a rescale box */
+/*----------------------*/
+
+void trackrescale()
+{
+ XPoint newpos;
+
+ newpos = UGetCursorPos();
+ if (newpos.x == areawin->save.x && newpos.y == areawin->save.y) return;
+
+ UDrawRescaleBox(&areawin->save);
+ UDrawRescaleBox(&newpos);
+
+ areawin->save.x = newpos.x;
+ areawin->save.y = newpos.y;
+}
+
+/*----------------------------------------------------------------------*/
+/* Polygon distance comparison function for qsort */
+/*----------------------------------------------------------------------*/
+
+int dcompare(const void *a, const void *b)
+{
+ XPoint cpt;
+ genericptr agen, bgen;
+ short j, k, adist, bdist;
+
+ cpt.x = areawin->save.x;
+ cpt.y = areawin->save.y;
+
+ j = *((short *)a);
+ k = *((short *)b);
+
+ agen = *(topobject->plist + j);
+ bgen = *(topobject->plist + k);
+
+ if (agen->type != POLYGON || bgen->type != POLYGON) return 0;
+
+ adist = closedistance((polyptr)agen, &cpt);
+ bdist = closedistance((polyptr)bgen, &cpt);
+
+ if (adist == bdist) return 0;
+ return (adist < bdist) ? 1 : -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* Compare two selection linked lists */
+/*----------------------------------------------------------------------*/
+
+Boolean compareselection(selection *sa, selection *sb)
+{
+ int i, j, match;
+ short n1, n2;
+
+ if ((sa == NULL) || (sb == NULL)) return False;
+ if (sa->selects != sb->selects) return False;
+ match = 0;
+ for (i = 0; i < sa->selects; i++) {
+ n1 = *(sa->selectlist + i);
+ for (j = 0; j < sb->selects; j++) {
+ n2 = *(sb->selectlist + j);
+ if (n1 == n2) {
+ match++;
+ break;
+ }
+ }
+ }
+ return (match == sa->selects) ? True : False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Add pin cycles connected to selected labels */
+/*----------------------------------------------------------------------*/
+
+void label_connect_cycles(labelptr thislab)
+{
+ genericptr *pgen;
+ Boolean is_selected;
+ XPoint *testpt;
+ polyptr cpoly;
+ short *stest, cycle;
+
+ if (thislab->pin == LOCAL || thislab->pin == GLOBAL) {
+ for (pgen = topobject->plist; pgen < topobject->plist +
+ topobject->parts; pgen++) {
+ /* Ignore any wires that are already selected */
+ is_selected = FALSE;
+ for (stest = areawin->selectlist; stest < areawin->selectlist +
+ areawin->selects; stest++) {
+ if (SELTOGENERIC(stest) == *pgen) {
+ is_selected = TRUE;
+ break;
+ }
+ }
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ cpoly = TOPOLY(pgen);
+ if (!is_selected) {
+ cycle = 0;
+ for (testpt = cpoly->points; testpt < cpoly->points +
+ cpoly->number; testpt++) {
+ if (testpt->x == thislab->position.x
+ && testpt->y == thislab->position.y) {
+ addcycle(pgen, cycle, 0);
+ break;
+ }
+ else
+ cycle++;
+ }
+ }
+ else {
+ /* Make sure that this polygon's cycle is not set! */
+ removecycle(pgen);
+ }
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Add pin cycles connected to selected instances */
+/*----------------------------------------------------------------------*/
+
+void inst_connect_cycles(objinstptr thisinst)
+{
+ genericptr *ggen, *pgen;
+ Boolean is_selected;
+ XPoint refpoint, *testpt;
+ labelptr clab;
+ polyptr cpoly;
+ short *stest, cycle;
+ objectptr thisobj = thisinst->thisobject;
+
+ for (ggen = thisobj->plist; ggen < thisobj->plist + thisobj->parts; ggen++) {
+ if (ELEMENTTYPE(*ggen) == LABEL) {
+ clab = TOLABEL(ggen);
+ if (clab->pin == LOCAL || clab->pin == GLOBAL) {
+ ReferencePosition(thisinst, &clab->position, &refpoint);
+ for (pgen = topobject->plist; pgen < topobject->plist +
+ topobject->parts; pgen++) {
+ /* Ignore any wires that are already selected */
+ is_selected = FALSE;
+ for (stest = areawin->selectlist; stest < areawin->selectlist +
+ areawin->selects; stest++) {
+ if (SELTOGENERIC(stest) == *pgen) {
+ is_selected = TRUE;
+ break;
+ }
+ }
+ if (ELEMENTTYPE(*pgen) == POLYGON) {
+ cpoly = TOPOLY(pgen);
+ if (!is_selected) {
+ cycle = 0;
+ for (testpt = cpoly->points; testpt < cpoly->points +
+ cpoly->number; testpt++) {
+ if (testpt->x == refpoint.x && testpt->y == refpoint.y) {
+ addcycle(pgen, cycle, 0);
+ break;
+ }
+ else
+ cycle++;
+ }
+ }
+ else {
+ /* Make sure that this polygon's cycle is not set! */
+ removecycle(pgen);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Select connected pins on all selected object instances and labels */
+/*----------------------------------------------------------------------*/
+
+void select_connected_pins()
+{
+ short *selptr;
+ objinstptr selinst;
+ labelptr sellab;
+
+ if (!areawin->pinattach) return;
+
+ for (selptr = areawin->selectlist; selptr < areawin->selectlist +
+ areawin->selects; selptr++) {
+ switch (SELECTTYPE(selptr)) {
+ case LABEL:
+ sellab = SELTOLABEL(selptr);
+ label_connect_cycles(sellab);
+ break;
+ case OBJINST:
+ selinst = SELTOOBJINST(selptr);
+ inst_connect_cycles(selinst);
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Reset all polygon cycles flagged during a move (polygon wires */
+/* connected to pins of an object instance). */
+/*----------------------------------------------------------------------*/
+
+void reset_cycles()
+{
+ polyptr cpoly;
+ genericptr *pgen;
+
+ for (pgen = topobject->plist; pgen < topobject->plist +
+ topobject->parts; pgen++)
+ removecycle(pgen);
+}
+
+/*----------------------------------------------------------------------*/
+/* Recursive selection mechanism */
+/*----------------------------------------------------------------------*/
+
+short *recurse_select_element(short class, u_char mode) {
+ pushlistptr seltop, nextptr;
+ selection *rselect;
+ short *newselect, localpick; /* *desel, (jdk) */
+ static short pick = 0;
+ static selection *saveselect = NULL;
+ int i, j, k, ilast, jlast;
+ Boolean unselect = False;
+
+ seltop = (pushlistptr)malloc(sizeof(pushlist));
+ seltop->thisinst = areawin->topinstance;
+ seltop->next = NULL;
+
+ /* Definition for unselecting an element */
+
+ if (class < 0) {
+ unselect = True;
+ class = -class;
+ }
+ rselect = recurselect(class, mode, &seltop);
+
+ if (rselect) {
+ /* Order polygons according to nearest point distance. */
+ qsort((void *)rselect->selectlist, (size_t)rselect->selects,
+ sizeof(short), dcompare);
+
+ if (compareselection(rselect, saveselect))
+ pick++;
+ else
+ pick = 0;
+
+ localpick = pick % rselect->selects;
+ }
+
+ /* Mechanism for unselecting elements under the cursor */
+ /* (Unselect all picked objects) */
+
+ if (rselect && unselect) {
+
+ ilast = -1;
+ k = 0;
+ for (i = 0; i < rselect->selects; i++) {
+ for (j = 0; j < areawin->selects; j++) {
+ if (*(areawin->selectlist + j) == *(rselect->selectlist + i)) {
+ jlast = j;
+ ilast = i;
+ if (++k == localpick)
+ break;
+ }
+ }
+ if (j < areawin->selects) break;
+ }
+ if (ilast >= 0) {
+ newselect = rselect->selectlist + ilast;
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(SELTOCOLOR(newselect));
+ geneasydraw(*newselect, DEFAULTCOLOR, topobject, areawin->topinstance);
+ areawin->selects--;
+ for (k = jlast; k < areawin->selects; k++)
+ *(areawin->selectlist + k) = *(areawin->selectlist + k + 1);
+
+ if (areawin->selects == 0) freeselects();
+
+ /* Register the selection as an undo event */
+ register_for_undo(XCF_Select, mode, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+ }
+ }
+
+ else if (rselect) {
+
+ /* Mechanism for selecting objects: */
+ /* Count all elements from rselect that are part of */
+ /* the current selection. Pick the "pick"th item (modulo */
+ /* total number of items). */
+
+ ilast = -1;
+ k = 0;
+ for (i = 0; i < rselect->selects; i++) {
+ for (j = 0; j < areawin->selects; j++) {
+ if (*(areawin->selectlist + j) == *(rselect->selectlist + i))
+ break;
+ }
+ if (j == areawin->selects) {
+ ilast = i;
+ if (++k == localpick)
+ break;
+ }
+ }
+
+ if (ilast >= 0) {
+ newselect = allocselect();
+ *newselect = *(rselect->selectlist + ilast);
+ gendrawselected(newselect, topobject, areawin->topinstance);
+ setoptionmenu();
+ u2u_snap(&areawin->save);
+
+ /* Register the selection as an undo event */
+ /* (only if selection changed) */
+
+ register_for_undo(XCF_Select, mode, areawin->topinstance,
+ areawin->selectlist, areawin->selects);
+ }
+ }
+
+ /* Cleanup */
+
+ while (seltop != NULL) {
+ nextptr = seltop->next;
+ free(seltop);
+ seltop = nextptr;
+ }
+
+ freeselection(saveselect);
+ saveselect = rselect;
+
+#ifdef TCL_WRAPPER
+ if (xobjs.suspend < 0)
+ XcInternalTagCall(xcinterp, 2, "select", "here");
+#endif
+
+ return areawin->selectlist;
+}
diff --git a/spiceparser/Makefile.am b/spiceparser/Makefile.am
new file mode 100644
index 0000000..3b9454f
--- /dev/null
+++ b/spiceparser/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+EXTRA_DIST =
+
+INCLUDES = -I.. ${INC_SPECS}
+
+SUBDIRS =
+SUBLIB =
+
+# Requirements for spiceparser library
+noinst_LIBRARIES = libspiceparser.a
+
+libspiceparser_a_SOURCES = \
+ bitlist.c eqn.c eqnlist.c equations.c hash.c list.c list_search.c \
+ memory.c mergedup.c names.c netlist.c netlist_dev.c netlist_extract.c \
+ netlist_funcs.c netlist_lib.c netlist_spice.c netlist_template.c \
+ scanner.c sort.c xcircspice.c
+
diff --git a/spiceparser/Makefile.in b/spiceparser/Makefile.in
new file mode 100644
index 0000000..1c726ba
--- /dev/null
+++ b/spiceparser/Makefile.in
@@ -0,0 +1,619 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = spiceparser
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libspiceparser_a_AR = $(AR) $(ARFLAGS)
+libspiceparser_a_LIBADD =
+am_libspiceparser_a_OBJECTS = bitlist.$(OBJEXT) eqn.$(OBJEXT) \
+ eqnlist.$(OBJEXT) equations.$(OBJEXT) hash.$(OBJEXT) \
+ list.$(OBJEXT) list_search.$(OBJEXT) memory.$(OBJEXT) \
+ mergedup.$(OBJEXT) names.$(OBJEXT) netlist.$(OBJEXT) \
+ netlist_dev.$(OBJEXT) netlist_extract.$(OBJEXT) \
+ netlist_funcs.$(OBJEXT) netlist_lib.$(OBJEXT) \
+ netlist_spice.$(OBJEXT) netlist_template.$(OBJEXT) \
+ scanner.$(OBJEXT) sort.$(OBJEXT) xcircspice.$(OBJEXT)
+libspiceparser_a_OBJECTS = $(am_libspiceparser_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libspiceparser_a_SOURCES)
+DIST_SOURCES = $(libspiceparser_a_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_TARGET = @ALL_TARGET@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_LIB_SPECS = @EXTRA_LIB_SPECS@
+GREP = @GREP@
+GS_EXEC = @GS_EXEC@
+HAVE_LGF = @HAVE_LGF@
+INC_SPECS = @INC_SPECS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTALL_TARGET = @INSTALL_TARGET@
+INTERPRETER = @INTERPRETER@
+INTERP_PATH = @INTERP_PATH@
+LD = @LD@
+LDDL_FLAGS = @LDDL_FLAGS@
+LDFLAGS = @LDFLAGS@
+LD_RUN_PATH = @LD_RUN_PATH@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIB_SPECS = @LIB_SPECS@
+LTLIBOBJS = @LTLIBOBJS@
+M4 = @M4@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+REVISION = @REVISION@
+SET_MAKE = @SET_MAKE@
+SHDLIB_EXT = @SHDLIB_EXT@
+SHELL = @SHELL@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_LIB_SPECS = @SHLIB_LIB_SPECS@
+SPICE_EXEC = @SPICE_EXEC@
+STARTUP_FILE = @STARTUP_FILE@
+STDLIBS = @STDLIBS@
+STRIP = @STRIP@
+SUBDIRS =
+SUBLIB =
+TCL_LIB_DIR = @TCL_LIB_DIR@
+VERSION = @VERSION@
+WISH_EXE = @WISH_EXE@
+WRAPPER_SCRIPT = @WRAPPER_SCRIPT@
+XCIRCUIT_TARGET = @XCIRCUIT_TARGET@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+EXTRA_DIST =
+INCLUDES = -I.. ${INC_SPECS}
+
+# Requirements for spiceparser library
+noinst_LIBRARIES = libspiceparser.a
+libspiceparser_a_SOURCES = \
+ bitlist.c eqn.c eqnlist.c equations.c hash.c list.c list_search.c \
+ memory.c mergedup.c names.c netlist.c netlist_dev.c netlist_extract.c \
+ netlist_funcs.c netlist_lib.c netlist_spice.c netlist_template.c \
+ scanner.c sort.c xcircspice.c
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign spiceparser/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign spiceparser/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libspiceparser.a: $(libspiceparser_a_OBJECTS) $(libspiceparser_a_DEPENDENCIES)
+ -rm -f libspiceparser.a
+ $(libspiceparser_a_AR) libspiceparser.a $(libspiceparser_a_OBJECTS) $(libspiceparser_a_LIBADD)
+ $(RANLIB) libspiceparser.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/spiceparser/Makefile_orig b/spiceparser/Makefile_orig
new file mode 100644
index 0000000..df062f1
--- /dev/null
+++ b/spiceparser/Makefile_orig
@@ -0,0 +1,38 @@
+OBJS = bitlist.o \
+eqn.o \
+eqnlist.o \
+equations.o \
+hash.o \
+list.o \
+list_search.o \
+memory.o \
+mergedup.o \
+names.o \
+netlist.o \
+netlist_dev.o \
+netlist_extract.o \
+netlist_funcs.o \
+netlist_lib.o \
+netlist_spice.o \
+netlist_template.o \
+scanner.o \
+sort.o \
+
+
+CFLAGS = -Wall -I. -DCONFIGURED
+
+CC = gcc
+
+top: $(OBJS) example
+
+:%.o:%.c:
+ $(CC) $(CFLAGS) -o $@ $<
+
+example: README.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $^ -lm
+
+run_example: example test.lib
+ ./example -i test.lib -o test.out -p test.pins
+
+clean:
+ ${RM} -f *.o example test.out test.pins
diff --git a/spiceparser/README.c b/spiceparser/README.c
new file mode 100644
index 0000000..05e0570
--- /dev/null
+++ b/spiceparser/README.c
@@ -0,0 +1,207 @@
+/* subckt_translator.c : quick hack to enable subckt files to work in standard "magic" characterization flow
+ Conrad Ziesler
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "makeutils.lib/debug.h"
+#include "parsers.lib/scanner.h"
+#include "netlist.lib/netlist_spice.h"
+
+
+
+ /*
+ cell: c2 INVX1
+area: 10.368
+input: i_a
+out: o_y
+vss: i_vss
+vdd: i_vdd
+ */
+
+
+int is_power(char *name)
+{
+ if(strcasecmp(name,"vdd")==0) return 1;
+ return 0;
+}
+
+int is_ground(char *name)
+{
+ if(strcasecmp(name,"gnd")==0) return 1;
+ if(strcasecmp(name,"vss")==0) return 1;
+ return 0;
+}
+
+int is_input(char *name)
+{
+ if(!is_ground(name))
+ if(!is_power(name))
+ if(tolower(name[0])<='f') return 1;
+ return 0;
+}
+
+int is_output(char *name)
+{
+ char x;
+ x=tolower(name[0]);
+ if(!is_ground(name))
+ if(!is_power(name))
+ if(x>='q') return 1;
+ return 0;
+}
+
+char *node(node_t n)
+{
+ char *p;
+ p=n->str;
+ return p;
+}
+
+void dumprest(FILE *fp, card_t *cp)
+{
+ for(;cp!=NULL;cp=cp->next)
+ { /* just dump the rest verbatim */
+ fprintf(fp," %s",cp->str);
+ if(cp->val!=NULL) fprintf(fp,"=%s",cp->val);
+ }
+}
+
+void generate_stuff(spice_t *spice, FILE *fp_pins, FILE *fp_flat)
+{
+ subckt_t *ckt,**cktpp;
+ list_t subckts;
+ int i,j;
+ int uniq=1;
+
+
+ subckts=spice_list_subckt(spice->ckt);
+ list_iterate(&subckts,i,cktpp)
+ {
+ ckt=*cktpp;
+ assert(ckt!=NULL);
+ fprintf(fp_pins,"\n\n");
+ fprintf(fp_pins,"cell: c%i %s\n",i,ckt->name);
+ fprintf(fp_pins,"area: %i\n",ckt->nm); /* estimate area by transitor count */
+ for(j=0;j<ckt->ndefn;j++)
+ {
+ char *nn;
+ nn=ckt->defn[j]->str;
+ if(is_input(nn))
+ {
+ fprintf(fp_pins,"input: %s\n",nn);
+ }
+ else if(is_output(nn))
+ {
+ fprintf(fp_pins,"out: %s\n",nn);
+ }
+ else if(is_power(nn))
+ {
+ fprintf(fp_pins,"vdd: %s\n", nn);
+ }
+ else if(is_ground(nn))
+ {
+ fprintf(fp_pins,"vss: %s\n", nn);
+ }
+ else fprintf(fp_pins,"#error pin %s\n",nn);
+ }
+
+ if(fp_flat!=NULL)
+ {
+ fprintf(fp_flat,"\n\n*\n*\n* subckt %s \n\n",ckt->name);
+ for(j=0;j<ckt->nm;j++)
+ {
+ fprintf(fp_flat,"M%i c%i_%s c%i_%s c%i_%s c%i_%s ",
+ uniq++,i,node(ckt->m[j].nodes[0]),i,node(ckt->m[j].nodes[1]),
+ i,node(ckt->m[j].nodes[2]),i,node(ckt->m[j].nodes[3]));
+
+ dumprest(fp_flat,ckt->m[j].rest);
+ fprintf(fp_flat,"\n");
+ /* fprintf(fp_flat," l=%g w=%lf pd=%lf ps=%lf ad=%lf as=%lf \n", */
+ }
+ for(j=0;j<ckt->nc;j++)
+ {
+ fprintf(fp_flat,"C%i c%i_%s c%i_%s ",
+ uniq++,i,node(ckt->c[j].nodes[0]),i,node(ckt->c[j].nodes[1]));
+ dumprest(fp_flat,ckt->c[j].rest);
+ fprintf(fp_flat,"\n");
+ }
+
+ for(j=0;j<ckt->nr;j++)
+ {
+ fprintf(fp_flat,"R%i c%i_%s c%i_%s ",
+ uniq++,i,node(ckt->r[j].nodes[0]),i,node(ckt->r[j].nodes[1]));
+ dumprest(fp_flat,ckt->r[j].rest);
+ fprintf(fp_flat,"\n");
+ }
+
+ }
+ }
+}
+
+
+
+
+int main(int argc, char **argv)
+{
+ char *subckt_filename=NULL;
+ char *pins_output=NULL;
+ char *flat_spice=NULL;
+ int i;
+ scanner_t scan;
+ FILE *fp,*fp_pins,*fp_flat;
+ spice_t *spice;
+
+ for(i=1;i<argc;i++)
+ {
+ char *cmd=argv[i];
+ char *arg=(i<argc)?(argv[i+1]):NULL;
+ if(cmd[0]=='-')
+ switch(cmd[1])
+ {
+ case 'i':
+ if(arg!=NULL)
+ { subckt_filename=arg; i++; continue; }
+ break;
+ case 'p':
+ if(arg!=NULL)
+ { pins_output=arg; i++; continue; }
+ break;
+ case 'o':
+ if(arg!=NULL)
+ { flat_spice=arg; i++; continue; }
+ break;
+ }
+ fprintf(stderr,"Invalid command line option %s %s, skipping\n",cmd,arg);
+ }
+ if((subckt_filename==NULL))
+ {
+ fprintf(stderr,"Usage: translator -i input_subckt_file"
+ " -o output_flat_file -p output_pins_file\n");
+ exit(1);
+ }
+
+
+ scanner_init(&scan);
+ fp=fopen(subckt_filename,"rt");
+ scanner_input_newfp(&scan,fp);
+ spice=spice_new(&scan);
+
+ if(pins_output!=NULL)
+ fp_pins=fopen(pins_output,"w");
+ else fp_pins=stdout;
+
+ if(flat_spice!=NULL)
+ fp_flat=fopen(flat_spice,"w");
+ else fp_flat=NULL;
+
+
+ generate_stuff(spice,fp_pins,fp_flat);
+ if(fp_pins!=NULL)fclose(fp_pins);
+ if(fp_flat!=NULL)fclose(fp_flat);
+
+ return 0;
+}
+
diff --git a/spiceparser/bitlist.c b/spiceparser/bitlist.c
new file mode 100644
index 0000000..d4e660a
--- /dev/null
+++ b/spiceparser/bitlist.c
@@ -0,0 +1,183 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* bitlist.c, routines for bit arrays
+
+Conrad Ziesler
+
+*/
+
+#include "debug.h"
+#include "bitlist.h"
+
+
+
+
+bitlist_t * bitlist_new(int qty)
+{
+ bitlist_t *bl;
+ int qbytes;
+ qbytes=(qty>>3)+1;
+
+ bl= malloc(sizeof(bitlist_t)+qbytes);
+ assert(bl!=NULL);
+ memset(bl,0,sizeof(bitlist_t)+qbytes);
+ bl->qty=qty;
+ bl->qbytes=qbytes;
+
+ return bl;
+}
+
+void bitlist_free(bitlist_t *bl)
+{
+ if(bl!=NULL)
+ free(bl);
+}
+
+void bitlist_setall(bitlist_t *bl)
+{
+ memset(bl->data,0xff,bl->qbytes);
+}
+
+void bitlist_clearall(bitlist_t *bl)
+{
+ memset(bl->data,0,bl->qbytes);
+}
+
+
+int bitlist_set(bitlist_t *bl, int index)
+{
+ int byte,bit,r=0;
+ if(index<0) return 0;
+ byte=index>>3;
+ bit=index-(byte<<3);
+ assert(byte<bl->qbytes);
+ if((bl->data[byte]&(1<<bit))!=0)r=1;
+ bl->data[byte]|=(1<<bit);
+ return r;
+}
+
+int bitlist_test(bitlist_t *bl, int index)
+{
+ int byte,bit;
+ if(index<0) return 0;
+ byte=index>>3;
+ bit=index-(byte<<3);
+ assert(byte<bl->qbytes);
+ if((bl->data[byte]&(1<<bit))!=0)return 1;
+ return 0;
+}
+
+
+int bitlist_clear(bitlist_t *bl, int index)
+{
+ int byte,bit,r=0;
+ if(index<0) return 0;
+ byte=index>>3;
+ bit=index-(byte<<3);
+ assert(byte<bl->qbytes);
+ if((bl->data[byte]&(1<<bit))!=0)r=1;
+ bl->data[byte]&=~(1<<bit);
+ return 0;
+}
+
+/* realloc bitlist */
+bitlist_t *bitlist_resize(bitlist_t *bl, int qty)
+{
+ int oldqty;
+ int qbytes;
+ qbytes=(qty>>3)+1;
+ oldqty=bl->qty;
+
+ bl=realloc(bl,sizeof(bitlist_t)+qbytes);
+ assert(bl!=NULL);
+ if( (oldqty>>3) < (qbytes-(oldqty>>3)) )
+ memset(bl->data+(oldqty>>3),0,qbytes-(oldqty>>3));
+
+ bl->qty=qty;
+ bl->qbytes=qbytes;
+ return bl;
+}
+
+
+/* returns the index of the first bit set or cleared
+ from dir
+*/
+
+int bitlist_scan(bitlist_t *bl, int flags)
+{
+ int i,j;
+ assert(bl!=NULL);
+ switch(flags)
+ {
+ case (SCAN_FORWARD|SCAN_SET):
+ for(i=0;i<(bl->qbytes-1);i++)
+ {
+ if(bl->data[i]!=0)
+ {
+ for(j=(i<<3);j<bl->qty;j++)
+ if(bitlist_test(bl,j))return j;
+ }
+ }
+ break;
+ case (SCAN_FORWARD|SCAN_CLEAR):
+ for(i=0;i<(bl->qbytes-1);i++)
+ {
+ if( (bl->data[i])< ((unsigned char)0x00ff))
+ {
+
+ for(j=(i<<3);j<bl->qty;j++)
+ if(!bitlist_test(bl,j))return j;
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+
+
+int bitlist_copyhead(bitlist_t *dest, bitlist_t *src, int length)
+{
+ int i;
+ int finalbyte;
+ int finalbitoffset;
+ unsigned char a,b;
+ if(length>src->qty)length=src->qty;
+ if(length>dest->qty)length=dest->qty;
+
+ finalbyte=length>>3;
+ finalbitoffset=length-(finalbyte<<3);
+
+ for(i=0;i<finalbyte;i++)
+ dest->data[i]=src->data[i];
+
+ a=dest->data[finalbyte];
+ b=src->data[finalbyte];
+
+ for(i=0;i<finalbitoffset;i++)
+ a= (a & (~(1<<i)) ) | ((1<<i)&b) ;
+
+ dest->data[finalbyte]=a;
+ return length;
+}
diff --git a/spiceparser/bitlist.h b/spiceparser/bitlist.h
new file mode 100644
index 0000000..156bb14
--- /dev/null
+++ b/spiceparser/bitlist.h
@@ -0,0 +1,53 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* bitlist.h, declarations for bitlist functions
+Conrad Ziesler
+*/
+
+#ifndef __BITLIST_H__
+#define __BITLIST_H__
+
+
+/*** bitlist: 1-d array of bits ******/
+typedef struct bitlist_st
+{
+ int qty;
+ int qbytes;
+ unsigned char data[4];
+}bitlist_t;
+
+#define SCAN_FORWARD 1
+#define SCAN_REVERSE 0
+#define SCAN_SET 2
+#define SCAN_CLEAR 0
+
+bitlist_t * bitlist_new(int qty);
+void bitlist_free(bitlist_t *b);
+int bitlist_set(bitlist_t *bl, int index);
+int bitlist_test(bitlist_t *bl, int index);
+int bitlist_clear(bitlist_t *bl, int index);
+bitlist_t *bitlist_resize(bitlist_t *bl,int qty);
+int bitlist_scan(bitlist_t *bl, int flags);
+int bitlist_copyhead(bitlist_t *dest, bitlist_t *src, int length);
+void bitlist_clearall(bitlist_t *bl);
+void bitlist_setall(bitlist_t *bl);
+
+#endif
diff --git a/spiceparser/debug.h b/spiceparser/debug.h
new file mode 100644
index 0000000..746b2d5
--- /dev/null
+++ b/spiceparser/debug.h
@@ -0,0 +1,51 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* debug.h, header controlling inclusion of debugging code, specifically dmalloc
+ Conrad Ziesler
+*/
+
+
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <memory.h>
+
+#include <assert.h>
+
+#ifndef CONFIGURED
+#define DEBUG
+#endif
+
+
+#ifdef DEBUG
+#include <dmalloc.h>
+#endif
+
+void *cmdline_read_rc(int *p_argc, char ***p_argv, char *path);
+void cmdline_free_rc(void *p);
+
+#ifdef PRODUCTION
+#define DEBUG_CMDLINE(c,v,s) NULL
+#else
+#define DEBUG_CMDLINE(c,v,s) cmdline_read_rc(&c,&v,s)
+#endif
+
diff --git a/spiceparser/eqn.c b/spiceparser/eqn.c
new file mode 100644
index 0000000..3216ff5
--- /dev/null
+++ b/spiceparser/eqn.c
@@ -0,0 +1,906 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* eqn.c, equation evaluation and parsing
+
+Conrad Ziesler
+*/
+
+
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "debug.h"
+#include "eqn.h"
+extern int __debug_eqn__;
+
+/* int __debug_eqn__=1; */
+
+#ifndef STRIP_DEBUGGING
+#define D(level,a) do { if(__debug_eqn__>(level)) a; } while(0)
+#else
+#define D(level,a)
+#endif
+
+
+#define uchar unsigned char
+
+
+
+
+#include "memory.h"
+#define MAX_STACK 1024
+
+static memory_t eqn_mem_default=MEMORY_INIT;
+static memory_t *eqn_mem_stack[MAX_STACK]={ &eqn_mem_default , NULL, NULL };
+static int eqn_mem_stackp=0;
+static int eqn_mem_qalloc=0;
+
+void eqn_mem_free(void *p)
+{
+ memory_t *mem=p;
+ if(p!=NULL)
+ {
+ memory_freeall(mem);
+ free(p);
+ }
+}
+
+/* make and return a new eqn memory object */
+void *eqn_mem_new(void)
+{
+ void *p;
+ eqn_mem_qalloc++;
+ p=malloc(sizeof(memory_t));
+ assert(p!=NULL);
+ memory_init(p);
+ return p;
+}
+
+void eqn_mem_push(void *p)
+{
+ eqn_mem_stackp++;
+ assert(eqn_mem_stackp<MAX_STACK);
+ eqn_mem_stack[eqn_mem_stackp]=p;
+}
+
+
+/* return and pop stack */
+void *eqn_mem_pop(void)
+{
+ void *p;
+ assert(eqn_mem_stackp>0);
+ p=eqn_mem_stack[eqn_mem_stackp];
+ eqn_mem_stackp--;
+ return p;
+}
+
+
+#ifdef NO_EQUATIONS
+void eqn_free(enq_t e)
+{ } /* static equations are not mallocated */
+#else
+
+static void *eqn_malloc(int size)
+{
+ void *p=memory_alloc(eqn_mem_stack[eqn_mem_stackp],size);
+ if(p==((void *)0x81dd014))
+ {
+ int i=0;
+ i++;
+ }
+ return p;
+}
+
+void eqn_free(eqn_t e)
+{ memory_free(eqn_mem_stack[eqn_mem_stackp],e.eqn); }
+
+#endif
+
+
+#ifndef NO_EQUATIONS
+eqntoken_t *eqntoken_next(eqntoken_t *p)
+{
+ eqntoken_t *r;
+ switch(p->op)
+ {
+ case OPeolist: case OPeol_const: case OPeol_valp: case OPeol_qty:
+ r=p; break;
+ case OPval: case OPvalm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t) )) ; break;
+ case OPlit: case OPlitm:
+ case OPlitv: case OPlitvm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenlit_t) )) ; break;
+ default: r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
+ }
+ return r;
+}
+
+eqntoken_t *eqntoken_last(eqntoken_t *p)
+{
+ eqntoken_t *r=p;
+
+ while(!OP_ISEND(p->op))p=eqntoken_next(p);
+
+ switch(p->op)
+ {
+ case OPeol_const:
+ r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t))) ; break;
+ case OPeol_valp:
+ r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenpval_t))) ; break;
+ case OPeolist:
+ r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
+ case OPeol_qty:
+ assert(0);
+ default:
+ assert(0);
+ }
+ return r;
+}
+#endif
+
+static float float_parse(uchar *val, int *count)
+{
+ float v=0.0,sign=1,sig=0,rest=0;
+ int i,offset=0;
+ uchar *ps=NULL,*pa=NULL,*pb=NULL,*tmpc;
+ uchar a;
+
+ for(ps=val;(isspace(ps[0]))&&(ps[0]!=0);ps++);
+ if(ps[(unsigned)0]=='-') { sign=-1; pa=ps+1; }
+ else if(ps[(unsigned)0]=='+') { sign=1; pa=ps+1; }
+ else pa=ps;
+
+ if(pa[(unsigned)0]=='.'){ sig=0; pb=pa+1; }
+ else
+ if(isdigit(pa[(unsigned)0]))
+ {
+ sig=atoi(pa);
+ for(pb=pa;pb[0]!=0;pb++)
+ if(!isdigit(pb[0])) break;
+ }
+
+ if(pb==NULL){ return -1e99; }
+ if(pb[0]=='.')
+ pb++;
+
+ i=0;
+
+ if(isdigit(pb[0]))
+ {
+ rest=atoi(pb);
+ for(i=0;pb[i]!=0;i++)
+ {
+ if(!isdigit(pb[i]))break;
+ rest=rest*0.1;
+ }
+ }
+
+ v=(sig+rest)*sign;
+ offset=pb+i+1-val;
+
+
+ switch(pb[i])
+ {
+ case 'f': v*=1e-15; break;
+ case 'p': v*=1e-12; break;
+ case 'n': v*=1e-9; break;
+ case 'u': v*=1e-6; break;
+ case 'm': v*=1e-3; break;
+ case 'x': v*=1e6; break;
+ case 'e': v*=pow(10.0,(float)atoi(pb+i+1));
+ for(tmpc=pb+i+1;isdigit(tmpc[0]);tmpc++);
+ offset=tmpc-val;
+ break;
+ case 0: offset--; break;
+ case ' ': offset--; break;
+ default: offset--; break; /* dont eat this char */
+ }
+
+ /* this is for the case of '5fF' where we have some trailing alpha chars for units which
+ must be discarded so the parser doesn't get confused
+ */
+ while((a=val[offset])!=0)
+ {
+ if(isalpha(a))offset++;
+ else break;
+ }
+
+ D(10,fprintf(stderr,"%s = %e\n",val,v));
+ if(count!=NULL)*count=offset;
+ return v;
+}
+
+#ifndef NO_EQUATIONS
+static int eqntoken_parse(eqntop_t *top)
+{
+ eqntoken_t *node;
+ char *p=top->str;
+ int i=0;
+ int uselast=1;
+ char c;
+ int r=1;
+
+ if(isspace(top->last)||(top->last==0))uselast=0;
+
+ if(!uselast)
+ {
+ for(p=top->str;(isspace(p[0]))&&(p[0]!=0);p++);
+ c=p[0];
+ }
+ else c=top->last;
+ top->last=0;
+
+ if(top->nodep>=MAXEQNSTACK)return 0;
+
+ node=top->nodes+top->nodep++;
+ node->z.lit.lit=NULL;
+ switch(c)
+ {
+ case EQN_DELIM: if(!uselast)top->str++; /* fall through */
+ case 0: node->op=OPeolist; r=0; break;
+ case '+': node->op=OPadd; if(!uselast)top->str++; top->opc++; break;
+ case '-': node->op=OPsub; if(!uselast)top->str++; top->opc++; break;
+ case '*': node->op=OPmul; if(!uselast)top->str++; top->opc++; break;
+ case '/': node->op=OPdiv; if(!uselast)top->str++; top->opc++; break;
+ case '^': node->op=OPexp; if(!uselast)top->str++; top->opc++; break;
+ case '(': node->op=OPopen; if(!uselast)top->str++; top->opc++; break;
+ case ')': node->op=OPclose; if(!uselast)top->str++; top->opc++; break;
+
+ default:
+ if(isdigit(p[0]))
+ {
+ int count=0;
+ node->z.val.x=float_parse(p,&count);
+ node->op=OPval;
+ top->str=p+count;
+ }
+ else
+ {
+ for(i=0;p[i]!=0;i++)
+ if(strchr("\'+-/*^\n\r()",p[i])!=NULL)break;
+ top->last=p[i];
+ p[i]=0;
+ if( (top->last==0) || (top->last==EQN_DELIM)) { r=0; top->str=p+i; }
+ else top->str=p+i+1;
+
+ assert(uselast==0);
+ /* can never have alphanumeral followed by alphanumeral without some delimiter,
+ since it would just become one big identifer
+ */
+ node->z.lit.ref=eqn_litref_INIT;
+ node->z.lit.cache=0.0;
+ node->z.lit.lit=p;
+ node->op=OPlit;
+ }
+
+ top->litc++;
+
+ break;
+ }
+ return r;
+}
+
+
+/* this code assumes dependencies have already been cached, see eqnlist.c */
+static int token_value(eqntoken_t *token, float *v)
+{
+ int r=0;
+ float a=0.0;
+ switch(token->op)
+ {
+ case OPeol_valp:
+ if(token->z.pval.xp!=NULL)
+ a=*(token->z.pval.xp);
+ else r++;
+ D(3,fprintf(stderr,"loaded pval=(%p->%g)\n",token->z.pval.xp,a));
+ break;
+ case OPeol_const: a=token->z.val.x; break;
+ case OPlit: a= 0.0; r++; break;
+ case OPlitm: a=-0.0; r++; break;
+ case OPlitv: a= token->z.lit.cache; break;
+ case OPlitvm: a=-(token->z.lit.cache); break;
+ case OPval: a= token->z.val.x; break;
+ case OPvalm: a=-(token->z.val.x); break;
+ default: assert(0);
+ }
+ *v=a;
+ return r;
+}
+#define PUSH(a) do { if(data->stackp<MAXSTACK) data->stack[data->stackp++]=(a); \
+ D(5,fprintf(stderr,"Push(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
+#define POP(a) do { if(data->stackp>0) (a)=data->stack[--(data->stackp)]; \
+ D(5,fprintf(stderr,"Pop(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
+
+static int eqntoken_eval(eqneval_t *data)
+{
+ int loop,toend;
+ int r=0;
+ float a,b;
+ eqntoken_t *token,*lp;
+ int i;
+
+ static const int precidence[]=OPprecidence;
+ static const int type[]=OPtype;
+
+ int types[4]={ -10 , -10 , -10 , -10 };
+ int precs[4]={ -10, -10 , -10, -10 };
+ int stack_entry=data->stackp;
+
+ toend=0;
+ do
+ {
+ itemop_t ops[4]={OPeolist, OPeolist, OPeolist, OPeolist};
+ eqntoken_t *tokens[4]={ NULL, NULL, NULL, NULL };
+
+ loop=0;
+ token=data->list;
+ data->list=eqntoken_next(data->list);
+ if(data->list==token)
+ toend++; /* catch endings */
+
+ for(lp=token,i=0;(i<4);i++,lp=eqntoken_next(lp)) /* lookahead */
+ {
+ ops[i]=lp->op;
+ tokens[i]=lp;
+ assert(ops[i]>=0);
+ assert((ops[i]*sizeof(int))<sizeof(precidence));
+ assert((ops[i]*sizeof(int))<sizeof(type));
+ types[i]=type[ops[i]];
+ precs[i]=precidence[ops[i]];
+ if(OP_ISEND(lp->op)) /* we did last token, stop */
+ break;
+ }
+
+ D(8,fprintf(stderr,"Eval: lookahead = "));
+ for(i=0;i<4;i++)
+ {
+ char *syms[]=OPsyms;
+ D(8,fprintf(stderr," %s,t%i,p%i" ,syms[ops[i]],types[i],precs[i]));
+ }
+ D(8,fprintf(stderr,"\n"));
+
+ if(OP_ISANYV(token->op))
+ {
+ r=token_value(token,&a);
+ D(5,fprintf(stderr,"Value: %g\n",a));
+ PUSH(a);
+ }
+
+ else
+
+ if(types[0]==2) /* binary op */
+ {
+ a=1.0; b=1.0;
+ POP(a);
+
+ if( /* literal and higher precidence operator after literal not () */
+ (OP_ISV(ops[1]) && (precs[2] > precs[0]) && (types[2]!=4) ) ||
+
+ /* operator (ie open/close) which has a higher precidence */
+ ((types[1]>=2) && (precs[1] > precs[0]))
+ )
+
+ { /* SHIFT */
+ D(6,fprintf(stderr,"Shift: recursion\n"));
+
+ eqntoken_eval(data);
+
+
+ POP(b);
+ }
+ else /* REDUCE */
+ {
+ D(6,fprintf(stderr,"Reduce: \n"));
+ if( OP_ISANYV(ops[1]) )
+ {
+ data->list=eqntoken_next(data->list);
+ r+=token_value(tokens[1],&b);
+
+ }
+ else { /* error, need literal */ assert(0); }
+ }
+
+ D(6,fprintf(stderr,"Doing Binary Op, %g op %g \n",a,b));
+ switch(token->op)
+ {
+ case OPadd: a=a+b; break;
+ case OPsub: a=a-b; break;
+ case OPmul: a=a*b; break;
+ case OPdiv:
+ if(b!=0.0) a=a/b;
+ else a=0.0;
+ break;
+
+ case OPexp: a=pow(a,b); break;
+
+ default: assert(0);
+ }
+ PUSH(a);
+
+ }
+ else
+ if(types[0]==4) /* open/close */
+ {
+ if(token->op==OPopen)
+ {
+ D(6,fprintf(stderr,"open { : \n"));
+ loop=1;
+ }
+ else if(token->op==OPclose)
+ {
+ D(6,fprintf(stderr,"close } : returning \n"));
+ return 0;
+ }
+
+ }
+ else if(token->op == OPeolist);
+
+ if(toend) { D(6,fprintf(stderr,"Ending: \n")); return 0; }
+ else
+ {
+ D(6,fprintf(stderr,"Stack: entry=%i now=%i %s \n",stack_entry,data->stackp,
+ ((stack_entry<data->stackp)||loop)?"looping":"returning"));
+ }
+ }
+ while((stack_entry<data->stackp)||loop);
+ return r;
+}
+
+#undef PUSH
+#undef POP
+
+
+eqntoken_t *eqntok_parse(char *str)
+{
+ eqn_t eq;
+ int i,j,qlit,qval,qvalp;
+ int last_was_op;
+ int type[]=OPtype;
+ eqntoken_t *list,*lp,*lpn;
+ eqntop_t data;
+ eqntoken_t *cp,*np;
+ data.nodep=0;
+ data.litc=0;
+ data.opc=0;
+ data.last=0;
+ data.str=str;
+
+ D(2,fprintf(stderr,"Parsing [%s]\n",str));
+ while(eqntoken_parse(&data));
+
+ for(i=0,qval=0,qlit=0,qvalp=0,j=0;i<data.nodep;i++)
+ {
+ switch(data.nodes[i].op)
+ {
+ case OPlit:
+ case OPlitm:
+ qlit++; break;
+ case OPval:
+ case OPvalm:
+ case OPeol_const:
+ qval++; break;
+ case OPeol_valp:
+ qvalp++; break;
+ default: break;
+ }
+ j++;
+ }
+
+ if((qval==1) && (qlit==0) && (qvalp==0) ) /* optimization for single constant, don't store eolist */
+ {
+ eq=eqn_const(data.nodes[0].z.val.x);
+ lp=list=eq.eqn;
+ }
+ else if((qvalp==1) && (qlit==0) && (qval==0) )
+ {
+ eq=eqn_valp(data.nodes[0].z.pval.xp);
+ lp=list=eq.eqn;
+ }
+ else if((qvalp==0) && (qlit==0) && (qval==0) )
+ {
+ /* it appears we have a parse error, no equation is possible */
+ lp=list=NULL;
+ fprintf(stderr,"Invalid Equation \n");
+ assert(0);
+ }
+ else
+ {
+ lp=list=eqn_malloc((sizeof(itemop_t)*(j+1)) + (sizeof(eqntokenlit_t)*(qlit)) + (sizeof(eqntokenval_t)*(qval)));
+
+ for(last_was_op=1,i=j=0;i<data.nodep;i++)
+ {
+ cp=data.nodes+i;
+ if((i+1)<data.nodep)
+ {
+ np=data.nodes+i+1;
+ if( (last_was_op) && (cp->op==OPsub) && (type[np->op]==1) )
+ {
+ np->op++; /* go from OPxxx to OPxxxm */
+ last_was_op=0;
+ continue;
+ }
+ }
+ if(type[cp->op]>1)
+ last_was_op=1;
+ else last_was_op=0;
+
+ lp->op=cp->op;
+ lpn=eqntoken_next(lp);
+ memcpy(lp,cp,((char *)lpn)-((char *)lp));
+ lp=lpn;
+
+ /* list[j++]=cp[0]; */
+ }
+ /*memcpy(list,data.nodes,data->nodep*sizeof(eqntok_t));*/
+ lp->op=OPeolist;
+ /* list[j].op=OPeolist; */
+ }
+
+ D(7,
+ do {
+ char *syms[]=OPsyms;
+ fprintf(stderr, "eqnparse: %i tokens %p ", data.nodep,lp);
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ fprintf(stderr, "%s ",syms[lp->op]);
+ fprintf(stderr, "%s ",syms[lp->op]);
+ fprintf(stderr,"\n");
+ } while (0)
+ );
+
+ return list;
+}
+
+
+/* returns 0 if equation can be evaluated */
+int eqntok_depend(eqntoken_t *list, plookup_t *lookup)
+{
+ int q=0;
+ eqn_litref_t vp;
+ eqntoken_t *lp;
+
+ if(list->op==OPeol_const)return 0; /*optimization */
+ assert(lookup!=NULL);
+
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ {
+ if((lp->op==OPlit)||(lp->op==OPlitm))
+ {
+ D(3,fprintf(stderr,"eqntok_depend: Looking up %s\n",lp->z.lit.lit));
+ if((vp=lookup->lookup(lookup,lp->z.lit.lit))!=eqn_litref_INIT)
+ {
+ lp->z.lit.ref=vp;;
+ lp->op=(lp->op==OPlit)?OPlitv:OPlitvm;
+ }
+ else q++;
+ }
+ }
+ return q;
+}
+
+/* only evaluate after eqntok_depend, and
+ call eqntok_eval IN PROPER ORDER
+ returns 0 if eval ok, 1 if broken dependency, 2 on parse error
+*/
+
+int eqntok_eval(float *res, eqntoken_t *list)
+{
+ eqntoken_t *lp;
+ eqneval_t data;
+ memset(&data,0,sizeof(data));
+ data.stack[(data.stackp=0)]=0.0;
+ data.stackp++;
+ data.list=list;
+ {
+ eqn_t v;
+ v.eqn=list;
+ D(3,debug_eqn(stderr,"Evaluating ",&v));
+ D(3,fprintf(stderr,"\n"));
+ }
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ {
+ if(lp->op==OPlit)return 1;
+ }
+
+ eqntoken_eval(&data);
+
+ if(res!=NULL)
+ *res=data.stack[1];
+
+ if(data.stackp==2)return 0;
+ else return 2;
+}
+
+
+
+eqntoken_t *eqntok_copy(eqntoken_t *p)
+{
+ int q;
+ eqntoken_t *np;
+ np=eqntoken_last(p);
+ q=((char *)np)-((char *)p);
+ np=eqn_malloc(q);
+ assert(np!=NULL);
+ memcpy(np,p,q);
+ return np;
+}
+
+
+eqntoken_t *eqntok_copy_m(eqntoken_t *p, float m)
+{
+ int q;
+ eqntoken_t *np,*nnp;
+
+ if(p->op==OPeol_const) /* common case */
+ {
+ np=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenval_t));
+ np->op=OPeol_const;
+ np->z.val.x=m*p->z.val.x;
+ }
+ else /* build np = m*(old_equation)EOL */
+ {
+ np=eqntoken_last(p);
+ q=((char *)np)-((char *)p);
+
+ np=eqn_malloc(q+(sizeof(itemop_t)*4)+sizeof(eqntokenval_t));
+ nnp=np;
+ nnp->op=OPval;
+ nnp->z.val.x=m;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPmul;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPopen;
+ nnp=eqntoken_next(nnp);
+ memcpy(nnp,p,q);
+ nnp=(void *) (((char *)nnp)+q-sizeof(itemop_t));
+ nnp->op=OPclose;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPeolist;
+ }
+ return np;
+}
+
+#endif
+
+
+
+void debug_eqn(void *dbg_fp, char *str, eqn_t *eqn)
+{
+ FILE *dbg=dbg_fp;
+#ifdef NO_EQUATIONS
+ if(eqn==NULL)return;
+ fprintf(dbg,"%g",eqn->val);
+#else
+ eqntoken_t *eqt;
+ if(eqn==NULL)return;
+ if(0)fprintf(dbg," %s=[%p %p]",str,eqn,eqn->eqn);
+ else fprintf(dbg," %s=",str);
+ if(eqn->eqn!=NULL)
+ {
+ char s=' ';
+ for(eqt=eqn->eqn;!OP_ISEND(eqt->op);eqt=eqntoken_next(eqt))
+ {
+ switch(eqt->op)
+ {
+ case OPlitm:
+ s='-';
+ case OPlit:
+ fprintf(dbg,"(%c%s)",s,eqt->z.lit.lit); break;
+ case OPvalm:
+ s='-';
+ case OPval:
+ fprintf(dbg,"(%c%g)",s,eqt->z.val.x); break;
+ case OPlitvm:
+ s='-';
+ case OPlitv:
+ fprintf(dbg,"(%c%s=%i)",s,eqt->z.lit.lit,eqt->z.lit.ref); break;
+
+ case OPadd: fprintf(dbg,"+"); break;
+ case OPsub: fprintf(dbg,"-"); break;
+ case OPmul: fprintf(dbg,"*"); break;
+ case OPdiv: fprintf(dbg,"/"); break;
+ case OPexp: fprintf(dbg,"^"); break;
+ case OPopen: fprintf(dbg,"{"); break;
+ case OPclose: fprintf(dbg,"}"); break;
+ default: break;
+ }
+ }
+ if(eqt->op==OPeol_const)
+ fprintf(dbg,"%g",eqt->z.val.x);
+ if(eqt->op==OPeol_valp)
+ fprintf(dbg,"%p->%g",eqt->z.pval.xp, (eqt->z.pval.xp==NULL)?0.0:*(eqt->z.pval.xp));
+ }
+#endif
+}
+
+
+
+
+
+
+
+
+
+eqn_t eqn_const(float val)
+{
+ eqn_t eqn;
+#ifdef NO_EQUATIONS
+ eqn.val=val;
+#else
+ eqn.eqn=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenval_t));
+ eqn.eqn->op=OPeol_const;
+ eqn.eqn->z.val.x=val;
+#endif
+ return eqn;
+}
+
+eqn_t eqn_valp(float *valp)
+{
+ eqn_t r;
+#ifdef NO_EQUATIONS
+ r.val=0.0;
+#else
+ r.eqn=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenpval_t));
+ r.eqn->z.pval.xp=valp;
+ r.eqn->op=OPeol_valp;
+#endif
+ return r;
+}
+
+
+eqn_t eqn_undefined(void)
+{
+ return eqn_valp(NULL);
+}
+
+int eqn_is_undefined(eqn_t e)
+{
+#ifdef NO_EQUATIONS
+ return 0;
+#else
+ if(e.eqn==NULL)
+ return 1;
+ if(e.eqn->op==OPeol_valp)
+ return 2;
+ return 0;
+#endif
+}
+
+
+eqn_t eqn_copy(eqn_t e)
+{
+#ifdef NO_EQUATIONS
+ return e;
+#else
+ if(e.eqn!=NULL)
+ e.eqn=eqntok_copy(e.eqn);
+ return e;
+#endif
+}
+
+eqn_t eqn_copy_m(eqn_t e, float m)
+{
+ #ifdef NO_EQUATIONS
+ e.val*=m;
+ return e;
+#else
+ if(e.eqn!=NULL)
+ {
+ if(m==1.0) /* multiplication by 1 is a nop */
+ e.eqn=eqntok_copy(e.eqn);
+ else
+ e.eqn=eqntok_copy_m(e.eqn,m);
+ }
+ return e;
+#endif
+}
+
+eqn_t eqn_parse(uchar *val)
+{
+ eqn_t eqn;
+#ifdef NO_EQUATIONS
+ eqn.val=float_parse(val,NULL);
+#else
+ eqn.eqn=eqntok_parse(val);
+#endif
+ return eqn;
+}
+
+float parse_float(uchar *val)
+{
+ return float_parse(val,NULL);
+}
+
+
+/* this is valid ONLY if we have no literals, ie (6+3*5) */
+/* use eqnl_eval for equations like (lambda*5+delta) */
+
+float eqn_getval_(eqn_t *eqn)
+{
+#ifdef NO_EQUATIONS
+ assert(eqn!=NULL);
+ return eqn->val;
+#else
+ float f;
+ assert(eqn!=NULL);
+ assert(eqn->eqn!=NULL);
+ if(eqn->eqn->op==OPeol_const)
+ return eqn->eqn->z.val.x;
+ f=0.0;
+ eqntok_eval(&f,eqn->eqn);
+ return f;
+#endif
+}
+
+eqn_t eqn_empty(void)
+{
+ eqn_t r;
+#ifdef NO_EQUATIONS
+ r.val=0.0;
+#else
+ r.eqn=NULL;
+#endif
+ return r;
+}
+
+float eqn_setval(eqn_t *eqn, float val)
+{
+ assert(eqn!=NULL);
+#ifdef NO_EQUATIONS
+ return (eqn->val=val);
+#else
+ if(eqn->eqn==NULL)
+ *eqn=eqn_const(val);
+ else
+ if(eqn->eqn->op==OPeol_const)
+ eqn->eqn->z.val.x=val;
+ else
+ {
+ D(1,debug_eqn(stderr, "cannot change eqn",eqn));
+ D(1,fprintf(stderr,"\n"));
+ assert(0);
+ }
+ return val;
+#endif
+}
+
+float eqn_setvalp(eqn_t *eqn, float *valp)
+{
+ assert(eqn!=NULL);
+
+ #ifdef NO_EQUATIONS
+ return (eqn->val=*valp);
+#else
+ if(eqn->eqn==NULL)
+ *eqn=eqn_valp(valp);
+ else
+ if(eqn->eqn->op==OPeol_valp)
+ eqn->eqn->z.pval.xp=valp;
+ else
+ {
+ D(1,debug_eqn(stderr, "cannot set valp",eqn));
+ D(1,fprintf(stderr,"\n"));
+ assert(0);
+ }
+ return *valp;
+#endif
+}
+
+
+
diff --git a/spiceparser/eqn.h b/spiceparser/eqn.h
new file mode 100644
index 0000000..e52fca4
--- /dev/null
+++ b/spiceparser/eqn.h
@@ -0,0 +1,232 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* eqn.h, equation parsing and evaluation
+ Conrad Ziesler
+*/
+
+#define __EQN_H__
+
+/* defining equations eliminates expression parsing
+ and roughly halves memory needed for storage of numerics
+ however you can no longer use parameters.
+*/
+
+/* #define NO_EQUATIONS */
+
+/*#ifndef __FILE_H__
+#include "file.h"
+#endif
+*/
+
+#ifndef __LIST_H__
+#include "list.h"
+#endif
+
+#ifndef __NAMES_H__
+#include "names.h"
+#endif
+
+#ifndef __HASH_H__
+#include "hash.h"
+#endif
+
+
+typedef enum itemop_e
+{
+ OPeolist,
+ OPeol_const, /* special terminator, for constant (reduced memory usage) */
+ OPeol_valp, /* special terminator, for indirection (float *) */
+ OPeol_qty, /* for simplified decoding of eol */
+
+ OPlit,
+ OPlitm,
+ OPlitv,
+ OPlitvm,
+
+ OPval,
+ OPvalm,
+ OPadd,
+ OPsub,
+
+ OPmul,
+ OPdiv,
+ OPexp,
+ OPopen,
+
+ OPclose
+}itemop_t;
+
+#define OPsyms { "OPeolist", "OPeol_const", "OPeol_valp", "OPeol_qty", \
+ "OPlit", "OPlitm", "OPlitv", "OPlitvm", \
+ "OPval", "OPvalm", "OPadd", "OPsub", \
+ "OPmul", "OPdiv", "OPexp","OPopen", \
+ "OPclose" \
+ }
+
+#define OPprecidence { 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 1, 1, \
+ 2, 2, 3, 4, \
+ 4 \
+ }
+
+
+#define OPtype { 0, 1, 1, 0, \
+ 1, -1, 1, -1, \
+ 1, -1, 2, 2, \
+ 2, 2, 2, 4, \
+ 4 \
+ }
+
+#define OP_ISEV(a) (((a)>OPeolist) && ((a) < OPeol_qty) )
+#define OP_ISV(a) (((a)>=OPlit) && ((a) <= OPvalm))
+#define OP_ISEND(a) ( ((a)<=OPeol_qty) )
+#define OP_ISANYV(a) (OP_ISV(a) || OP_ISEV(a))
+
+
+typedef int eqn_litref_t;
+#define eqn_litref_INIT -1
+
+typedef struct eqntokenlit_st
+{
+ char *lit;
+ eqn_litref_t ref;
+ float cache;
+}eqntokenlit_t;
+
+
+typedef struct eqntokenval_st
+{
+ float x;
+}eqntokenval_t;
+
+typedef struct eqntokenpval_st
+{
+ float *xp;
+} eqntokenpval_t;
+
+typedef struct eqntoken_st
+{
+ itemop_t op;
+ union lit_val_un
+ {
+ eqntokenlit_t lit;
+ eqntokenval_t val;
+ eqntokenpval_t pval;
+ }z;
+}eqntoken_t;
+
+
+#define EQN_DELIM '\''
+
+#define MAXEQNSTACK 512
+typedef struct eqntop_st
+{
+ char *str;
+ char last;
+
+ eqntoken_t nodes[MAXEQNSTACK];
+ int nodep;
+
+ int litc;
+ int opc;
+}eqntop_t;
+
+
+
+typedef struct plookup_st
+{
+ eqn_litref_t (*lookup)(struct plookup_st *user, char *str);
+ void *user;
+}plookup_t;
+
+#define MAXSTACK 512
+typedef struct eqneval_st
+{
+ float stack[MAXSTACK];
+ int stackp;
+ eqntoken_t *list;
+
+}eqneval_t;
+
+
+typedef struct eqn_st
+{
+#ifdef NO_EQUATIONS
+ float val;
+#else
+ eqntoken_t *eqn;
+#endif
+}eqn_t;
+
+
+
+eqn_t eqn_const(float val);
+void debug_eqn(void *dbg_fp, char *str, eqn_t *eqn);
+eqn_t eqn_undefined(void);
+eqn_t eqn_valp(float *valp);
+float eqn_setvalp(eqn_t *eqn, float *valp);
+int eqn_is_undefined(eqn_t e);
+
+eqntoken_t *eqntok_parse(char *str);
+
+eqntoken_t *eqntoken_next(eqntoken_t *p);
+int eqntok_depend(eqntoken_t *list, plookup_t *lookup);
+int eqntok_eval(float *res, eqntoken_t *list);
+float parse_float(unsigned char *val);
+eqntoken_t *eqntok_copy(eqntoken_t *p);
+float eqn_setval(eqn_t *eqn, float val);
+float eqn_getval_(eqn_t *eqn);
+#define eqn_getval(a) ___FIXME___
+eqn_t eqn_copy(eqn_t e);
+eqn_t eqn_copy_m(eqn_t e, float m);
+eqn_t eqn_empty(void);
+eqn_t eqn_parse(unsigned char *val);
+
+void *eqn_mem_new(void);
+void eqn_mem_push(void *p);
+void *eqn_mem_pop(void);
+void eqn_mem_free(void *p);
+
+
+/** dependency lists ***/
+
+
+typedef struct eqnlist_st
+{
+ names_t *params;
+ list_t eqnlist;
+ list_t cache;
+}eqnlist_t;
+
+void eqnl_depend(eqnlist_t *nl, eqn_t e);
+void eqnl_free(eqnlist_t *nl);
+void eqnl_init(eqnlist_t *nl);
+void eqnl_evaldep(eqnlist_t *nl);
+float eqnl_eval(eqnlist_t *nl, eqn_t e);
+int eqnl_add(eqnlist_t *nl, eqn_t e, char *str);
+eqn_t eqnl_eqn(eqnlist_t *nl, int index);
+int eqnl_find(eqnlist_t *nl, char *str);
+int eqnl_define(eqnlist_t *nl, int index, float *valp);
+int eqnl_is_undefined(eqnlist_t *nl, int index);
+int eqnl_qty(eqnlist_t *nl);
+char * eqnl_lookup(eqnlist_t *nl, int index);
+void eqnl_autodepend(eqnlist_t *nl);
diff --git a/spiceparser/eqnlist.c b/spiceparser/eqnlist.c
new file mode 100644
index 0000000..64d1243
--- /dev/null
+++ b/spiceparser/eqnlist.c
@@ -0,0 +1,291 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* eqnlist.c, routines for equation dependency lists, part of package eqn
+ Conrad Ziesler
+*/
+
+#include <stdio.h>
+#include "debug.h"
+
+#include "names.h"
+#include "list.h"
+#include "eqn.h"
+#include "bitlist.h"
+
+
+
+int __debug_eqnlist__=1;
+
+#ifndef STRIP_DEBUGGING
+#define D(level,a) do { if(__debug_eqnlist__>(level)) a; } while(0)
+#else
+#define D(level,a)
+#endif
+
+void eqnl_init(eqnlist_t *nl)
+{
+ nl->params=names_new();
+ list_init(&(nl->eqnlist),sizeof(eqn_t),LIST_DEFMODE);
+ list_init(&(nl->cache),sizeof(float),LIST_DEFMODE);
+}
+void eqnl_free(eqnlist_t *nl)
+{
+ list_empty(&(nl->eqnlist));
+ list_empty(&(nl->cache));
+ names_free(nl->params);
+}
+
+int eqnl_find(eqnlist_t *nl, char *str)
+{
+ int ind;
+ ind=names_check(nl->params,str);
+ return ind;
+}
+
+eqn_t eqnl_eqn(eqnlist_t *nl, int index)
+{
+ eqn_t *ep;
+ ep=list_data(&(nl->eqnlist),index);
+ if(ep!=NULL)
+ return *ep;
+ return eqn_empty();
+}
+
+
+int eqnl_add(eqnlist_t *nl, eqn_t e, char *str)
+{
+#ifdef NO_EQUATIONS
+ return -1;
+#else
+ int i;
+ eqn_t ed;
+ float fv=0.0;
+
+ ed=eqn_copy(e);
+ i=list_add(&(nl->eqnlist),&ed);
+ if(names_check(nl->params,str)>=0)
+ { fprintf(stderr,"eqnlist equations: you are doing something wierd w/ hier. (%s) \n",str); assert(0); }
+ names_add(nl->params,i,str);
+ list_add(&(nl->cache),&fv);
+ D(10,fprintf(stderr,"eqnl_add: adding %s as index %i\n",str,i));
+ return i;
+#endif
+}
+
+/* here we evaluate terminals for the user, that is equations
+ for which no other equation depends,
+
+ we first lookup in the parameter cache any dependencies
+ and then call eqntok_eval to do the dirty work
+*/
+
+float eqnl_eval(eqnlist_t *nl, eqn_t e)
+{
+#ifdef NO_EQUATIONS
+ return e.val;
+#else
+ float *fp;
+ float res;
+ int r;
+ eqntoken_t *et;
+ int index;
+
+ if(e.eqn==NULL)return 0.0;
+ for(et=e.eqn;!OP_ISEND(et->op);et=eqntoken_next(et))
+ {
+ if((et->op==OPlit) || (et->op==OPlitm))
+ assert(0);
+
+ if((et->op==OPlitv) || (et->op==OPlitvm))
+ {
+ if((index=et->z.lit.ref)==eqn_litref_INIT)
+ assert(0);
+
+ fp=list_data(&(nl->cache),index);
+ if(fp!=NULL)
+ et->z.lit.cache=*fp;
+ else assert(0);
+ }
+ }
+ res=0.0;
+ r=eqntok_eval(&res,e.eqn);
+ assert(r==0);
+ return res;
+#endif
+}
+
+
+/*
+ any parameter is stored in our cache.
+ here we resolve parameter dependecies
+ and evaluate all parameters.
+
+*/
+
+void eqnl_evaldep(eqnlist_t *nl)
+{
+#ifdef NO_EQUATIONS
+ return;
+#else
+ eqntoken_t *et;
+ int i,sweep,qleft=0,qdep,index;
+ eqn_t *e;
+ bitlist_t *bl;
+
+ qleft=list_qty(&(nl->eqnlist));
+ bl=bitlist_new(qleft);
+
+ for(sweep=0;sweep<32;sweep++) /* limit heirarchy depth to stop cycles */
+ {
+ /* now check dependencies of all equations until done */
+ list_iterate(&(nl->eqnlist),i,e)
+ {
+ if(!bitlist_test(bl,i)) /* quick check for done */
+ {
+ qdep=0;
+ /* go through eqntokens and find dependencies */
+ for(et=e->eqn;!OP_ISEND(et->op);et=eqntoken_next(et))
+ {
+ if((et->op==OPlit) || (et->op==OPlitm))
+ assert(0);
+
+ if((et->op==OPlitv) || (et->op==OPlitvm))
+ {
+ if((index=et->z.lit.ref)==eqn_litref_INIT)
+ assert(0);
+
+ if(bitlist_test(bl,index))
+ { /* dependency is already computed, get its value */
+ float *fp;
+
+ fp=list_data(&(nl->cache),index);
+ if(fp!=NULL)
+ et->z.lit.cache=*fp;
+ else assert(0);
+ }
+ else qdep++; /* indicate dependency not done */
+ }
+ }
+
+ if(qdep==0) /* all dependencies resolved, mark as done */
+ {
+ int r=100;
+ float *fp;
+
+ fp=list_data(&(nl->cache),i);
+
+ if(fp!=NULL) /* compute new value */
+ {
+ r=eqntok_eval(fp,e->eqn);
+ D(5,fprintf(stderr,"Evaldep: recomputed equation %i -> %s == %g\n",i,eqnl_lookup(nl,i),*fp));
+ }
+ assert(r==0);
+ bitlist_set(bl,i);
+ qleft--;
+ }
+
+ }
+ }
+ if(qleft==0)break;
+ }
+ if(sweep==32)
+ {
+ assert(0);
+ }
+
+ bitlist_free(bl);
+#endif
+}
+
+/* do eqntoken_depend looking up unresolved symbols in eqnlist
+ that is, a single predefined list of parameters
+ */
+
+static eqn_litref_t eqnl_depend_lookup(struct plookup_st *user, char *str)
+{
+ eqn_litref_t r;
+ r=eqnl_find(user->user, str);
+ if(r<0)
+ {
+ fprintf(stderr,"eqnl_depend: unresolved symbol %s\n",str);
+ assert(0);
+ }
+ return r;
+}
+
+
+void eqnl_depend(eqnlist_t *nl, eqn_t e)
+{
+ plookup_t plu;
+ if(e.eqn==NULL)return;
+ plu.lookup=eqnl_depend_lookup;
+ plu.user=nl;
+ eqntok_depend(e.eqn,&plu);
+}
+
+
+/* do eqnl_depend on all predefined parameters in eqnlist */
+void eqnl_autodepend(eqnlist_t *nl)
+{
+ int i;
+ eqn_t *e;
+
+ list_iterate(&(nl->eqnlist),i,e)
+ {
+ eqnl_depend(nl,*e);
+ }
+}
+
+/* check if an entry in our eqn table is undefined,
+ that is it should be defined by the client
+ before it tries to call evaleqns
+*/
+int eqnl_is_undefined(eqnlist_t *nl, int index)
+{
+ eqn_t *ep;
+ ep= list_data(&(nl->eqnlist),index);
+ if(ep==NULL)return -1;
+ return eqn_is_undefined(*ep);
+}
+
+
+int eqnl_define(eqnlist_t *nl, int index, float *valp)
+{
+ eqn_t *ep;
+ ep= list_data(&(nl->eqnlist),index);
+ if(ep==NULL)return -1;
+ eqn_setvalp(ep,valp);
+ return 0;
+}
+
+int eqnl_qty(eqnlist_t *nl)
+{
+ int a,b;
+ a=list_qty(&(nl->eqnlist));
+ b=list_qty(&(nl->cache));
+ assert(a==b);
+ return a;
+}
+
+char *eqnl_lookup(eqnlist_t *nl, int index)
+{
+ return names_lookup(nl->params,index);
+}
diff --git a/spiceparser/equations.c b/spiceparser/equations.c
new file mode 100644
index 0000000..1806a70
--- /dev/null
+++ b/spiceparser/equations.c
@@ -0,0 +1,742 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* equations.c, equation evaluation and parsing
+
+Conrad Ziesler
+*/
+
+
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "debug.h"
+#include "equations.h"
+
+int __debug_eqn__=0;
+
+#ifndef STRIP_DEBUGGING
+#define D(level,a) do { if(__debug_eqn__>(level)) a; } while(0)
+#else
+#define D(level,a)
+#endif
+
+
+#define uchar unsigned char
+
+
+
+static eqntoken_t *eqntoken_next(eqntoken_t *p);
+
+
+static void debug_eqn(FILE *fp, char *str, eqn_t *eqn)
+{
+ eqntoken_t *eqt;
+ if(eqn==NULL)return;
+ fprintf(fp," %s=",str);
+ if(eqn->eqn!=NULL)
+ {
+ char s=' ';
+ for(eqt=eqn->eqn;!OP_ISEND(eqt->op);eqt=eqntoken_next(eqt))
+ {
+ switch(eqt->op)
+ {
+ case OPlitm:
+ s='-';
+ case OPlit:
+ fprintf(fp,"(%c%s)",s,eqt->z.lit.lit); break;
+ case OPvalm:
+ s='-';
+ case OPval:
+ fprintf(fp,"(%c%g)",s,eqt->z.val.x); break;
+ case OPlitvm:
+ s='-';
+ case OPlitv:
+ fprintf(fp,"(%c%p->%g)",s,eqt->z.pval.xp,eqt->z.pval.xp[0]); break;
+
+ case OPadd: fprintf(fp,"+"); break;
+ case OPsub: fprintf(fp,"-"); break;
+ case OPmul: fprintf(fp,"*"); break;
+ case OPdiv: fprintf(fp,"/"); break;
+ case OPexp: fprintf(fp,"^"); break;
+ case OPopen: fprintf(fp,"{"); break;
+ case OPclose: fprintf(fp,"}"); break;
+ case OPnorm: fprintf(fp,":norm:"); break; /* A norm B == norm_B(A) */
+ default: break;
+ }
+ }
+ if(eqt->op==OPeol_const)
+ fprintf(fp,"%g",eqt->z.val.x);
+ if(eqt->op==OPeol_valp)
+ fprintf(fp,"%p->%g",eqt->z.pval.xp, (eqt->z.pval.xp==NULL)?0.0:*(eqt->z.pval.xp));
+ }
+}
+
+
+
+
+static void *eqn_malloc(int size)
+{
+ void *p=calloc(1,size);
+ return p;
+}
+static char *eqn_strdup(char *p)
+{
+ return strdup(p);
+}
+
+static void eqn_free(void *p)
+{ if(p!=NULL) free(p); }
+
+
+
+static eqntoken_t *eqntoken_next(eqntoken_t *p)
+{
+ eqntoken_t *r;
+ switch(p->op)
+ {
+ case OPeolist: case OPeol_const: case OPeol_valp: case OPeol_qty:
+ r=p; break;
+ case OPval: case OPvalm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t) )) ; break;
+ case OPlit: case OPlitm:
+ case OPlitv: case OPlitvm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenlit_t) )) ; break;
+ default: r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
+ }
+ return r;
+}
+
+#ifdef UNUSED
+
+static eqntoken_t *eqntoken_last(eqntoken_t *p)
+{
+ eqntoken_t *r=p;
+
+ while(!OP_ISEND(p->op))p=eqntoken_next(p);
+
+ switch(p->op)
+ {
+ case OPeol_const:
+ r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t))) ; break;
+ case OPeol_valp:
+ r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenpval_t))) ; break;
+ case OPeolist:
+ r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
+ case OPeol_qty:
+ assert(0);
+ default:
+ assert(0);
+ }
+ return r;
+}
+#endif
+
+
+
+
+static inline char t_peek(eqntop_t *top)
+{
+ if(top->n_unget>0) { return top->unget[top->n_unget-1]; }
+ return top->str[0];
+}
+
+static inline char t_eat(eqntop_t *top)
+{
+ char c;
+ c=t_peek(top);
+ if(top->n_unget>0) top->n_unget++;
+ else top->str++;
+ return c;
+}
+
+static inline void t_uneat(eqntop_t *top, char a)
+{
+ if(top->n_unget>(sizeof(top->unget)-1)) assert(0);
+ else
+ {
+ top->unget[top->n_unget]=a;
+ top->n_unget++;
+ }
+}
+
+
+
+
+static float float_parse(eqntop_t *top)
+{
+ float v=0.0,sign=1,sig=0,rest=0,digit,place,exp;
+ uchar a;
+
+ while(isspace(t_peek(top))) t_eat(top);
+ a=t_peek(top);
+ if(a=='-') { sign=-1; t_eat(top); }
+ else if(a=='+') { sign=1; t_eat(top); }
+
+ if(t_peek(top)=='.') { sig=0; t_eat(top); }
+ else
+ {
+ sig=0;
+ while(isdigit(t_peek(top)))
+ { sig*=10; sig+=(t_eat(top)-'0'); }
+ }
+
+ if(t_peek(top)=='.') t_eat(top);
+ if(isdigit(t_peek(top)))
+ {
+ place=0.1;
+ while(isdigit(t_peek(top)))
+ { digit=(t_eat(top)-'0'); rest+=(digit*place); place*=0.1; }
+ }
+
+ v=(sig+rest)*sign;
+
+ a=t_peek(top);
+
+ switch(a)
+ {
+ case 'f': t_eat(top); v*=1e-15; break;
+ case 'p': t_eat(top); v*=1e-12; break;
+ case 'n': t_eat(top); v*=1e-9; break;
+ case 'u': t_eat(top); v*=1e-6; break;
+ case 'm': t_eat(top); v*=1e-3; break;
+ case 'x': t_eat(top); v*=1e6; break;
+ case 'e': t_eat(top);
+ exp=0;
+ while(isdigit(t_peek(top)))
+ { exp*=10; exp+=(t_eat(top)-'0'); }
+ v*=pow(10.0,exp);
+ break;
+ }
+ if(isalpha(t_peek(top))) /* eat trailing alphanumerics (ie. 15fF <- F is extra alpha) */
+ t_eat(top);
+
+ D(10,fprintf(stdout,"NUM[%e]\n",v));
+ return v;
+}
+
+
+
+
+static int eqntoken_parse(eqntop_t *top)
+{
+ eqntoken_t *node;
+ int i,inquote=0;
+ char c;
+
+ c=t_peek(top);
+ if(top->nodep>=MAXEQNSTACK)return 0;
+
+ node=top->nodes+top->nodep++;
+ node->z.lit.lit=NULL;
+ switch(c)
+ {
+ case EQN_DELIM: t_eat(top); /* fall through */
+ case 0: node->op=OPeolist; return 0;
+ case '+': node->op=OPadd; t_eat(top); top->opc++; break;
+ case '-': node->op=OPsub; t_eat(top); top->opc++; break;
+ case '*': node->op=OPmul; t_eat(top); top->opc++; break;
+ case '/': node->op=OPdiv; t_eat(top); top->opc++; break;
+ case '^': node->op=OPexp; t_eat(top); top->opc++; break;
+ case '(': node->op=OPopen; t_eat(top); top->opc++; break;
+ case ')': node->op=OPclose; t_eat(top); top->opc++; break;
+ case '$': node->op=OPnorm ; t_eat(top); top->opc++; break;
+
+ default:
+
+ if(isdigit(c))
+ {
+ node->z.val.x=float_parse(top);
+ node->op=OPval;
+ }
+ else
+ {
+ char *p;
+ p=alloca(strlen(top->str)+sizeof(top->unget)+16);
+
+ if(c=='{') { inquote++; t_eat(top); c=t_peek(top); }
+
+ for(i=0;c!=0;c=t_peek(top),i++)
+ {
+ if(!inquote) { if(strchr("\'+-/*^\n\r()",c)!=NULL)break; }
+ if(inquote && (c=='{')) inquote++;
+ if(inquote && (c=='}')) { inquote--; if(inquote==0) { t_eat(top); break; }}
+
+ p[i]=t_eat(top);
+ p[i+1]=0;
+ }
+ D(10,fprintf(stdout,"LIT[%s]\n",p));
+ node->z.lit.lit=eqn_strdup(p);
+ node->op=OPlit;
+ }
+ top->litc++;
+ break;
+ }
+ return 1;
+}
+
+
+/* this code assumes dependencies have already been cached, see eqnlist.c */
+static int token_value(eqntoken_t *token, float *v)
+{
+ int r=0;
+ float a=0.0;
+ switch(token->op)
+ {
+ case OPeol_valp:
+ if(token->z.pval.xp!=NULL)
+ a=*(token->z.pval.xp);
+ else r++;
+ D(3,fprintf(stdout,"loaded pval=(%p->%g)\n",token->z.pval.xp,a));
+ break;
+ case OPeol_const: a=token->z.val.x; break;
+ case OPlit: a= 0.0; r++; break;
+ case OPlitm: a=-0.0; r++; break;
+ case OPlitv: a= *(token->z.pval.xp); break;
+ case OPlitvm: a=-(*(token->z.pval.xp)); break;
+ case OPval: a= token->z.val.x; break;
+ case OPvalm: a=-(token->z.val.x); break;
+ default: assert(0);
+ }
+ *v=a;
+ return r;
+}
+#define PUSH(a) do { if(data->stackp<MAXSTACK) data->stack[data->stackp++]=(a); \
+ D(5,fprintf(stdout,"Push(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
+#define POP(a) do { if(data->stackp>0) (a)=data->stack[--(data->stackp)]; \
+ D(5,fprintf(stdout,"Pop(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
+
+static int eqntoken_eval(eqneval_t *data)
+{
+ int loop,toend;
+ int r=0;
+ float a,b;
+ eqntoken_t *token,*lp;
+ int i;
+
+ static const int precidence[]=OPprecidence;
+ static const int type[]=OPtype;
+
+ int types[4]={ -10 , -10 , -10 , -10 };
+ int precs[4]={ -10, -10 , -10, -10 };
+ int stack_entry=data->stackp;
+
+ toend=0;
+ do
+ {
+ itemop_t ops[4]={OPeolist, OPeolist, OPeolist, OPeolist};
+ eqntoken_t *tokens[4]={ NULL, NULL, NULL, NULL };
+
+ loop=0;
+ token=data->list;
+ data->list=eqntoken_next(data->list);
+ if(data->list==token)
+ toend++; /* catch endings */
+
+ for(lp=token,i=0;(i<4);i++,lp=eqntoken_next(lp)) /* lookahead */
+ {
+ ops[i]=lp->op;
+ tokens[i]=lp;
+ assert(ops[i]>=0);
+ assert((ops[i]*sizeof(int))<sizeof(precidence));
+ assert((ops[i]*sizeof(int))<sizeof(type));
+ types[i]=type[ops[i]];
+ precs[i]=precidence[ops[i]];
+ if(OP_ISEND(lp->op)) /* we did last token, stop */
+ break;
+ }
+
+ D(8,fprintf(stdout,"Eval: lookahead = "));
+ for(i=0;i<4;i++)
+ {
+ char *syms[]=OPsyms;
+ D(8,fprintf(stdout," %s,t%i,p%i" ,syms[ops[i]],types[i],precs[i]));
+ }
+ D(8,fprintf(stdout,"\n"));
+
+ if(OP_ISANYV(token->op))
+ {
+ r=token_value(token,&a);
+ D(5,fprintf(stdout,"Value: %g\n",a));
+ PUSH(a);
+ }
+
+ else
+
+ if(types[0]==2) /* binary op */
+ {
+ a=1.0; b=1.0;
+ POP(a);
+
+ if( /* literal and higher precidence operator after literal not () */
+ (OP_ISV(ops[1]) && (precs[2] > precs[0]) && (types[2]!=4) ) ||
+
+ /* operator (ie open/close) which has a higher precidence */
+ ((types[1]>=2) && (precs[1] > precs[0]))
+ )
+
+ { /* SHIFT */
+ D(6,fprintf(stdout,"Shift: recursion\n"));
+
+ eqntoken_eval(data);
+
+
+ POP(b);
+ }
+ else /* REDUCE */
+ {
+ D(6,fprintf(stdout,"Reduce: \n"));
+ if( OP_ISANYV(ops[1]) )
+ {
+ data->list=eqntoken_next(data->list);
+ r+=token_value(tokens[1],&b);
+ }
+ else { /* error, need literal */ assert(0); }
+ }
+
+ D(6,fprintf(stdout,"Doing Binary Op, %g op %g \n",a,b));
+ switch(token->op)
+ {
+ case OPadd: a=a+b; break;
+ case OPsub: a=a-b; break;
+ case OPmul: a=a*b; break;
+ case OPdiv:
+ if(b!=0.0) a=a/b;
+ else a=0.0;
+ break;
+
+ case OPexp: a=pow(a,b); break;
+ case OPnorm: if(b!=0) a=pow(pow(a,b),1/b); else a=0; break;
+
+ default: assert(0);
+ }
+ PUSH(a);
+
+ }
+ else
+ if(types[0]==4) /* open/close */
+ {
+ if(token->op==OPopen)
+ {
+ D(6,fprintf(stdout,"open { : \n"));
+ loop=1;
+ }
+ else if(token->op==OPclose)
+ {
+ D(6,fprintf(stdout,"close } : returning \n"));
+ return 0;
+ }
+
+ }
+ else if(token->op == OPeolist);
+
+ if(toend) { D(6,fprintf(stdout,"Ending: \n")); return 0; }
+ else
+ {
+ D(6,fprintf(stdout,"Stack: entry=%i now=%i %s \n",stack_entry,data->stackp,
+ ((stack_entry<data->stackp)||loop)?"looping":"returning"));
+ }
+ }
+ while((stack_entry<data->stackp)||loop);
+ return r;
+}
+
+#undef PUSH
+#undef POP
+
+
+static eqntoken_t *eqntok_parse(char *str)
+{
+ int i,j,qlit,qval,qvalp;
+ int last_was_op;
+ int type[]=OPtype;
+ eqntoken_t *list,*lp,*lpn;
+ eqntop_t data;
+ eqntoken_t *cp,*np;
+ memset(&data,0,sizeof(data));
+ data.n_unget=0;
+ data.nodep=0;
+ data.litc=0;
+ data.opc=0;
+ data.str=str;
+
+ D(2,fprintf(stdout,"Parsing [%s]\n",str));
+ data.errors=0;
+ if(data.str[0]==EQN_DELIM) data.str++; /* eat equation prefix delimiter */
+ while(eqntoken_parse(&data));
+
+ for(i=0,qval=0,qlit=0,qvalp=0,j=0;i<data.nodep;i++)
+ {
+ switch(data.nodes[i].op)
+ {
+ case OPlit:
+ case OPlitm:
+ qlit++; break;
+ case OPval:
+ case OPvalm:
+ case OPeol_const:
+ qval++; break;
+ case OPeol_valp:
+ qvalp++; break;
+ default: break;
+ }
+ j++;
+ }
+
+ /* fixme. undo bitrot */
+#ifdef BITROT
+ if((qval==1) && (qlit==0) && (qvalp==0) ) /* optimization for single constant, don't store eolist */
+ {
+ eq=eqn_const(data.nodes[0].z.val.x);
+ lp=list=eq.eqn;
+ }
+ else if((qvalp==1) && (qlit==0) && (qval==0) )
+ {
+ eq=eqn_valp(data.nodes[0].z.pval.xp);
+ lp=list=eq.eqn;
+ }
+ else if((qvalp==0) && (qlit==0) && (qval==0) )
+ {
+ /* it appears we have a parse error, no equation is possible */
+ lp=list=NULL;
+ fprintf(stdout,"Invalid Equation \n");
+ assert(0);
+ }
+ else
+#endif
+ {
+ lp=list=eqn_malloc((sizeof(itemop_t)*(j+1)) + (sizeof(eqntokenlit_t)*(qlit)) + (sizeof(eqntokenval_t)*(qval)));
+
+ for(last_was_op=1,i=j=0;i<data.nodep;i++)
+ {
+ cp=data.nodes+i;
+ if((i+1)<data.nodep)
+ {
+ np=data.nodes+i+1;
+ if( (last_was_op) && (cp->op==OPsub) && (type[np->op]==1) )
+ {
+ np->op++; /* go from OPxxx to OPxxxm */
+ last_was_op=0;
+ continue;
+ }
+ }
+ if(type[cp->op]>1)
+ last_was_op=1;
+ else last_was_op=0;
+
+ lp->op=cp->op;
+ lpn=eqntoken_next(lp);
+ memcpy(lp,cp,((char *)lpn)-((char *)lp));
+ lp=lpn;
+ }
+ lp->op=OPeolist;
+ }
+
+ D(7,
+ do {
+ char *syms[]=OPsyms;
+ fprintf(stdout, "eqnparse: %i tokens %p ", data.nodep,lp);
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ fprintf(stdout, "%s ",syms[lp->op]);
+ fprintf(stdout, "%s ",syms[lp->op]);
+ fprintf(stdout,"\n");
+ } while (0)
+ );
+
+ return list;
+}
+
+
+
+
+
+/* only evaluate after eqntok_depend, and
+ call eqntok_eval IN PROPER ORDER
+ returns 0 if eval ok, 1 if broken dependency, 2 on parse error
+*/
+
+static int eqntok_eval(float *res, eqntoken_t *list)
+{
+ eqntoken_t *lp;
+ eqneval_t data;
+ memset(&data,0,sizeof(data));
+ data.stack[(data.stackp=0)]=0.0;
+ data.stackp++;
+ data.list=list;
+ {
+ eqn_t v;
+ v.eqn=list;
+ D(3,debug_eqn(stdout,"Evaluating \n",&v));
+ }
+
+ /* check that all dependencies have been taken care of */
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ {
+ if((lp->op==OPlit)||(lp->op==OPlitm))return 1;
+ }
+
+ eqntoken_eval(&data);
+
+ if(res!=NULL)
+ *res=data.stack[1];
+
+ if(data.stackp==2)return 0;
+ else return 2;
+}
+
+
+#ifdef UNUSED
+static eqntoken_t *eqntok_copy(eqntoken_t *p)
+{
+ int q;
+ eqntoken_t *np;
+ np=eqntoken_last(p);
+ q=((char *)np)-((char *)p);
+ np=eqn_malloc(q);
+ assert(np!=NULL);
+ memcpy(np,p,q);
+ return np;
+}
+
+
+static eqntoken_t *eqntok_copy_m(eqntoken_t *p, float m)
+{
+ int q;
+ eqntoken_t *np,*nnp;
+
+ if(p->op==OPeol_const) /* common case */
+ {
+ np=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenval_t));
+ np->op=OPeol_const;
+ np->z.val.x=m*p->z.val.x;
+ }
+ else /* build np = m*(old_equation)EOL */
+ {
+ np=eqntoken_last(p);
+ q=((char *)np)-((char *)p);
+
+ np=eqn_malloc(q+(sizeof(itemop_t)*4)+sizeof(eqntokenval_t));
+ nnp=np;
+ nnp->op=OPval;
+ nnp->z.val.x=m;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPmul;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPopen;
+ nnp=eqntoken_next(nnp);
+ memcpy(nnp,p,q);
+ nnp=(void *) (((char *)nnp)+q-sizeof(itemop_t));
+ nnp->op=OPclose;
+ nnp=eqntoken_next(nnp);
+ nnp->op=OPeolist;
+ }
+ return np;
+}
+
+
+#endif
+
+
+
+
+
+
+
+eqn_t equation_parse(uchar *str)
+{
+ eqn_t eqn;
+ eqn.val=0.0;
+ eqn.eqn=eqntok_parse(str);
+ return eqn;
+}
+
+
+
+
+
+/* returns 0 if equation can be evaluated */
+int equation_depend(eqn_t eqn, float *(lookup)(void *user, char *str), void *user)
+{
+ int q=0;
+ float *vp;
+ eqntoken_t *lp,*list;
+ list=eqn.eqn;
+ if(list==NULL)return -1;
+
+ if(list->op==OPeol_const)return 0; /*optimization */
+
+ for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
+ {
+ if((lp->op==OPlit)||(lp->op==OPlitm))
+ {
+ D(50,fprintf(stdout,"eqntok_depend: Looking up %s\n",lp->z.lit.lit));
+ if((vp=lookup(user,lp->z.lit.lit))!=NULL)
+ {
+ eqn_free(lp->z.lit.lit);
+ lp->z.pval.xp=vp;
+ lp->op=(lp->op==OPlit)?OPlitv:OPlitvm;
+ }
+ else q++;
+ }
+ }
+ return q;
+}
+
+
+int equation_eval(eqn_t *peqn)
+{
+ int r=-1;
+ if(peqn->eqn!=NULL)
+ {
+ r=eqntok_eval(&(peqn->val), peqn->eqn);
+ D(1,fprintf(stdout,"Result: %g\n",peqn->val));
+ }
+ return r;
+}
+
+eqn_t equation_empty(eqn_t eqn)
+{
+ eqntoken_t *eqt;
+ /* should traverse equations first to free any literal strings */
+
+ for(eqt=eqn.eqn;(eqt!=NULL);eqt=eqntoken_next(eqt))
+ {
+ switch(eqt->op)
+ {
+ case OPlit:
+ case OPlitm:
+ eqn_free(eqt->z.lit.lit);
+ break;
+ default: break;
+ }
+ if(OP_ISEND(eqt->op)) break;
+ }
+ eqn_free(eqn.eqn);
+ eqn.eqn=NULL;
+ eqn.val=0.0;
+ return eqn;
+}
+
+
+void equation_debug(eqn_t eqn, void *fp)
+{
+ char buf[64];
+ sprintf(buf,"eqn=%g \n ",eqn.val);
+ debug_eqn(fp, buf, &eqn);
+}
diff --git a/spiceparser/equations.h b/spiceparser/equations.h
new file mode 100644
index 0000000..908e340
--- /dev/null
+++ b/spiceparser/equations.h
@@ -0,0 +1,176 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* eqn.h, equation parsing and evaluation
+ Conrad Ziesler
+*/
+
+#ifndef __EQUATIONS_H__
+
+#define __EQUATIONS_H__
+
+
+
+
+#ifndef __LIST_H__
+#include "list.h"
+#endif
+
+#ifndef __NAMES_H__
+#include "names.h"
+#endif
+
+#ifndef __HASH_H__
+#include "hash.h"
+#endif
+
+
+typedef enum itemop_e
+{
+ OPeolist,
+ OPeol_const, /* special terminator, for constant (reduced memory usage) */
+ OPeol_valp, /* special terminator, for indirection (float *) */
+ OPeol_qty, /* for simplified decoding of eol */
+
+ OPlit,
+ OPlitm,
+ OPlitv, /* valp */
+ OPlitvm, /* -valp */
+
+ OPval,
+ OPvalm,
+ OPadd,
+ OPsub,
+
+ OPmul,
+ OPdiv,
+ OPexp,
+ OPnorm, /* a $ b == pow(pow(a,b),1/b) */
+ OPopen,
+
+ OPclose
+}itemop_t;
+
+#define OPsyms { "OPeolist", "OPeol_const", "OPeol_valp", "OPeol_qty", \
+ "OPlit", "OPlitm", "OPlitv", "OPlitvm", \
+ "OPval", "OPvalm", "OPadd", "OPsub", \
+ "OPmul", "OPdiv", "OPexp","OPnorm", "OPopen", \
+ "OPclose" \
+ }
+
+#define OPprecidence { 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 1, 1, \
+ 2, 2, 3, 3, 4, \
+ 4 \
+ }
+
+
+#define OPtype { 0, 1, 1, 0, \
+ 1, -1, 1, -1, \
+ 1, -1, 2, 2, \
+ 2, 2, 2, 2, 4, \
+ 4 \
+ }
+
+#define OP_ISEV(a) (((a)>OPeolist) && ((a) < OPeol_qty) )
+#define OP_ISV(a) (((a)>=OPlit) && ((a) <= OPvalm))
+#define OP_ISEND(a) ( ((a)<=OPeol_qty) )
+#define OP_ISANYV(a) (OP_ISV(a) || OP_ISEV(a))
+
+
+
+typedef struct eqntokenlit_st
+{
+ char *lit;
+}eqntokenlit_t;
+
+
+typedef struct eqntokenval_st
+{
+ float x;
+}eqntokenval_t;
+
+typedef struct eqntokenpval_st
+{
+ float *xp;
+} eqntokenpval_t;
+
+typedef struct eqntoken_st
+{
+ itemop_t op;
+ union lit_val_un
+ {
+ eqntokenlit_t lit;
+ eqntokenval_t val;
+ eqntokenpval_t pval;
+ }z;
+}eqntoken_t;
+
+
+#define EQN_DELIM '\''
+
+#define MAXEQNSTACK 512
+typedef struct eqntop_st
+{
+ char *str;
+ char unget[4];
+ int n_unget;
+
+ int errors;
+ eqntoken_t nodes[MAXEQNSTACK];
+ int nodep;
+
+ int litc;
+ int opc;
+}eqntop_t;
+
+
+#define MAXSTACK 512
+typedef struct eqneval_st
+{
+ float stack[MAXSTACK];
+ int stackp;
+ eqntoken_t *list;
+
+}eqneval_t;
+
+
+typedef struct eqn_st
+{
+ float val;
+ eqntoken_t *eqn;
+}eqn_t;
+
+/* for named equations */
+typedef struct eqndef_st
+{
+ char *name;
+ eqn_t eqn;
+}eqndef_t;
+
+
+/* public interface */
+eqn_t equation_parse(uchar *str);
+int equation_depend(eqn_t eqn, float *(lookup)(void *user, char *str), void *user);
+int equation_eval(eqn_t *peqn);
+eqn_t equation_empty(eqn_t eqn);
+void equation_debug(eqn_t eqn, void *fp);
+#endif
diff --git a/spiceparser/eval.h b/spiceparser/eval.h
new file mode 100644
index 0000000..2eac9a3
--- /dev/null
+++ b/spiceparser/eval.h
@@ -0,0 +1,65 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* eval.h, support for evaluation
+ Conrad Ziesler
+*/
+#ifndef __EVAL_H__
+#define __EVAL_H__
+
+typedef enum eval_op_en
+{
+ EOnone,
+ EOadd,
+ EOsub,
+ EOneg,
+ EOmul,
+ EOdiv,
+ EOmod,
+ EOleft,
+ EOright,
+ EObitxor,
+ EObitand,
+ EObitor,
+ EObitnot,
+ EOor,
+ EOand,
+ EOnot,
+ EOlist,
+ EOliteral,
+ EOlistitem,
+ EOlast
+}eval_op_t;
+
+#define EVAL_ARGS_OF_OP { 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1 }
+#define EVAL_OP_NAMES { "none", "add", "sub", "neg", "mul", "div", "mod", "left", "right", "bitxor", "bitand" \
+ "bitor", "bitnot", "or", "and", "not", "list", "literal", "listitem", "last" }
+
+extern const char *eval_op_names[EOlast+1];
+extern const int eval_args_of_op[EOlast];
+
+typedef struct eval_expr_st
+{
+ eval_op_t op;
+ int args[2];
+}eval_expr_t;
+
+
+#endif
diff --git a/spiceparser/hash.c b/spiceparser/hash.c
new file mode 100644
index 0000000..b403f14
--- /dev/null
+++ b/spiceparser/hash.c
@@ -0,0 +1,267 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* hash.c : Hash table functions for string identifier lookup
+ Conrad Ziesler
+*/
+
+
+#include "debug.h"
+#include "hash.h"
+
+
+
+unsigned int hash_strhash(int max, void *data, int size)
+{
+ int i;
+ unsigned int r=0;
+ char *str=data;
+
+ for(i=0;i<size;i++)
+ {
+ if(str[0]==0)break;
+ r+=((unsigned int)(str[0]&0x7f));
+ r%=max;
+ str++;
+ }
+
+ assert(r<max);
+ assert(r>=0);
+ return r;
+}
+
+
+#define quickhashbin(a,b,c) hash_binhash(a,b,c)
+
+unsigned int hash_binhash(int max, void *data, int size)
+{
+ unsigned int r=0;
+ int i;
+ uchar *str=data;
+
+ for(i=0;i<size;i++)
+ {
+ r+=((unsigned int)(str[0]&0x7f));
+ r%=max;
+ str++;
+ }
+
+ assert(r<max);
+ assert(r>=0);
+ return r;
+}
+
+static hashbin_t *hash_newbin(void *copyfrom, int size)
+{
+ hashbin_t *p;
+
+ p=malloc(size+sizeof(hashbin_t));
+ assert(p!=NULL);
+
+ p->size=size;
+ p->next=NULL;
+ memcpy(hash_bin2user(p),copyfrom,size);
+ return p;
+}
+
+
+static hashbin_t *hash_insert(hash_t *h, unsigned int index, hashbin_t *cp)
+{
+ cp->next=h->bins[index];
+ h->bins[index]=cp;
+ return cp;
+}
+
+#ifdef UNUSED
+static hashbin_t *hash_insertsorted(hash_t *h, hashbin_t *head, hashbin_t *cp)
+{
+ hashbin_t *a,*b=NULL;
+
+ for(a=head;a!=NULL;a=a->next)
+ {
+ if(h->hashcmp(a,cp)>=0)
+ {
+ if(b==NULL)
+ {
+ cp->next=head;
+ return cp;
+ }
+ else
+ {
+ cp->next=a;
+ b->next=cp;
+ return head;
+ }
+ }
+ b=a;
+ }
+ if(b==NULL)
+ {
+ cp->next=NULL;
+ return cp;
+ }
+ else
+ {
+ cp->next=NULL;
+ b->next=cp;
+ return head;
+ }
+}
+#endif
+
+static hashbin_t *hash_findbin(hash_t *h, hashbin_t *start, int ksize, void *key)
+{
+ while(start!=NULL)
+ {
+ if(h->hashcmp(ksize,key,start->size,start+1)==0)return start;
+ start=start->next;
+ }
+ return NULL;
+}
+
+
+
+/******* public functions ********/
+void hash_free (hash_t *h)
+{
+ int i;
+ hashbin_t *p,*np;
+
+ if(h!=NULL)
+ {
+ for(i=0;i<h->qalloc;i++)
+ if(h->alloc[i]!=NULL)free(h->alloc[i]);
+ for(i=0;i<h->qbin;i++)
+ {
+ for(p=h->bins[i];p!=NULL;p=np)
+ {
+ np=p->next;
+ free(p);
+ }
+ }
+ free(h);
+ }
+}
+
+
+hash_t *hash_new (
+ int qbins,
+ uint (*hashfunc)(int max, void *data, int size),
+ int (*hashcmp)(int sizea, void *a, int sizeb, void *b)
+ )
+{
+ hash_t *p;
+ int i;
+ if(qbins<=0)qbins=4;
+ p=malloc(sizeof(hash_t)+(sizeof(hashbin_t *)*qbins) );
+ assert(p!=NULL);
+ p->bins=(void *) (((char *)p)+sizeof(hash_t));
+ p->uniq=0;
+ p->qbin=qbins;
+ p->hashfunc=hashfunc;
+ p->hashcmp=hashcmp;
+ for(i=0;i<qbins;i++)
+ p->bins[i]=NULL;
+ p->qalloc=0;
+ p->alloc=NULL;
+ return p;
+}
+
+
+void *hash_find(hash_t *h, void *key, int ksize)
+{
+ unsigned int ukey;
+ hashbin_t *fbin;
+
+ assert(h!=NULL);
+ ukey=h->hashfunc(h->qbin,key,ksize);
+ assert(ukey<h->qbin);
+
+ fbin=hash_findbin(h,h->bins[ukey],ksize,key);
+
+ if(fbin==NULL)return NULL;
+ return hash_bin2user(fbin);
+}
+
+int hash_size(void *user)
+{
+ hashbin_t *bin;
+ if(user==NULL)return 0;
+ bin=hash_user2bin(user);
+ return bin->size;
+}
+
+void *hash_add(hash_t *h, void *key, int ksize)
+{
+ unsigned int ukey;
+ hashbin_t *fbin, *dbin;
+
+
+ assert(h!=NULL);
+ ukey=h->hashfunc(h->qbin,key,ksize);
+ assert(ukey<h->qbin);
+
+ fbin=hash_findbin(h,h->bins[ukey],ksize,key);
+ if(fbin==NULL)
+ {
+ dbin=hash_newbin(key,ksize);
+ fbin=hash_insert(h,ukey,dbin);
+ }
+ if(fbin!=NULL)
+ return hash_bin2user(fbin);
+ else return NULL;
+}
+
+
+uint hclient_ptrflagstr_hash(int max, void *data, int size)
+{
+ return hash_strhash(max, ((char *)data) + sizeof(hclient_ptrflagstr_t) ,size-sizeof(hclient_ptrflagstr_t));
+}
+
+int hclient_ptrflagstr_cmp(hashbin_t *a, hashbin_t *b)
+{
+ if(a==NULL)return 1;
+ if(b==NULL)return -1;
+ if(a->size > b->size) return 1;
+ if(a->size < b->size) return -1;
+ return strcmp( ((char *) hash_bin2user(a) ) + sizeof(hclient_ptrflagstr_t), ((char *) hash_bin2user(b) ) + sizeof(hclient_ptrflagstr_t) );
+
+}
+
+
+/* binary object
+ straight binary comparison and hash
+*/
+
+uint hclient_bobject_hash(int max, void *data, int size)
+{
+ return quickhashbin(max,data,size);
+}
+
+int hclient_bobject_cmp(int sizea, void *a, int sizeb, void *b)
+{
+ if(a==NULL)return 1;
+ if(b==NULL)return -1;
+ if(sizea > sizeb) return 1;
+ if(sizea < sizeb) return -1;
+ return memcmp(a,b,sizea);
+}
+
+
diff --git a/spiceparser/hash.h b/spiceparser/hash.h
new file mode 100644
index 0000000..4c2ef79
--- /dev/null
+++ b/spiceparser/hash.h
@@ -0,0 +1,110 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* hash.h, hash function headers
+ Conrad Ziesler
+
+*/
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#ifndef UCHAR
+typedef unsigned char uchar;
+#define UCHAR
+#endif
+
+
+#ifndef _SYS_TYPES_H
+typedef unsigned int uint;
+#endif
+
+
+/**********************************/
+/* HASH TABLES ********************/
+
+typedef struct hashbin_st
+{
+ struct hashbin_st *next;
+ int size;
+ /* alloc in place data here */
+}hashbin_t;
+
+typedef struct hash_st
+{
+ int uniq;
+ uint (*hashfunc)(int max, void *data, int size);
+ int (*hashcmp)(int sa, void *a, int sb, void *b);
+ int qbin;
+ hashbin_t **bins;
+ int qalloc;
+ void **alloc;
+}hash_t;
+
+#define hash_bin2user(p) ((void *)(((char *)p)+sizeof(hashbin_t)))
+#define hash_user2bin(p) ((hashbin_t *)((void *)(((char *)p)-sizeof(hashbin_t))))
+#define hash_forall(h,i,p) for((i)=0;(i)<(h)->qbin;(i)++) for((p)=(h)->bins[(i)];(p)!=NULL;(p)=(p)->next)
+#define hash_malloc(h,s) hash_alloc((h),malloc((s)))
+
+
+hash_t *hash_new (
+ int qbins,
+ uint (*hashfunc)(int max, void *data, int size),
+ int (*hashcmp)(int sizea, void *a, int sizeb, void *b)
+ ) ;
+
+void hash_free (hash_t *h); /* free hash table and associated memory */
+void *hash_find (hash_t *h, void *key, int ksize); /* find key in table */
+void *hash_add (hash_t *h, void *key, int ksize); /* add key of size to table */
+void *hash_alloc (hash_t *h, void *data); /* add data to list of allocs */
+int hash_size (void *user); /* just return size of associated bin */
+
+/* ----- some predefined hash clients --------- */
+
+unsigned int hash_strhash(int max, void *data, int size);
+unsigned int hash_binhash(int max, void *data, int size);
+
+/* ptr,flag, in place string
+ do strcmp on strings, hash on the string only
+ store a payload of a ptr and a flag
+*/
+
+typedef struct hash_ptrflagstr_st
+{
+ void *ptr;
+ char flag;
+ /* inplace string to follow */
+}hclient_ptrflagstr_t;
+
+uint hclient_ptrflagstr_hash(int max, void *data, int size);
+
+
+
+/* binary object
+ straight binary comparison and hash
+*/
+
+uint hclient_bobject_hash(int max, void *data, int size);
+int hclient_bobject_cmp(int sizea, void *a, int sizeb, void *b);
+
+
+
+#endif
+
diff --git a/spiceparser/list.c b/spiceparser/list.c
new file mode 100644
index 0000000..4ea5755
--- /dev/null
+++ b/spiceparser/list.c
@@ -0,0 +1,361 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* list.c list module, for array-type list operators
+
+ Conrad Ziesler
+*/
+
+#include "debug.h"
+#include "list.h"
+
+/* listx, supports allocation and freeing of list elements */
+
+void listx_init(listx_t *l, int size, int mode)
+{
+ list_init(&(l->list),size,mode);
+ l->bitmap=NULL;
+}
+
+int listx_alloc(listx_t *l)
+{
+ int cell;
+ if(l->bitmap==NULL)
+ {
+ cell=list_nextz(&(l->list));
+ l->bitmap=bitlist_new(l->list.m);
+ assert(l->bitmap!=NULL);
+ bitlist_set(l->bitmap,cell);
+ return cell;
+ }
+ else
+ {
+ cell=bitlist_scan(l->bitmap,SCAN_FORWARD|SCAN_CLEAR);
+ if((cell<0)||(cell>=l->list.q))
+ cell=list_nextz(&(l->list));
+
+ if(l->list.m != l->bitmap->qty )
+ l->bitmap=bitlist_resize(l->bitmap,l->list.m);
+
+ bitlist_set(l->bitmap,cell);
+ return cell;
+ }
+ return -1;
+}
+
+void listx_free(listx_t *l, int cell)
+{
+ bitlist_clear(l->bitmap,cell);
+ memset(list_data(&(l->list),cell),0,l->list.s);
+}
+void listx_empty(listx_t *l)
+{
+ list_empty(&(l->list));
+ if(l->bitmap!=NULL)bitlist_free(l->bitmap);
+ l->bitmap=NULL;
+}
+
+void *listx_vdata(listx_t *l, int cell)
+{
+ if(bitlist_test(l->bitmap,cell))
+ return list_data(&(l->list),cell);
+ return NULL;
+}
+
+void *listx_data(listx_t *l, int cell)
+{
+ return list_data(&(l->list),cell);
+}
+
+int listx_qty(listx_t *l)
+{
+ return list_qty(&(l->list));
+}
+
+
+void list_shrink(list_t *l)
+{
+ list_hint(l,l->q);
+}
+
+
+void list_empty(list_t *l)
+{
+ if(l->d!=NULL)
+ free(l->d);
+ l->q=0;
+ l->m=0;
+ l->d=NULL;
+}
+
+void list_init(list_t *l, int s, int mode)
+{
+ static const list_t id=LIST_INITDATA;
+ if(l!=NULL)
+ { *l=id; l->s=s; l->mode=mode; l->q=0; l->m=0; }
+}
+
+void list_hint(list_t *l, int max)
+{
+
+ if(max==0)
+ {
+ if(l->d!=NULL)
+ free(l->d);
+ l->d=NULL;
+ l->m=0;
+ l->q=0;
+ }
+ else
+ {
+ if(l->s!=0)
+ l->d=realloc(l->d,(l->m=max)*l->s);
+
+ assert(l->d!=NULL);
+ }
+}
+
+
+void list_hint_grow(list_t *l, int add_q)
+{
+ int qm=l->q+add_q;
+ if(l->m < qm )
+ l->d=realloc(l->d,(l->m=qm)*l->s);
+}
+
+void inline *list_data_func(list_t *l, int i)
+{
+ if((i<l->q)&&(i>=0))
+ return ((char *)(l->d))+(l->s * i);
+ return NULL;
+}
+
+void *list_next(list_t *l)
+{
+ int v;
+
+ if(l->q>=l->m)
+ {
+ if( (l->mode & LIST_FIXEDMODE)!=0)
+ { assert(0); return NULL; }
+
+ if( (l->mode & LIST_EXPMODE)!=0)
+ {
+ if(l->s<(1024*1024))
+ {
+ if((l->m*l->s)>(1024*1024*16))
+ list_hint(l,l->m+((1024*1024*16)/l->s));
+ else
+ list_hint(l,2*( (l->m==0)?16:l->m) );
+ }
+ else list_hint(l,l->m+1);
+ }
+ else
+ {
+ v=l->m+(l->mode&LIST_MODECHUNK);
+ if(v<l->m)v=l->m+1;
+ list_hint(l, v);
+ }
+ }
+ return ((char *)(l->d))+(l->s * l->q++);
+}
+
+void *list_prev(list_t *l)
+{
+ if(l->q>0)
+ {
+ return ((char *)(l->d))+(l->s * --(l->q));
+ }
+ return NULL;
+}
+
+void *list_block_next(list_t *l, int qty)
+{
+ void *r;
+ if((l->q+qty)>=l->m)
+ list_hint(l, l->q+qty);
+
+ r=((char*)l->d)+(l->s*l->q);
+ l->q+=qty;
+ return r;
+}
+
+
+
+
+int list_contains(list_t *l, void *d)
+{
+ int i;
+ for(i=0;i<l->q;i++)
+ if(memcmp(d,list_data(l,i),l->s)==0)
+ return i;
+ return -1;
+}
+
+int list_add(list_t *l, void *d)
+{
+ void *p; int i;
+ i=l->q;
+ p=list_next(l);
+ memcpy(p,d,l->s);
+ return i;
+}
+
+int list_nextz(list_t *l)
+{
+ int i;
+ void *p;
+ i=l->q;
+ p=list_next(l);
+ memset(p,0,l->s);
+ return i;
+}
+
+int list_index(list_t *l, void *p)
+{
+ if( p >= (void *) ((((char *)(l->d))+(l->s*l->q)))) return -1;
+ if( p < l->d) return -1;
+ return (((char *)p)-((char *)(l->d)))/l->s;
+}
+
+int list_stdlib_bsearch(list_t *l, void *key, int (*cmp)(const void *a, const void *b))
+{
+ void *p= bsearch(key,l->d, l->q,l->s,cmp);
+ if(p==NULL)return -1;
+ return list_index(l,p);
+}
+
+void list_sort(list_t *l, int (*cmp)(const void *a, const void *b))
+{
+ qsort(l->d,l->q,l->s,cmp);
+}
+
+void list_start(list_t *l)
+{
+ l->q=0;
+}
+
+
+int list_remove(list_t *l, int i, void *save)
+{
+ void *p;
+ if(i>=l->q)return 1;
+ if(i<0)return 1;
+ p=list_data(l,i);
+ if(save!=NULL)memcpy(save,p,l->s);
+ l->q--;
+ if(l->q>i)
+ memmove(p,((char *)p)+l->s,(l->q-i)*l->s);
+
+ return 0;
+}
+
+void list_copyfrom(list_t *newl, list_t *oldl)
+{
+
+ list_t id=LIST_INITDATA;
+ if(newl!=NULL)
+ { *newl=id; newl->s=oldl->s; newl->mode=oldl->mode; newl->q=0; newl->m=0; }
+}
+
+void list_dup(list_t *newl, list_t *oldl)
+{
+ void *d;
+ list_copyfrom(newl,oldl);
+ list_hint(newl,oldl->q);
+ d=list_block_next(newl,oldl->q);
+ memcpy(d,oldl->d,oldl->s*oldl->q);
+}
+
+void list_append(list_t *growing, list_t *copyfrom)
+{
+ void *d;
+ if(copyfrom==NULL)return;
+ assert(growing->s==copyfrom->s);
+ if(copyfrom->q==0)return;
+ list_hint(growing,growing->q+copyfrom->q);
+ d=list_block_next(growing,copyfrom->q);
+ memcpy(d,copyfrom->d,copyfrom->s*copyfrom->q);
+}
+
+
+int list_element_dup(list_t *l, int from, int to)
+{
+ void *a,*b;
+ if( (to>l->q) || (to<0) || (from>=l->q) || (from<0) )return 1;
+ if(to==l->q) list_next(l);
+ a=list_data(l,to);
+ b=list_data(l,from);
+ assert((a!=NULL)&&(b!=NULL));
+ memcpy(a,b,l->s);
+ return 0;
+}
+
+void list_reset(list_t *l)
+{
+ l->q=0;
+}
+
+
+#include <stdio.h>
+
+int list_bsearch(sort_func_t *sf, void *key)
+{
+ int l,u,idx, res;
+ char *base=sf->tosort->d;
+ void *p;
+ int size=sf->tosort->s;
+
+ if(size==0)return -1;
+ if(sf->tosort->q==0)return -1;
+ if(base==NULL)return -1;
+
+ sf->aiskey=1;
+ l =0;
+ u = sf->tosort->q -1 ;
+
+ res= sf->cmpf(sf,key,base);
+ idx= sf->cmpf(sf,key,(void *)(((const char *)base)+((u-1)*size)));
+ if(0)fprintf(stderr,"list_bsearch, cmpf(e 0)=%i cmpf(e %i)=%i ",res,u-1,idx);
+
+ while (l < u)
+ {
+ idx = (l + u) / 2;
+ p = (void *) (((const char *) base) + (idx * size));
+ res = sf->cmpf (sf, key, p);
+ if (res <= 0) /* if we happen to hit the element, pretend we overshot, we want the first element of key */
+ u = idx;
+ else if (res > 0)
+ l = idx + 1;
+ }
+ res=-1;
+ if(sf->tosort->q>0)
+ {
+ p = (void *) (((const char *) base) + (l * size));
+ res = sf->cmpf (sf,key, p);
+ if(0)fprintf(stderr," l=%i u=%i res=%i\n",l,u,res);
+ if(res==0)
+ return l;
+ return -1;
+ }
+ if(0)fprintf(stderr,"no elements\n");
+ return -1;
+}
+
diff --git a/spiceparser/list.h b/spiceparser/list.h
new file mode 100644
index 0000000..d69d404
--- /dev/null
+++ b/spiceparser/list.h
@@ -0,0 +1,138 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* list.h list module, for array-type list operators
+
+ Conrad Ziesler
+*/
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#ifndef __BITLIST_H__
+#include "bitlist.h"
+#endif
+
+typedef struct list_st
+{
+ int q; /* qty or current index */
+ int s; /* size of item */
+ int m; /* max alloc */
+ int mode; /* list access mode */
+ void *d;
+}list_t;
+
+
+typedef struct listx_st
+{
+ list_t list;
+ bitlist_t *bitmap;
+}listx_t;
+
+
+#define LIST_INITDATA { 0, 0, 0, 0, NULL }
+#define LIST_MODECHUNK 0x000fff /* mask for chunck bits */
+#define LIST_DEFMODE 0x000010 /* reallocate every 16 */
+#define LIST_EXPMODE 0x001fff /* double size per allocation (for exponential growth lists) */
+#define LIST_FIXEDMODE 0x002000 /* flag error if we exceed hinted size */
+#define LIST_UNITMODE 0x01 /* reallocate every 1 */
+#define LIST_USERFLAG1 0x010000
+#define LIST_USERFLAG2 0x020000
+#define LIST_USERMASK 0xff0000
+#define list_getuser(l) (((l)->mode&LIST_USERMASK)>>16)
+#define list_putuser(l,u) (l)->mode=((u<<16)&LIST_USERMASK)
+#define list_setuser(l,u) list_putuser((l),list_getuser((l))|(u))
+#define list_clearuser(l,u) list_putuser((l),list_getuser((l))&(~u))
+#define list_iterate(l,i,p) for((p)=list_data((l),(i)=0);(p)!=NULL;(p)=list_data((l),++(i)))
+#define list_iterate_(l,i) for((i)=0;(i)<((l)->q);(i)++)
+#define list_iterate_backwards(l,i,p) for((p)=list_data((l),(i)=((l)->q-1));(p)!=NULL;(p)=list_data((l),--(i)))
+#define list_lastitem(l) (list_data((l),(l)->q-1))
+#define list_firstitem(l) (list_data((l),0))
+#define list_qty(l) ((l)->q)
+#define list_sizeof(l) ((l)->s)
+
+/* listx routines allow for allocating and freeing list elements */
+void listx_init(listx_t *l, int size, int mode);
+int listx_qty(listx_t *l);
+void *listx_data(listx_t *l, int cell);
+void listx_empty(listx_t *l);
+void listx_free(listx_t *l, int cell);
+int listx_alloc(listx_t *l);
+void *listx_vdata(listx_t *l, int cell);
+
+#define listx_iterate(l,i,p) for((p)=list_data(&((l)->list),(i)=0);(p)!=NULL;(p)=list_data(&((l)->list),++(i))) if(bitlist_test((l)->bitmap,i))
+
+/* #define list_data(l,i) ((void *)( (((i)<((l)->q))&&((i)>=0))? (((char *)((l)->d))+((l)->s * (i))):NULL))
+
+#define list_data(l,i) list_data_func(l,i)
+ */
+
+static inline void *list_data(const list_t *l, int i)
+{
+ if((i<l->q)&&(i>=0))
+ return ((char *)(l->d))+(l->s * i);
+ return NULL;
+}
+
+static inline void *list_vdata(const list_t *l, int i)
+{
+ if((i<l->q)&&(i>=0))
+ return ((char *)(l->d))+(l->s * i);
+ assert(0&&"invalid index into list");
+}
+
+int list_element_dup(list_t *l, int from, int to);
+int list_remove(list_t *l, int i, void *save);
+void list_empty(list_t *l);
+void list_init(list_t *l, int s, int mode);
+void list_hint(list_t *l, int max);
+void *list_next(list_t *l);
+void *list_prev(list_t *l);
+void *list_block_next(list_t *l, int qty);
+void inline *list_data_func(list_t *l, int i);
+int list_contains(list_t *l, void *d);
+int list_add(list_t *l, void *d);
+int list_index(list_t *l, void *p);
+void list_sort(list_t *l, int (*cmp)(const void *a, const void *b));
+void list_start(list_t *l);
+void list_copyfrom(list_t *newl, list_t *oldl);
+void list_shrink(list_t *l);
+int list_nextz(list_t *l);
+void list_dup(list_t *newl, list_t *oldl);
+void list_reset(list_t *l);
+void list_append(list_t *growing, list_t *copyfrom);
+int list_stdlib_bsearch(list_t *l, void *key, int (*cmp)(const void *a, const void *b));
+
+typedef struct sort_func_st
+{
+ list_t *tosort;
+ int (*cmpf)(struct sort_func_st *s, void *a, void *b);
+ int aiskey; /* if element a is a key and not a normal element */
+ void *user;
+}sort_func_t;
+
+int list_bsearch(sort_func_t *sf, void *key);
+
+/* this is in sort.c */
+void list_qsort (sort_func_t *sf);
+
+
+
+#endif
diff --git a/spiceparser/list_search.c b/spiceparser/list_search.c
new file mode 100644
index 0000000..a3fb2b9
--- /dev/null
+++ b/spiceparser/list_search.c
@@ -0,0 +1,182 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* list_search.c, container supporting mulitple sorted searches
+ Conrad Ziesler
+*/
+
+#include "debug.h"
+#include "list_search.h"
+
+void list_search_init(list_search_t *lp, int size, int mode)
+{
+ list_init(&(lp->list),size,mode);
+ list_init(&(lp->psearch),sizeof(list_psearch_t),LIST_DEFMODE);
+}
+
+
+void list_search_empty(list_search_t *lp)
+{
+ int i;
+ list_psearch_t *p;
+ list_empty(&(lp->list));
+ list_iterate(&(lp->psearch),i,p)
+ {
+ if(p->isearchdata!=NULL)free(p->isearchdata);
+ }
+ list_empty(&(lp->list));
+}
+
+
+
+int list_search_addrule(list_search_t *lp, int (*cmpf)(const void *user, const void *a, const void *b),void *user)
+{
+ list_psearch_t t;
+ t.isearchdata=NULL;
+ t.is_sorted=0;
+ t.user=user;
+ t.cmpf=cmpf;
+ t.len=0;
+ return list_add(&(lp->psearch),&t);
+}
+
+int list_search_findnext(list_search_iterator_t *sip)
+{
+ list_psearch_t *psp;
+ int id;
+ void *pa,*pb;
+
+ id=sip->last_id+1;
+ if(sip->sp==NULL)return -1;
+ if(sip->last_id<0)return -1;
+ if(id>=sip->sp->list.q)return -1; /* last one, can't be any more */
+ psp=list_data(&(sip->sp->psearch),sip->which);
+ if(psp==NULL)return -1;
+ if(!psp->is_sorted)return -1;
+ if(psp->len!=sip->sp->list.q) return -1;
+
+ pa=list_data(&(sip->sp->list),psp->isearchdata[sip->last_id]);
+ pb=list_data(&(sip->sp->list),psp->isearchdata[id]);
+ if((pa!=NULL) && (pb!=NULL))
+ if( psp->cmpf(psp->user,pa,pb)==0) /* yes we match previous */
+ {
+ sip->last_id=id;
+ return psp->isearchdata[id];
+ }
+ return -1;
+}
+
+
+
+
+static list_t *debug_cmpf_list=NULL;
+static int (*debug_psp_cmpf)(const void *user ,const void *a, const void *b);
+static void *debug_user;
+
+int debug_cmpf(const void *a, const void *b)
+{
+ const int *ap=a,*bp=b;
+ return debug_psp_cmpf(debug_user,list_vdata(debug_cmpf_list,ap[0]),list_vdata(debug_cmpf_list,bp[0]));
+}
+
+void list_search_qsort_debug (list_search_t *lsp, list_psearch_t *psp)
+{
+ debug_cmpf_list=&(lsp->list);
+ debug_psp_cmpf=psp->cmpf;
+ debug_user=psp->user;
+ qsort(psp->isearchdata,psp->len,sizeof(int),debug_cmpf);
+}
+
+
+int list_search_find(list_search_t *lp, int which, void *key, list_search_iterator_t *sip)
+{
+ list_psearch_t *psp;
+ int i,l,u,idx, res;
+ char *list_base=lp->list.d;
+ int base_size=lp->list.s;
+ int base_qty=lp->list.q;
+ int *base;
+
+ if(sip!=NULL)
+ {
+ sip->sp=lp;
+ sip->which=which;
+ sip->last_id=-1;
+ }
+
+ if(base_size==0)return -1;
+ if(base_qty<=0)return -1;
+
+
+ psp=list_data(&(lp->psearch),which);
+ assert(psp!=NULL);
+
+ if(psp->len!=base_qty)psp->is_sorted=0; /* guard against changes */
+
+ if(!psp->is_sorted)
+ {
+ if(psp->isearchdata!=NULL)free(psp->isearchdata);
+ psp->isearchdata=malloc(sizeof(int)*base_qty);
+ assert(psp->isearchdata!=NULL);
+ psp->len=base_qty;
+ for(i=0;i<base_qty;i++) psp->isearchdata[i]=i;
+ list_search_qsort_debug(lp,psp);
+ psp->is_sorted=1;
+
+ }
+
+ base=psp->isearchdata;
+ l =0;
+ u = base_qty;
+
+ if(base==NULL)return -1;
+
+ while (l < u)
+ {
+ idx = (l + u) >> 1;
+ res= psp->cmpf(psp->user, key, (void *)(list_base+ (base_size*base[idx])));
+ if (res <= 0)
+ u = idx;
+ else if (res > 0)
+ l = idx + 1;
+ }
+ if(l>=base_qty) return -1;
+ if(l<0)return -1;
+ res= psp->cmpf(psp->user, key, (void *)(list_base+ (base_size*base[l])));
+ if(res==0)
+ { if(sip!=NULL)sip->last_id=l; return base[l]; }
+ return -1;
+}
+
+
+
+void list_search_resort(list_search_t *lp)
+{
+ int i;
+ list_psearch_t *ps;
+ list_iterate(&(lp->psearch),i,ps)
+ {
+ ps->is_sorted=0;
+ ps->len=0;
+ if(ps->isearchdata!=NULL)free(ps->isearchdata);
+ }
+}
+
+
diff --git a/spiceparser/list_search.h b/spiceparser/list_search.h
new file mode 100644
index 0000000..28d7d86
--- /dev/null
+++ b/spiceparser/list_search.h
@@ -0,0 +1,83 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* list_search.h, list container that supports arbitary (binary) search
+ Conrad Ziesler
+*/
+
+
+#ifndef __LIST_SEARCH_H__
+#define __LIST_SEARCH_H__
+
+#ifndef __LIST_H__
+#include "list.h"
+#endif
+
+typedef struct list_psearch_st
+{
+ void *user;
+ int (*cmpf)(const void *user, const void *a, const void *b);
+ int *isearchdata;
+ int is_sorted;
+ int len;
+}list_psearch_t;
+
+typedef struct list_search_st
+{
+ list_t list;
+ list_t psearch;
+}list_search_t;
+
+typedef struct list_search_iterator_st
+{
+ list_search_t *sp;
+ int which;
+ int last_id;
+}list_search_iterator_t;
+
+#define list_search(lp) (&((lp)->list))
+
+#define list_search_data(a,b) list_data(list_search((a)),(b))
+#define list_search_vdata(a,b) list_vdata(list_search((a)),(b))
+#define list_search_iterate(l,i,p) for((p)=list_search_data((l),(i)=0);(p)!=NULL;(p)=list_search_data((l),++(i)))
+#define list_search_add(a,b) list_add(list_search((a)),(b))
+#define list_search_qty(a) list_qty(list_search((a)))
+#define list_search_index(a,b) list_index(list_search((a)),(b))
+#define list_search_reset(a) list_reset(list_search((a)))
+#define list_search_iterate_backwards(l,i,p) for((p)=list_search_data((l),(i)=(list_search((l))->q-1));(p)!=NULL;(p)=list_search_data((l),--(i)))
+
+
+void list_search_init(list_search_t *lp, int size, int mode);
+int list_search_addrule(list_search_t *lp, int (*cmpf)(const void *user, const void *a, const void *b),void *user);
+void list_search_resort(list_search_t *lp);
+int list_search_find(list_search_t *lp, int which, void *key, list_search_iterator_t *sip);
+int list_search_findnext(list_search_iterator_t *sip);
+void list_search_empty(list_search_t *lp);
+
+
+/* private */
+void list_search_qsort (list_search_t *lsp, list_psearch_t *psp);
+
+
+
+
+
+
+#endif
diff --git a/spiceparser/memory.c b/spiceparser/memory.c
new file mode 100644
index 0000000..64f390b
--- /dev/null
+++ b/spiceparser/memory.c
@@ -0,0 +1,224 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* memory.c, sequential memory allocator
+ Conrad Ziesler
+*/
+
+/*
+ these routines are used to allocate char aligned
+ objects (namely strings) in such a way that we
+ 1. allocate in big chunks
+ 2. keep track of all the chunk allocations
+ 3. free a bunch at once without having to
+ remember all the little pointers we once had.
+
+ this allows any module to maintain private string
+ (or equations too) storage space that is leak-proof
+*/
+#include "debug.h"
+#include "memory.h"
+
+
+static memory_chain_t *memory_newblock(void)
+{
+ int i;
+ memory_chain_t *p;
+ p=malloc(sizeof(memory_chain_t));
+ p->q=0;
+ for(i=0;i<4;i++)p->magic[i]=MEMORY_MAGIC+i;
+ p->next=NULL;
+ p->qref=0;
+ /*assert(p!=((void *)0x80d8008)); */
+ return p;
+}
+
+void memory_init(memory_t *ma)
+{
+ memory_t def=MEMORY_INIT;
+ *ma=def;
+}
+
+void memory_checkblock(memory_chain_t *p)
+{
+ int i;
+ for(i=0;i<4;i++)
+ if(p->magic[i]!=MEMORY_MAGIC+i)
+ assert(0);
+}
+
+void *memory_alloc(memory_t *ma, int size)
+{
+ memory_chain_t *p,*pp;
+ memory_other_t *op;
+
+ if(size==0)return NULL;
+
+ /* round up to word alignment, thus all allocations will be aligned */
+ size=(size+(sizeof(int)-1))&(~(sizeof(int)-1));
+
+ /* directly allocate big blocks */
+ if(size> (MEMORY_CHUNKSIZE/2))
+ {
+ op=malloc(size+sizeof(memory_other_t)+4);
+ op->next=ma->others;
+ ma->others=op;
+ return (op+1);
+ }
+
+ /* indirectly allocate small blocks */
+ while(1)
+ {
+ for(pp=NULL,p=ma->head;p!=NULL;p=p->next)
+ {
+ memory_checkblock(p);
+ if((MEMORY_CHUNKSIZE-p->q)>=size)
+ {
+ void *d=p->data+p->q;
+ p->q+=size;
+ p->qref++;
+ if(p->q> (MEMORY_CHUNKSIZE-MEMORY_THRESHOLD))
+ {
+ if(pp==NULL)
+ {
+ ma->head=p->next;
+ p->next=ma->full;
+ ma->full=p;
+ }
+ else
+ {
+ pp->next=p->next;
+ p->next=ma->full;
+ ma->full=p;
+ }
+ }
+ return d;
+ }
+ pp=p;
+ }
+
+ if(ma->head==NULL) ma->head= memory_newblock();
+ else
+ {
+ for(pp=NULL,p=ma->head;p!=NULL;p=p->next)
+ pp=p;
+ pp->next=memory_newblock();
+ }
+ }
+}
+
+
+
+void memory_free(memory_t *ma, void *vp)
+{
+ memory_chain_t *p,*pp, **hp;
+ char *ca,*cb,*c=vp;
+ memory_other_t *op,*pop;
+
+ for(hp=&ma->head,pp=NULL,p=ma->head;p!=NULL;p=p->next)
+ {
+ ca=(void*)p;
+ cb=(void*) (p+1);
+ if((c>=ca)&&(c<cb)) { p->qref--; break; }
+ pp=p;
+ }
+ if(p!=NULL)
+ for(hp=&ma->full,pp=NULL,p=ma->full;p!=NULL;p=p->next)
+ {
+ ca=(void*)p;
+ cb=(void*) (p+1);
+ if((c>=ca)&&(c<cb)) { p->qref--; break; }
+ pp=p;
+ }
+ if(p!=NULL)
+ {
+ if(pp==NULL)
+ *hp=p->next;
+ else
+ pp->next=p->next;
+ free(p);
+ return ;
+ }
+
+ for(pop=NULL,op=ma->others;op!=NULL;op=op->next)
+ {
+ if(op==vp)
+ {
+ if(pop==NULL)ma->others=op->next;
+ else pop->next=ma->others;
+ free(op);
+ return;
+ }
+ pop=op;
+ }
+}
+
+void memory_freeall(memory_t *ma)
+{
+ memory_chain_t *p,*pp;
+ memory_other_t *op,*pop;
+
+ for(pp=NULL,p=ma->head;p!=NULL;p=p->next)
+ {
+ if(pp!=NULL)
+ {
+ memory_checkblock(pp);
+ free(pp);
+ }
+ pp=p;
+ }
+
+ if(pp!=NULL)
+ {
+ memory_checkblock(pp);
+ free(pp);
+ }
+ ma->head=NULL;
+
+ for(pp=NULL,p=ma->full;p!=NULL;p=p->next)
+ {
+ if(pp!=NULL)
+ {
+ memory_checkblock(pp);
+ free(pp);
+ }
+ pp=p;
+ }
+
+ if(pp!=NULL)
+ {
+ memory_checkblock(pp);
+ free(pp);
+ }
+ ma->full=NULL;
+ for(pop=NULL,op=ma->others;op!=NULL;op=op->next)
+ {
+ if(pop!=NULL)
+ free(pop);
+ pop=op;
+ }
+ if(pop!=NULL)
+ {
+ free(pop);
+ }
+ ma->others=NULL;
+}
+
+
diff --git a/spiceparser/memory.h b/spiceparser/memory.h
new file mode 100644
index 0000000..6ea68b3
--- /dev/null
+++ b/spiceparser/memory.h
@@ -0,0 +1,63 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* memory.h, header for private memory allocation routines
+ Conrad Ziesler
+*/
+
+#ifndef __MEMORY_H__
+#define __MEMORY_H__
+
+#define MEMORY_CHUNKSIZE (1024*16)
+#define MEMORY_THRESHOLD 16 /* a block is full if it within this size of full */
+
+typedef struct memory_chain_st
+{
+ struct memory_chain_st *next;
+ int q;
+ int qref; /* we maintain an reference count */
+ char data[MEMORY_CHUNKSIZE];
+ int magic[4];
+}memory_chain_t;
+#define MEMORY_MAGIC 0x35dfa315
+
+typedef struct memory_other_st
+{
+ struct memory_other_st *next;
+}memory_other_t;
+
+typedef struct memory_head_st
+{
+ memory_chain_t *head,*full;
+ memory_other_t *others;
+}memory_t;
+
+#define MEMORY_INIT { NULL, NULL, NULL }
+
+
+void *memory_alloc(memory_t *ma, int size);
+void memory_free(memory_t *ma, void *vp);
+void memory_freeall(memory_t *ma);
+void memory_init(memory_t *ma);
+
+#endif
+
+
+
diff --git a/spiceparser/mergedup.c b/spiceparser/mergedup.c
new file mode 100644
index 0000000..52cdaca
--- /dev/null
+++ b/spiceparser/mergedup.c
@@ -0,0 +1,153 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* mergedup.c -> code to find and merge common entities,
+ works in nlogn time, for general entities
+
+Conrad Ziesler
+*/
+
+#include "debug.h"
+#include "mergedup.h"
+
+
+
+
+mergedup_t *mergedup_alloc(int q, int qs)
+{
+ mergedup_t *m;
+ int es=sizeof(sortlist_t)+qs-1;
+
+ m=malloc(sizeof(mergedup_t) + (es * q) + ((q>>3)+2));
+ assert(m!=NULL);
+ m->flb=(q>>3)+2;
+ m->qs=qs;
+ m->es=es;
+ m->qun=qs/4;
+ m->run=(qs-(m->qun*4));
+ m->q=q;
+ m->i=0;
+ m->data= (void *) (((char *)m)+sizeof(mergedup_t)) ;
+ m->freelist= (void *) (((char *)(m->data))+ (es*q) );
+ m->last=(void *)(m->data);
+ memset(m->freelist,0,m->flb);
+ return m;
+}
+
+
+void mergedup_fill(mergedup_t *m, unsigned char *d, int index)
+{
+ int i;
+ sortlist_t *p;
+ p= (sortlist_t *) ( (char *)m->data + (m->es*m->i) );
+ for(i=0;i<m->qs;i++)
+ p->sorted[i]=d[i];
+
+ p->index=index;
+ m->i++;
+ assert(m->i<=m->q);
+}
+
+static int mergedup__qs=0;
+
+static int comparesorted(const void *a, const void *b)
+{
+ unsigned char *pa=((sortlist_t *)a)->sorted;
+ unsigned char *pb=((sortlist_t *)b)->sorted;
+ int i;
+
+ if(pa==pb)return 0;
+ if(pa==NULL)return 1;
+ if(pb==NULL)return -1;
+
+ for(i=0;i<mergedup__qs;i++)
+ {
+ if (pa[i]<pb[i]) return 1;
+ else if (pa[i]>pb[i]) return -1;
+ }
+ return 0;
+}
+
+
+void mergedup_sort(mergedup_t *m)
+{
+ mergedup__qs=m->qs;
+ comparesorted(NULL,NULL);
+ qsort(m->data,m->q, m->es, comparesorted);
+ m->i=0;
+ m->last=NULL;
+}
+
+void mergedup_setbit(mergedup_t *m, int index)
+{
+ int byte,bit;
+ byte=index>>3;
+ bit=index-(byte<<3);
+ assert(byte<m->flb);
+ m->freelist[byte]|=(1<<bit);
+}
+
+int mergedup_testbit(mergedup_t *m, int index)
+{
+ int byte,bit;
+ byte=index>>3;
+ bit=index-(byte<<3);
+ assert(byte<m->flb);
+ if((m->freelist[byte]&(1<<bit))!=0)return 1;
+ return 0;
+}
+
+int mergedup_visit(mergedup_t *m, int w)
+{
+ sortlist_t *p;
+ int i;
+ int v=-1;
+
+ if(m->i>=m->q)return -1;
+
+ /* get unsorted of current data[m->i] */
+ p= (sortlist_t *) ( (char *)m->data + (m->es*m->i) );
+ v=p->index;
+
+ if(w) /* w=1, get next item */
+ {
+ m->last=p;
+ m->i++;
+ return v;
+ }
+ else /* w=0, return next same item */
+ {
+ if(m->last==NULL)return -1;
+ for(i=0;i<m->qs;i++)
+ if(p->sorted[i]!=m->last->sorted[i])return -1;
+
+ m->i++;
+ return v;
+ }
+ return -1;
+}
+
+
+
+void mergedup_free(mergedup_t *m)
+{
+ if(m!=NULL)free(m);
+}
+
diff --git a/spiceparser/mergedup.h b/spiceparser/mergedup.h
new file mode 100644
index 0000000..fb469fe
--- /dev/null
+++ b/spiceparser/mergedup.h
@@ -0,0 +1,53 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* mergedup.h : utility routine header for detecting multiple same entities in nlogn time
+ Conrad Ziesler
+*/
+
+typedef struct sortlist_st
+{
+ int index;
+ unsigned char sorted[1];
+} sortlist_t;
+
+
+typedef struct mergedup_st
+{
+ int qs,es;
+ int qun;
+ int run;
+ int q;
+ int i;
+ int flb;
+ sortlist_t *last;
+ unsigned char *freelist;
+ char *data;
+}mergedup_t;
+
+void mergedup_setbit(mergedup_t *m, int index);
+int mergedup_testbit(mergedup_t *m, int index);
+mergedup_t *mergedup_alloc(int q, int qs);
+void mergedup_fill(mergedup_t *m, unsigned char *d, int index);
+void mergedup_sort(mergedup_t *m);
+int mergedup_visit(mergedup_t *m, int w);
+void mergedup_free(mergedup_t *m);
+
+
diff --git a/spiceparser/names.c b/spiceparser/names.c
new file mode 100644
index 0000000..bce7ef9
--- /dev/null
+++ b/spiceparser/names.c
@@ -0,0 +1,287 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* names.c, efficient string table support
+ Conrad Ziesler
+*/
+
+
+
+#include <stdio.h>
+#include "debug.h"
+
+#define __NAMES_PRIVATE__
+#include "names.h"
+
+static namehash_t *names_newhash(names_t *nt, int refp, const char *str)
+{
+ namehash_t *b;
+ int q=strlen(str);
+ b=malloc(sizeof(namehash_t)+q);
+ assert(b!=NULL);
+ b->refp=refp;
+ b->magic=NAME_MAGIC;
+ strcpy(b->str,str);
+ nt->bytesalloc+=sizeof(namehash_t)+q;
+ nt->namebytes+=q;
+ nt->qtynames++;
+
+ return b;
+}
+
+
+static unsigned int names_ptrhash(names_t *nt, int refp)
+{
+ unsigned q=nt->qtybins;
+ unsigned int v, r=0;
+
+ v=(unsigned)refp;
+ /*
+ v>>=2;
+ r= ((v%(7*q+(q/3)+5))^v) % q;
+ */
+ r= v ^ (v>>3) ^ ((v/3)>>15) ^ ((~v)>>11);
+ return r%q;
+}
+
+static unsigned int names_strhash(names_t *nt, const char *str)
+{
+ unsigned q=nt->qtybins;
+ unsigned int r=0;
+
+ while(*str!=0)
+ {
+ r+= (str[0]^(r%q));
+ r%=q;
+ str++;
+ }
+
+ return r%q;
+}
+
+
+char *names_lookup(names_t *nt, int refp)
+{
+ unsigned int id;
+ namehash_t *nh;
+ int i=0;
+
+ id=names_ptrhash(nt,refp);
+
+ for(nh=nt->cref[id];nh!=NULL;nh=nh->cref,i++)
+ {
+ assert(nh->magic==NAME_MAGIC);
+ if(refp==nh->refp){ return nh->str; }
+ }
+
+ return NULL;
+}
+
+int names_check(names_t *nt, const char *name)
+{
+ unsigned int id;
+ namehash_t *nh;
+ int i=0;
+
+ id=names_strhash(nt,name);
+
+ for(nh=nt->cstr[id];nh!=NULL;nh=nh->cstr,i++)
+ {
+ assert(nh->magic==NAME_MAGIC);
+ if(strcmp(name,nh->str)==0){ return nh->refp; }
+ }
+ return -1;
+}
+
+
+
+void names_add(names_t *nt, int refp, const char *name)
+{
+ unsigned int idn,idr,id;
+ namehash_t *nh,*nhref=NULL,*nhstr=NULL;
+ int i=0;
+
+ if(nt->qtynames>((5*nt->qtybins)/4)) /* double table size each time we outgrow old table */
+ names_rehash(nt, (2*nt->qtynames) );
+
+ idn=names_strhash(nt,name);
+ idr=names_ptrhash(nt,refp);
+
+ for(nh=nt->cref[idr];nh!=NULL;nh=nh->cref,i++)
+ {
+ assert(nh->magic==NAME_MAGIC);
+ if(refp==nh->refp){ nt->avg_refl=(nt->avg_refl+i)/2; nhref=nh; break; }
+ }
+
+ for(nh=nt->cstr[idn];nh!=NULL;nh=nh->cstr,i++)
+ {
+ assert(nh->magic==NAME_MAGIC);
+ if(strcmp(name,nh->str)==0){ nt->avg_strl=(nt->avg_strl+i)/2; nhstr=nh; break; }
+ }
+
+ if(nhstr==NULL) /* adding new name entry */
+ {
+ if(nhref!=NULL) /* but refp was the same */
+ {
+ fprintf(stderr,"**** DUPLICATE KEY NAME ****\n");
+ if(1)assert(0&&"duplicate key in names");
+ }
+
+ nh=names_newhash(nt, refp, name);
+ nh->cstr=nt->cstr[idn];
+ nt->cstr[idn]=nh;
+ nh->cref=nt->cref[idr];
+ nt->cref[idr]=nh;
+ }
+ else /* replacing old name entry */
+ {
+ namehash_t *prev=NULL;
+ assert(0 && "Replacing strings in names has a bug. do not use");
+ /* lookup refp of old name and unlink */
+ id=names_ptrhash(nt,nhstr->refp);
+ for(nh=nt->cref[id];nh!=NULL;prev=nh,nh=nh->cref,i++)
+ if(nhstr->refp==nh->refp)
+ {
+ if(prev==NULL)nt->cref[id]=nh->cref;
+ else prev->cref=nh->cref;
+ break;
+ }
+ /* relink new name, refp */
+ nhstr->refp=refp;
+ nhstr->cref=nt->cref[idr];
+ nt->cref[idr]=nhstr;
+ }
+}
+
+char * names_stats(names_t *nt)
+{
+ static char buf[1024];
+ int i,qs=0,qp=0,ms=0,mp=0,j,ks=0,kp=0;
+ namehash_t *nh;
+
+ for(i=0;i<nt->qtybins;i++)
+ {
+
+ for(j=0,nh=nt->cstr[i];nh!=NULL;nh=nh->cstr,j++) assert(nh->magic==NAME_MAGIC);
+ if(j>0)ks++;
+ if(ms<j)ms=j;
+ qs+=j;
+ for(j=0,nh=nt->cref[i];nh!=NULL;nh=nh->cref,j++) assert(nh->magic==NAME_MAGIC);
+ if(mp<j)mp=j;
+ if(j>0)kp++;
+ qp+=j;
+ }
+
+ qp/=kp;
+ qs/=ks;
+
+ sprintf(buf,"names: %i bins (%i totaling %i) , alloc %i, avg: %i %i max: %i %i",nt->qtybins,nt->qtynames,nt->namebytes,nt->bytesalloc,qp,qs,mp,ms);
+
+ return buf;
+}
+
+
+
+/* this should optimize our hash table for memory usage */
+void names_rehash(names_t *nt, int newbins)
+{
+ int i;
+ int oldqty;
+ namehash_t *hp;
+
+ oldqty=nt->qtybins;
+ nt->qtybins=newbins;
+
+ nt->bytesalloc+= ( (newbins-oldqty)*sizeof(void *)*2 );
+ /* do cref first, using cstr */
+ if(nt->cref!=NULL)
+ free(nt->cref);
+ nt->cref=malloc(sizeof(void *)*(nt->qtybins+1));
+ assert(nt->cref!=NULL);
+ memset(nt->cref,0,sizeof(void*)*nt->qtybins);
+
+ /* iterate through list of string hashes, adding to ref hashes */
+ for(i=0;i<oldqty;i++)
+ for(hp=nt->cstr[i];hp!=NULL;hp=hp->cstr)
+ {
+ unsigned id;
+ id=names_ptrhash(nt,hp->refp);
+ hp->cref=nt->cref[id];
+ nt->cref[id]=hp;
+ }
+
+ /* next do cstr, using new cref */
+ if(nt->cstr!=NULL)
+ free(nt->cstr);
+ nt->cstr=malloc(sizeof(void *)*(nt->qtybins+1));
+ assert(nt->cstr!=NULL);
+ memset(nt->cstr,0,sizeof(void*)*nt->qtybins);
+
+ for(i=0;i<nt->qtybins;i++)
+ for(hp=nt->cref[i];hp!=NULL;hp=hp->cref)
+ {
+ unsigned id;
+ id=names_strhash(nt,hp->str);
+ hp->cstr=nt->cstr[id];
+ nt->cstr[id]=hp;
+ }
+}
+
+
+
+names_t *names_new(void)
+{
+ names_t *p;
+ p=malloc(sizeof(names_t));
+ assert(p!=NULL);
+ memset(p,0,sizeof(names_t));
+ p->bytesalloc=sizeof(names_t);
+ p->namebytes=0;
+ p->qtynames=0;
+ p->avg_strl=0;
+ p->avg_refl=0;
+
+ p->qtybins=0;
+ p->cstr=NULL;
+ p->cref=NULL;
+ names_rehash(p,13); /* start small, grow bigger */
+ return p;
+}
+
+void names_free(names_t *nt)
+{
+ int i;
+ namehash_t *nh,*next;
+ if(nt!=NULL)
+ {
+ for(i=0;i<nt->qtybins;i++)
+ {
+ for(nh=nt->cstr[i];nh!=NULL;nh=next)
+ {
+ assert(nh->magic==NAME_MAGIC);
+ next=nh->cstr;
+ free(nh);
+ }
+ }
+ free(nt->cstr);
+ free(nt->cref);
+ free(nt);
+ }
+}
diff --git a/spiceparser/names.h b/spiceparser/names.h
new file mode 100644
index 0000000..94e2ec8
--- /dev/null
+++ b/spiceparser/names.h
@@ -0,0 +1,62 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* names.h, definitions for name storage
+ Conrad Ziesler
+*/
+
+#ifndef __NAMES_H__
+#define __NAMES_H__
+#ifdef __NAMES_PRIVATE__
+
+#define NAME_MAGIC 0x52a01250
+typedef struct name_hash_st
+{
+ int magic;
+ struct name_hash_st *cref,*cstr;
+ int refp;
+ char str[1];
+}namehash_t;
+
+typedef struct names_st
+{
+ namehash_t **cref,**cstr;
+ int avg_refl;
+ int avg_strl;
+ int qtybins;
+ int qtynames;
+ int namebytes;
+ int bytesalloc;
+}names_t;
+#else
+
+struct names_st;
+typedef struct names_st names_t;
+#endif
+
+char *names_stats(names_t *nt);
+char *names_lookup(names_t *nt, int refp);
+int names_check(names_t *nt, const char *name);
+void names_add(names_t *nt, int refp, const char *name);
+names_t *names_new(void);
+void names_free(names_t *nt);
+void names_rehash(names_t *nt, int newbins); /* private-ish */
+
+#endif
diff --git a/spiceparser/netlist.c b/spiceparser/netlist.c
new file mode 100644
index 0000000..29dba7c
--- /dev/null
+++ b/spiceparser/netlist.c
@@ -0,0 +1,686 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist.c, generalized netlist functions
+Conrad Ziesler
+*/
+#include <stdio.h>
+/* note:
+
+ we try to store a netlist in a form which is as compact as possible, while being extensible
+ by clients, in addition to being general enough to handle all possible netlist input formats
+
+ the primary memory saving device is the termptr_t bitfield, where we make a complex
+ pointer which represents the type of node it points to.
+
+ also we statically allocate memory for the devices using list_t blocks.
+ and allocate extra space per device as defined by the client structure
+
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "debug.h"
+
+#define __NETLIST_PRIVATE__
+#include "netlist.h"
+#include "mergedup.h"
+
+
+/* call these at entry and exit of all netlist functions that potentially modify equations */
+void netlist_eqn_begin(netlist_t *nl)
+{
+ assert(nl->eqn_mem!=NULL);
+ eqn_mem_push(nl->eqn_mem);
+}
+
+void netlist_eqn_end(netlist_t *nl)
+{
+ if(eqn_mem_pop()!=nl->eqn_mem)
+ assert(0);
+}
+
+
+/* some assumptions we make about bitfield encodings */
+int netlist_machine(void)
+{
+ assert(sizeof(termptr_t)==sizeof(void*));
+ assert(sizeof(unsigned int) == sizeof(void*));
+ assert(sizeof(unsigned int) == 4 );
+ return 0;
+}
+
+termptr_t netlist_termptr_null_t(termptr_t from)
+{
+ from.nonnull=0;
+ return from;
+}
+
+termptr_t netlist_termptr_null(void)
+{
+ termptr_t v;
+ v.nonnull=0;
+ v.termi=0;
+ v.devi=0;
+ v.devt=0;
+ return v;
+}
+
+termptr_t netlist_termptr_nonnull(termptr_t from)
+{
+ from.nonnull=1;
+ return from;
+}
+
+
+termptr_t netlist_termptr(int dev, int term, int type)
+{
+ termptr_t t;
+ t.termi=term;
+ t.devi=dev;
+ t.devt=type;
+ t.nonnull=1;
+ return t;
+}
+
+int netlist_termptr_devi(termptr_t t)
+{ return t.devi; }
+
+int netlist_termptr_termi(termptr_t t)
+{ return t.termi; }
+
+int netlist_termptr_devt(termptr_t t)
+{ return t.devt; }
+
+termptr_t netlist_termptr_deref(netlist_t *nl, termptr_t t)
+{
+ assert(t.devt>=0);
+ assert(t.devt<nl->qe);
+ assert(t.termi>=0);
+ assert(t.termi<nl->e[t.devt].qterms);
+ assert(t.nonnull==1);
+ return NETLIST_TERM(nl,t.devt,t.devi,t.termi);
+}
+
+int netlist_node_termptr(netlist_t *nl, termptr_t t)
+{
+ while(t.devt!=DEVT_NODE)
+ t=netlist_termptr_deref(nl,t);
+ return t.devi;
+}
+
+
+int netlist_add_dev_(netlist_t *nl, int devt, void *p)
+{
+ int i;
+ assert(devt>=0);
+ assert(devt<nl->qe);
+ i=list_add(&(nl->e[devt].l),p);
+ return i;
+}
+
+int netlist_add_dev(netlist_t *nl, int devt)
+{
+ int i;
+ assert(devt>=0);
+ assert(devt<nl->qe);
+ i=list_nextz(&(nl->e[devt].l));
+ return i;
+}
+
+/* merge duplicate entities summing results
+ the user function tocompare returns a ptr to some static area
+ which is filled with data that should be sorted and matched to
+
+ the user function sum takes the indices of the two entities
+ and performs the equivilent of [a]=[a]+[b]
+ if sum returns 1 we remove item b
+ so sum should frees any private data associated with [b] on 1
+*/
+
+void netlist_merge(netlistfunc_t *nm)
+{
+ mergedup_t *md;
+ int i,ib,ia;
+ void *data;
+ char *buffer;
+ list_t *entity=&(nm->entity->l);
+ list_t newl;
+
+ if(nm->tocompare==NULL)return;
+ if(nm->sum==NULL)return;
+ if(nm->qcmp<=0)return;
+ buffer=malloc(nm->qcmp);
+ assert(buffer!=NULL);
+ memset(buffer,0,nm->qcmp);
+
+ md=mergedup_alloc(list_qty(entity),nm->qcmp);
+
+ list_iterate(entity,i,data)
+ {
+ nm->tocompare(nm,i,buffer);
+ mergedup_fill(md,buffer,i);
+ }
+ free(buffer);
+ buffer=NULL;
+ mergedup_sort(md);
+ ib=-1;
+ ia=-1;
+ while(1)
+ {
+ ib=mergedup_visit(md,0); /* get next same */
+ if(ib==-1)
+ {
+ i=ia;
+ ia=mergedup_visit(md,1); /* get next different */
+ if(ia==-1)break;
+ }
+ else
+ {
+ if(nm->sum(nm,ia,ib))
+ {
+ /* flag delete item */
+ mergedup_setbit(md,ib);
+ }
+ }
+
+ }
+
+ ia=0; /* count number of remaining elements */
+ for(i=0;i<list_qty(entity);i++)
+ if(!mergedup_testbit(md,i))ia++;
+
+ list_copyfrom(&newl,entity); /* setup new list */
+ list_hint(&newl,ia); /* pre-alloc data */
+ list_iterate(entity,i,data) /* fill new list */
+ {
+ if(!mergedup_testbit(md,i))
+ list_add(&newl,data);
+ }
+ mergedup_free(md); /* free mergedup */
+ list_empty(entity); /* free old list data */
+ *entity=newl; /* copy over new pointers into old list */
+}
+
+
+/* distribute some attribute across entity
+
+ network of entities, connected via nodes.
+ some attribute associated with an entity terminal
+ first accumulate properties per node
+ then distribute to all entities connected to that node
+
+ ie: extract programs lump diffusion on one fet instead of distributing it as per width
+ for resizing
+*/
+
+void netlist_distribute(netlistfunc_t *nm)
+{
+ int i,j;
+ netlist_t *nl=nm->nl;
+ list_t *entity=&(nm->entity->l);
+ entity_t *e=nm->entity;
+ int qterm=nm->entity->qterms;
+ float *node_sums;
+
+ if(nm->qproperties<=0)return;
+
+ node_sums=malloc(sizeof(float)*list_qty(&(nl->e[DEVT_NODE].l))*nm->qproperties);
+ assert(node_sums!=NULL);
+
+ for(i=0;i< (list_qty(&(nl->e[DEVT_NODE].l))*nm->qproperties);i++)
+ node_sums[i]=0.0;
+
+ list_iterate_(entity,i)
+ {
+ for(j=0;j<qterm;j++)
+ {
+ termptr_t t;
+ float *node_data;
+ t=NETLIST_E_TERM(e,i,j);
+ node_data=node_sums+ (netlist_termptr_devi(t)*nm->qproperties) ;
+ if(nm->accumulate!=NULL)
+ nm->accumulate(nm,i,j,node_data);
+ }
+ }
+
+ list_iterate_(entity,i)
+ {
+ for(j=0;j<qterm;j++)
+ {
+ termptr_t t;
+ float *node_data;
+ t=NETLIST_E_TERM(e,i,j);
+ node_data=node_sums+ (netlist_termptr_devi(t)*nm->qproperties) ;
+ if(nm->distribute!=NULL)
+ nm->distribute(nm,i,j,node_data);
+ }
+ }
+ free(node_sums);
+}
+
+
+
+/* fixup netlist node pointers
+
+ when we first build a netlist, we have a many to one relationship
+ for the entity terminals, ie. they all point to the associated node
+
+ we also want to be able to enumerate the list of entity terminals on
+ a given net, without going through all entities and comparing.
+
+ thus we have to fixup the netlist, making a linked list out of the terminal ptrs
+
+ so we can walk through all the terminals on a net.
+ also we put the actual node on the head of that list.
+
+ we call a user function for each terminal on the net (to store back pointer if necessary)
+*/
+
+void netlist_fixup(netlistfunc_t *nm)
+{
+ netlist_t *nl=nm->nl;
+ int i,j,k;
+ int qterms;
+ termptr_t t,nt;
+
+ void *dp;
+ void *np;
+
+ /* init tail ptrs, to point to the head ptr */
+ list_iterate(&(nl->e[DEVT_NODE].l),i,np)
+ {
+ termptr_t t;
+ NETLIST_TERM(nl,DEVT_NODE,i,1)=t=netlist_termptr(i,0,DEVT_NODE);
+ NETLIST_TERM(nl,DEVT_NODE,i,0)=netlist_termptr_null_t(t);
+ }
+
+ for(i=0;i<nl->qe;i++)
+ {
+ qterms=nl->e[i].qterms;
+ list_iterate(&(nl->e[i].l),j,dp)
+ {
+ for(k=0;k<qterms;k++)
+ {
+ termptr_t npn1;
+ t=NETLIST_TERM(nl,i,j,k);
+ assert(t.devt==DEVT_NODE);
+ nt=NETLIST_TERM(nl,t.devt,t.devi,1); /* tail ptr */
+ npn1=NETLIST_TERM(nl,t.devt,t.devi,1)=netlist_termptr(j,k,i);
+ NETLIST_TERM(nl,nt.devt,nt.devi,nt.termi)=npn1; /* also links n[0] */
+ /* call user routine if not avail */
+ if(nm->fixup!=NULL)
+ nm->fixup(nm,t);
+ }
+ }
+ }
+}
+
+
+
+int netlist_findnode(netlist_t *nl, char *str)
+{
+ int pindex;
+ pindex=names_check(nl->names,str);
+ return pindex;
+}
+
+
+termptr_t netlist_node(netlist_t *nl, char *str, void *parent)
+{
+ int pindex;
+ termptr_t tp;
+ if(0)fprintf(stderr,"\nnode %s %p\n",str,parent);
+ pindex=names_check(nl->names,str);
+ if(pindex==-1)
+ {
+ pindex=netlist_add_dev(nl,DEVT_NODE);
+ names_add(nl->names,pindex,str);
+ tp=netlist_termptr(pindex,0,DEVT_NODE);
+ NETLIST_TERM(nl,DEVT_NODE,pindex,0)=tp;
+ NETLIST_TERM(nl,DEVT_NODE,pindex,1)=tp;
+ }
+ else
+ {
+ tp=netlist_termptr(pindex,0,DEVT_NODE);
+ }
+ return tp;
+}
+
+
+
+int netlist_newdev_fromnode(netlist_t *nl, int devt, dev_input_t parent , termptr_t n[])
+{
+ int q,qv,i,index;
+
+ qv =NETLIST_QVALS (nl,devt);
+ q =NETLIST_QTERMS (nl,devt);
+
+ index=netlist_add_dev(nl,devt);
+ NETLIST_PARENT(nl,devt,index)=parent;
+
+ for(i=0;i<q;i++)
+ NETLIST_TERM(nl,devt,index,i)=n[i];
+
+ for(i=0;i<qv;i++)
+ NETLIST_VAL(nl,devt,index,i)=eqn_empty();
+
+ return index;
+}
+
+
+void netlist_init(netlist_t *nl)
+{
+ int i;
+ entity_t e=ENTITY_INVALID;
+ netlist_machine();
+ for(i=0;i<TERMPTR_MAX_DEVT;i++)
+ nl->e[i]=e;
+ nl->qe=0;
+ nl->names=names_new();
+ nl->input.p=NULL;
+ nl->eqn_mem=eqn_mem_new();
+ nl->iscopy=0;
+ eqnl_init(&(nl->eqnl));
+}
+
+
+int netlist_register_entity (netlist_t *nl, int id, int qterms, int qvals, int qrest, char *sym, int othersize)
+{
+ entity_t *ep;
+
+ if(nl->qe>=TERMPTR_MAX_DEVT)
+ return -1;
+
+ ep=&(nl->e[nl->qe]);
+ nl->qe++;
+ ep->id=id;
+ ep->qterms=qterms;
+ ep->qvals=qvals;
+ strncpy(ep->sym,sym,8);
+ ep->sym[7]=0;
+ ep->qcount=0;
+ ep->qother=qrest;
+ list_init(&(ep->l),NETLIST_OFFSET_OTHER((*ep))+othersize,LIST_DEFMODE);
+ return nl->qe-1;
+}
+
+netlist_input_t netlist_parse_input(scanner_t *scan, char *type, netlist_param_t *params)
+{
+ netlist_input_t p;
+
+ netlist_machine();
+ p.p=NULL;
+
+ if(strcmp(type,"spice")==0)
+ {
+ p.spice=spice_new(scan);
+ }
+ if(strcmp(type,"extract")==0)
+ {
+ /* p.ext=extract_new(scan); */
+ }
+ if(p.p==NULL)
+ parse_error(scan, "Netlist: can't parse input of type %s",type);
+ return p;
+}
+
+
+
+void netlist_debug_input(void * dbg_fp, netlist_input_t p)
+{
+ FILE *dbg=dbg_fp;
+ netlist_machine();
+
+ if(p.p==NULL)
+ fprintf(dbg, "can't debug netlist input, null ptr");
+
+ if(p.generic->magic==SPICE_MAGIC)
+ spice_debug(dbg,p.spice);
+
+ else if(p.generic->magic==EXTRACT_MAGIC)
+ /* p.ext=extract_debug(dbg,p.extract) */ ;
+
+}
+
+void netlist_debug(void * dbg_fp, netlist_t *nl)
+{
+ netlist_debug_(dbg_fp,nl,0);
+}
+
+
+void netlist_debug_(void * dbg_fp, netlist_t *nl, int eval)
+{
+ FILE *dbg=dbg_fp;
+ int i;
+
+ if(nl==NULL)
+ fprintf(dbg,"can't debug netlist, null ptr");
+
+ if(eval)
+ {
+ if(0)fprintf(stderr,"\n\nbegin evaldep \n\n");
+ eqnl_evaldep(&(nl->eqnl));
+ if(0)fprintf(stderr,"\n\ndone evaldep \n\n");
+ }
+
+ fprintf(dbg,"debugging netlist eval=%i, %p\n",eval,nl);
+ for(i=0;i<nl->qe;i++)
+ {
+ entity_t *e;
+ int j;
+ eqn_t *v;
+
+ e=nl->e+i;
+ fprintf(dbg," e %i %s, qterm=%i qcount=%i l.q,m=%i,%i\n",
+ i,e->sym,e->qterms,e->qcount,e->l.q,e->l.m
+ );
+ list_iterate_(&(e->l),j)
+ {
+ int k;
+ fprintf(dbg,"%i: ",j);
+
+ for(k=0;k<e->qterms;k++)
+ {
+ termptr_t t=NETLIST_E_TERM(e,j,k);
+ fprintf(dbg," [%i %s.%i]",t.devi,nl->e[t.devt].sym,t.termi);
+ if(i==DEVT_NODE)
+ fprintf(dbg,"=%s ",names_lookup(nl->names,j));
+ }
+ fprintf(dbg,"\n ");
+
+ v=NETLIST_VALS(nl,i,j);
+ for(k=0;k<e->qvals;k++)
+ {
+ if(!eval)
+ {
+ char buf[32];
+ sprintf(buf," %i",k);
+ debug_eqn(dbg,buf,v+k);
+ fprintf(dbg," ");
+ }
+ else
+ {
+ float f;
+ f=eqnl_eval(&(nl->eqnl),v[k]);
+ fprintf(dbg," ev %g ",f);
+ }
+ }
+ fprintf(dbg,"\n");
+ }
+ }
+}
+
+
+
+
+
+/* release input from netlist (free structures if possible)
+ after this call, all parent ptrs and input ptrs are set to null
+*/
+void netlist_release(netlist_t *nl)
+{
+ int i,j;
+
+ /* reset all the parent ptrs to null */
+ for(i=0;i<nl->qe;i++)
+ {
+ list_iterate_(&(nl->e[i].l),j)
+ NETLIST_PARENT(nl,i,j).p=NULL;
+ }
+
+ /* call low level free function */
+ switch(nl->input.generic->magic)
+ {
+ case SPICE_MAGIC:
+ spice_release(nl->input.spice);
+ break;
+
+ case EXTRACT_MAGIC:
+ /* extract_release(nl->input.ext); */
+ break;
+ }
+ nl->input.p=NULL;
+}
+
+
+
+/* this releases input if not already done
+ and then frees up the memory associated with the netlist
+ any additional client memory should already have been freed
+*/
+
+void netlist_free(netlist_t *nl)
+{
+ int i;
+ if(nl!=NULL)
+ {
+ if(nl->input.p!=NULL)
+ netlist_release(nl);
+
+ for(i=0;i<TERMPTR_MAX_DEVT;i++)
+ list_empty(&(nl->e[i].l));
+
+ eqn_mem_free(nl->eqn_mem);
+ nl->eqn_mem=NULL;
+ if(!nl->iscopy)
+ {
+ eqnl_free(&(nl->eqnl));
+ names_free(nl->names);
+ }
+ free(nl);
+ nl=NULL;
+ }
+}
+
+
+
+int netlist_print_nodep(netlist_t *n, netprint_t grp, void * file_fp, void *gn, char *str)
+{
+ FILE *file=file_fp;
+ int index=-1;
+ const char *err="node_error";
+ char *name="error";
+ int i;
+
+ fprintf(file,"%s",str);
+ if(n!=NULL)
+ index=list_index(&(n->e[DEVT_NODE].l),gn);
+
+ switch(grp)
+ {
+ case netprint_none:
+ break;
+ case netprint_name:
+ if(index!=-1)
+ fprintf(file,"%s",names_lookup(n->names,index));
+ else fprintf(file,err);
+ break;
+ case netprint_index:
+ if(index!=-1)
+ fprintf(file,"n%i",index);
+ else fprintf(file,err);
+ case netprint_ptr:
+ fprintf(file,"N_%p",gn);
+ case netprint_nname:
+ if(index!=-1)
+ name=names_lookup(n->names,index);
+ i=strlen(name)-8;
+ if(i<0)i=0;
+ fprintf(file,"N%i_%s",index,name+i);
+ break;
+
+ case netprint_debug:
+ if(index!=-1)
+ fprintf(file,"[Node %p %i %s]",gn,index,names_lookup(n->names,index));
+ else
+ fprintf(file,"[Node %p]",gn);
+ break;
+ }
+ return 0;
+}
+
+void netlist_eval(netlist_t *n)
+{
+ eqnl_evaldep(&(n->eqnl));
+}
+
+
+
+/* this is somewhat inefficient, please don't rely on it */
+netlist_t *netlist_copyisher(netlist_t *in, int extrasize, int extrasizes[])
+{
+ char buffer[4096];
+ int i,j,sin;
+ void *p;
+ netlist_t *nl;
+ netlist_machine();
+ nl=malloc(sizeof(netlist_t)+extrasize);
+ assert(nl!=NULL);
+ netlist_init(nl);
+ nl->iscopy=1;
+ for(i=0;i<in->qe;i++)
+ {
+ entity_t *ep;
+ int index;
+ ep=in->e+i;
+ index=netlist_register_entity(nl,ep->id,ep->qterms,ep->qvals,ep->qother,ep->sym,extrasizes[i]);
+ assert(sizeof(buffer)> (extrasizes[i]+NETLIST_OFFSET_OTHER((*ep))));
+ assert(index>=0);
+ memset(buffer,0,sizeof(buffer));
+ sin=list_sizeof(&(in->e[i].l));
+ list_hint(&(nl->e[index].l),sin);
+ list_iterate(&(ep->l),j,p)
+ {
+ memcpy(buffer,p,sin); /* yes, we copy twice. this is required, think about it */
+ list_add(&(nl->e[index].l),buffer);
+ }
+ }
+
+ /* POTENTIAL MEMORY LEAK HERE */
+ nl->names=in->names; /* share name database */
+ nl->eqnl=in->eqnl; /* share eqnl database */
+ nl->input.p=NULL; /* flag this to null */
+
+ return nl;
+}
+
+
diff --git a/spiceparser/netlist.h b/spiceparser/netlist.h
new file mode 100644
index 0000000..2945cc0
--- /dev/null
+++ b/spiceparser/netlist.h
@@ -0,0 +1,282 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist.h, headers for generic netlist wrappers
+Conrad Ziesler
+*/
+
+/* even though the different file formats (spice, magic extract, verilog)
+ have widely different requirements, the basic information is still
+ comparable, so we try to build a common interface to the subtype procedures
+*/
+
+#ifndef __NETLIST_H__
+
+
+#ifndef __LIST_H__
+#include "list.h"
+#endif
+
+
+#ifndef __NAMES_H__
+#include "names.h"
+#endif
+
+#ifndef __EQN_H__
+#include "eqn.h"
+#endif
+
+#ifndef __SCANNER_H__
+#include "scanner.h"
+#endif
+
+#define __NETLIST_H__
+
+struct extract_st;
+struct spice_st;
+
+#define EXTRACT_MAGIC 0x55315662
+#define SPICE_MAGIC 0x435acde0
+
+
+typedef struct geninput_st
+{
+ int magic;
+ int other[4];
+}geninput_t;
+
+
+/* internal definition of netlist type */
+typedef union netlist_input_un
+{
+ void *p;
+ geninput_t *generic;
+ struct spice_st *spice;
+ struct extract_st *ext;
+}netlist_input_t;
+
+typedef union dev_input_un
+{
+ void *p;
+ struct m_st *spice_fet;
+ struct c_st *spice_cap;
+ void *spice_res;
+ void *extract_fet;
+ void *extract_cap;
+ void *extract_res;
+}dev_input_t;
+
+
+
+
+
+
+/* compact netlist:
+
+ device is: object with k terminals (k small)
+ netlist is connection of devices
+
+ share common terminal pointer.
+
+*/
+
+
+#define TERMPTR_BITS_DEVI 24
+#define TERMPTR_BITS_TERMI 3
+#define TERMPTR_BITS_DEVT 4
+
+typedef struct termptr_st
+{
+ unsigned devi: TERMPTR_BITS_DEVI;
+ unsigned nonnull: 1;
+ unsigned termi: TERMPTR_BITS_TERMI;
+ unsigned devt: TERMPTR_BITS_DEVT;
+}termptr_t;
+
+#define TERMPTR_MAX_DEVI ((1<<TERMPTR_BITS_DEVI)-1)
+#define TERMPTR_MAX_TERMI ((1<<TERMPTR_BITS_TERMI)-1)
+#define TERMPTR_MAX_DEVT ((1<<TERMPTR_BITS_DEVT)-1)
+#define netlist_termptr_isnull(t) (t.nonnull==0)
+
+
+/**** entities:
+
+ an entity_t describes and holds a list of devices
+
+ the flexible device structure is formatted as follows
+ {
+ dev_input_t parent;
+ termptr_t terms[e->qterms];
+ eqn_t vals[e->qvals];
+ rest....
+ }
+
+*****/
+
+typedef struct entity_st
+{
+ list_t l;
+ int qterms; /* q terms of in generic structure */
+ int qvals; /* q values in generic structure */
+ int qcount; /* counted number, low level */
+ int id; /* uniq device id */
+ int qother; /* bytes of other info in dev structure */
+ char sym[8]; /* symbolic name */
+}entity_t;
+
+#define ENTITY_INVALID { LIST_INITDATA, 0, 0, 0, -1,0, "INVALID" }
+
+/* macros for accessing entities */
+
+#define NETLIST_E(nl,t,i) ((void *)list_data(&((nl)->e[(t)].l),i))
+#define NETLIST_E_DATA(nl,t,i) ((char *)NETLIST_E(nl,t,i))
+#define NETLIST_ED(e,i) ((char *)(list_data(&(e->l),i)))
+#define NETLIST_OFFSET_PARENT(e) (0)
+#define NETLIST_PARENTS(nl,t,i) ((dev_input_t*) (NETLIST_E_DATA(nl,t,i)+NETLIST_OFFSET_PARENT(nl->e[t])))
+#define NETLIST_PARENT(nl,t,i) (NETLIST_PARENTS((nl),(t),(i))[0])
+
+#define NETLIST_OFFSET_TERMS(e) (sizeof(dev_input_t) + NETLIST_OFFSET_PARENT(e) )
+#define NETLIST_TERMS(nl,t,i) ((termptr_t*)(NETLIST_E_DATA(nl,t,i)+NETLIST_OFFSET_TERMS(nl->e[t])))
+#define NETLIST_TERM(nl,t,i,j) (NETLIST_TERMS(nl,t,i)[(j)])
+#define NETLIST_E_TERMS(e,i) ((termptr_t*) (NETLIST_ED(e,i) + NETLIST_OFFSET_TERMS(*(e))))
+#define NETLIST_E_TERM(e,i,j) (NETLIST_E_TERMS(e,i)[(j)])
+
+#define NETLIST_OFFSET_VALS(e) (NETLIST_OFFSET_TERMS((e)) + ((e).qterms*sizeof(termptr_t)))
+#define NETLIST_VALS(nl,t,i) ((eqn_t *) (NETLIST_E_DATA(nl,t,i)+NETLIST_OFFSET_VALS(nl->e[t])))
+#define NETLIST_VAL(nl,t,i,j) (NETLIST_VALS(nl,t,(i))[(j)])
+
+
+#define NETLIST_OFFSET_REST(e) ( NETLIST_OFFSET_VALS(e) + (sizeof(eqn_t)*((e).qvals)))
+#define NETLIST_REST(nl,t,i) ((void *) (NETLIST_E_DATA(nl,t,i) + NETLIST_OFFSET_REST(nl->e[t]))
+
+#define NETLIST_OFFSET_OTHER(e) ( NETLIST_OFFSET_REST(e) + (e).qother )
+#define NETLIST_OTHER(nl,t,i) ((void *) (NETLIST_E_DATA(nl,t,i)+NETLIST_OFFSET_OTHER(nl->e[t])))
+
+#define NETLIST_E_QTERMS(e) ((e)->qterms)
+#define NETLIST_QTERMS(nl,t) ((nl)->e[t].qterms)
+#define NETLIST_E_QVALS(e) ((e)->qvals)
+#define NETLIST_QVALS(nl,t) ((nl)->e[t].qvals)
+
+#define DEVT_NODE 0 /* all netlists have type 0 as a node */
+#define DEVP(nl,t) list_data(&((nl)->e[(t).devt].l),(t).devi)
+#define DEVT_NODE_TERMS 2
+
+typedef struct devnode_st
+{
+ dev_input_t parent;
+ termptr_t n[DEVT_NODE_TERMS];
+}devnode_t;
+
+
+typedef struct netlist_st
+{
+ netlist_input_t input; /* where the netlist came from */
+ void *eqn_mem; /* where we store our equations */
+ int iscopy; /* this is set if we shouldn't free/modify some structures */
+ names_t *names; /* key off of node indices */
+ eqnlist_t eqnl;
+ int qe; /* valid entities */
+ entity_t e[TERMPTR_MAX_DEVT];
+}netlist_t;
+
+
+
+
+
+typedef struct netlistfunc_st
+{
+ netlist_t *nl;
+ entity_t *entity;
+
+ /* for merge */
+ int qcmp;
+ int (*sum)(struct netlistfunc_st *nm,int ia, int ib);
+ void (*tocompare)(struct netlistfunc_st *nm, int index, void *data);
+
+ /* for distribute */
+ int qproperties;
+ void (*accumulate)(struct netlistfunc_st *nm, int devi, int termi, float *nodeprops);
+ void (*distribute)(struct netlistfunc_st *nm, int devi, int termi, float *nodeprops);
+
+ /* for fixup */
+ void (*fixup)(struct netlistfunc_st *nm, termptr_t t);
+
+}netlistfunc_t;
+
+typedef struct netlist_param_st
+{
+ struct netlist_param_st *next;
+ char str[4];
+}netlist_param_t;
+
+
+
+typedef enum netprint_en
+{
+ netprint_none,
+ netprint_name,
+ netprint_index,
+ netprint_ptr,
+ netprint_nname,
+ netprint_debug
+}netprint_t;
+
+
+
+
+/******* netlist.c ********/
+void netlist_init(netlist_t *nl);
+int netlist_register_entity (netlist_t *nl, int id, int qterms, int qvals, int qrest, char *sym, int othersize);
+int netlist_print_nodep(netlist_t *n, netprint_t grp, void *filefp, void *gn, char *str);
+netlist_input_t netlist_parse_input(scanner_t *scan, char *type, netlist_param_t *params);
+void netlist_release(netlist_t *nl);
+void netlist_free(netlist_t *nl);
+int netlist_newdev_fromnode(netlist_t *nl, int devt, dev_input_t parent , termptr_t n[]);
+void netlist_debug_input(void *dbg_fp, netlist_input_t p);
+void netlist_debug(void *dbg_fp, netlist_t *nl);
+void netlist_debug_(void *dbg_fp, netlist_t *nl, int eval);
+termptr_t netlist_node(netlist_t *nl, char *str, void *parent);
+termptr_t netlist_termptr(int dev, int term, int type);
+int netlist_node_termptr(netlist_t *nl, termptr_t t);
+int netlist_findnode(netlist_t *nl, char *str);
+void netlist_merge(netlistfunc_t *nm);
+void netlist_distribute(netlistfunc_t *nm);
+void netlist_fixup(netlistfunc_t *nm);
+void netlist_eval(netlist_t *n);
+void netlist_eqn_begin(netlist_t *nl);
+void netlist_eqn_end(netlist_t *nl);
+
+netlist_t *netlist_copyisher(netlist_t *in, int extrasize, int extrasizes[]);
+void netlist_copyfree(netlist_t *nl);
+
+
+/********* netlist_spice.c *********/
+
+struct spice_st *spice_new(scanner_t *scan);
+void spice_release(struct spice_st *sp);
+
+void spice_build(netlist_t *nl);
+void spice_count(netlist_t *nl);
+void spice_debug(void *dbg_fp, struct spice_st *sp);
+
+
+
+#endif
+
diff --git a/spiceparser/netlist_dev.c b/spiceparser/netlist_dev.c
new file mode 100644
index 0000000..2438e22
--- /dev/null
+++ b/spiceparser/netlist_dev.c
@@ -0,0 +1,198 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_dev.c, netlist functions for netlists of circuital devices (ie fets)
+ Conrad Ziesler
+*/
+
+
+/* our goal here is to provide all the netlist convenience functions
+ which are dependent on the particular definitions for the devices (ie hard coded device types)
+ by device netlists we refer to netlists to be fed to spice-like simulators.
+
+ this was split off the core device-independent netlist routines
+*/
+
+#include <stdio.h>
+#include "debug.h"
+
+#include "netlist_dev.h"
+
+
+/* make a new device netlist, using client sizes as given
+ ni is ptr returned by netlist_parse_input
+*/
+
+
+netlist_t *netlist_devnew_inplace(netlist_input_t ni, int extrasize, int extrasizes[DEVT_MAX])
+{
+ int i,r;
+ int terms[]=DEVT_TERMS;
+ int vals[]=DEVT_VALS;
+ char *syms[]=DEVT_SYMS;
+ int others[]=DEVT_OTHERS;
+ netlist_t *nl;
+
+ nl=malloc(sizeof(netlist_t)+extrasize);
+ assert(nl!=NULL);
+ netlist_init(nl);
+
+ for(i=0;i<DEVT_MAX;i++)
+ {
+ r=netlist_register_entity(nl,i,terms[i],vals[i],others[i],syms[i],extrasizes[i]);
+ assert(r==i);
+ }
+
+ nl->input=ni;
+ if(ni.p!=NULL)
+ {
+ switch(ni.generic->magic)
+ {
+ case SPICE_MAGIC:
+ spice_count(nl);
+
+ for(i=0;i<DEVT_MAX;i++)
+ if(nl->e[i].qcount>0)
+ list_hint(&(nl->e[i].l),nl->e[i].qcount);
+
+ spice_build(nl);
+ break;
+ case EXTRACT_MAGIC:
+ /*
+ extract_count(nl);
+ for(i=0;i<DEVT_MAX;i++)
+ if(nl->e[i].qcount>0)
+ list_hint(&(nl->e[i].l),nl->e[i].qcount);
+ extract_build(nl);
+ */
+ break;
+ }
+ }
+ return nl;
+}
+
+netlist_t *netlist_devnew(netlist_input_t ni)
+{
+ int sz[DEVT_MAX];
+ memset(sz,0,sizeof(sz));
+ return netlist_devnew_inplace(ni, 0, sz);
+}
+
+
+/**** output spice_like file ****/
+
+void netlist_o_spice(void *of_fp, netlist_t *nl, int n_start)
+{
+ FILE *of=of_fp;
+ int i,j,k;
+ int m_i=1, c_i=1, l_i=1, i_i=1, v_i=1;
+
+ devall_p p;
+ entity_t *e;
+ int nodes[32];
+ float vals[32];
+ eqn_t *v;
+
+ if(nl==NULL) return;
+ eqnl_evaldep(&(nl->eqnl));
+
+ fprintf(of,"*** netlist output \n");
+ for(i=0;i<DEVT_MAX;i++)
+ {
+ e=nl->e+i;
+ assert(e->qterms<(sizeof(nodes)/sizeof(int)));
+ assert(e->qvals<(sizeof(vals)/sizeof(float)));
+
+ list_iterate(&(e->l),j,p.p)
+ {
+ for(k=0;k<e->qterms;k++)
+ nodes[k]=n_start+netlist_node_termptr(nl,p.genp->n[k]);
+
+ v=NETLIST_VALS(nl,i,j);
+ for(k=0;k<e->qvals;k++)
+ vals[k]=eqnl_eval(&(nl->eqnl),v[k]);
+
+ switch(e->id)
+ {
+ case DEVT_NODE: /* output a mini node-name directory */
+ fprintf(of,"* %i %s\n",j+n_start,names_lookup(nl->names,j));
+ break;
+
+ case DEVT_FET:
+ fprintf(of,"m%i %i %i %i %i %s L=%g W=%g AS=%g AD=%g PS=%g PD=%g\n",m_i++,
+ nodes[DEVFET_S],nodes[DEVFET_G],nodes[DEVFET_D], nodes[DEVFET_B],
+ (p.fetp->type==DEVFET_nmos)?"n":"p",
+ vals[DEVFET_l],vals[DEVFET_w], vals[DEVFET_as],
+ vals[DEVFET_ad], vals[DEVFET_ps], vals[DEVFET_pd]
+ );
+ break;
+ case DEVT_CAP:
+ fprintf(of,"c%i %i %i %g\n",c_i++,
+ nodes[DEV2TERM_P], nodes[DEV2TERM_N], vals[DEVCAP_c]
+ );
+ break;
+ case DEVT_RES:
+ fprintf(of,"c%i %i %i %g\n",c_i++,
+ nodes[DEV2TERM_P], nodes[DEV2TERM_N], vals[DEVRES_r]
+ );
+ break;
+ case DEVT_IND:
+ fprintf(of,"l%i %i %i %g\n",l_i++,
+ nodes[DEV2TERM_P], nodes[DEV2TERM_N], vals[0]
+ );
+ break;
+ case DEVT_VSRC:
+ fprintf(of,"v%i %i %i %g\n",v_i++,
+ nodes[DEV2TERM_P], nodes[DEV2TERM_N], vals[0]
+ );
+ break;
+ case DEVT_ISRC:
+ fprintf(of,"i%i %i %i %g\n",i_i++,
+ nodes[DEV2TERM_P], nodes[DEV2TERM_N], vals[0]
+ );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ fprintf(of,"*** end netlist output \n");
+}
+
+
+
+netlist_t *netlist_copyish(netlist_t *in, int size, int sizes[])
+{
+ int i;
+ int extras[TERMPTR_MAX_DEVT];
+ int defsize[DEVT_MAX]=NETLIST_DEFSIZES;
+ for(i=0;i<TERMPTR_MAX_DEVT;i++)
+ {
+ if(i<DEVT_MAX)
+ extras[i]=sizes[i]-defsize[i];
+ else extras[i]=0;
+
+ if(extras[i]<0)extras[i]=0;
+ assert(extras[i]<2048);
+ }
+
+ return netlist_copyisher(in,size-sizeof(netlist_t),extras);
+}
diff --git a/spiceparser/netlist_dev.h b/spiceparser/netlist_dev.h
new file mode 100644
index 0000000..d3b2ebd
--- /dev/null
+++ b/spiceparser/netlist_dev.h
@@ -0,0 +1,202 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_dev.h, definitions for a netlist of circuital devices
+ Conrad Ziesler
+*/
+#ifndef __NETLIST_DEV_H__
+#define __NETLIST_DEV_H__
+#ifndef __NETLIST_H__
+#include "netlist.h"
+#endif
+
+#define DEVNODE_HEAD 0
+#define DEVNODE_TAIL 1
+
+#define DEVFET_S 0
+#define DEVFET_D 1
+#define DEVFET_G 2
+#define DEVFET_B 3
+#define DEVFET_w 0
+#define DEVFET_l 1
+#define DEVFET_as 2
+#define DEVFET_ad 3
+#define DEVFET_ps 4
+#define DEVFET_pd 5
+#define DEVFET_V 6
+
+#define DEV2TERM_P 1
+#define DEV2TERM_N 0
+
+#define DEVCAP_c 0
+#define DEVCAP_V 1
+
+#define DEVRES_r 0
+#define DEVRES_V 1
+
+/* #define DEVT_NODE 0 defined in netlist.h */
+#define DEVT_FET 1
+#define DEVT_CAP 2
+#define DEVT_RES 3
+#define DEVT_IND 4
+#define DEVT_DIODE 5
+#define DEVT_VSRC 6
+#define DEVT_ISRC 7
+#define DEVT_BJT 8
+#define DEVT_MAX 9
+/* 0 1 2 3 4 5 6 7 8 */
+#define DEVT_TERMS { 2, 4, 2, 2, 2, 2, 2, 2, 4 }
+#define DEVT_SYMS { "NODE", "FET", "CAP", "RES", "IND", "DIODE", "VSRC", "ISRC", "BJT" }
+#define DEVT_VALS { 0, DEVFET_V, DEVCAP_V, DEVRES_V, 0 , 0, 0, 0 , 0 }
+#define DEVT_OTHERS { 0, sizeof(unsigned), 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0 , 0 }
+
+
+#define DEVP_NODE(nl,t) list_data(&((nl)->e[DEVT_NODE].l),(t).devi)
+#define DEVP_NODEt(nl,t) ((devnode_t *)DEVP_NODE((nl),(t)))
+
+#define DEVP_FET(nl,t) list_data(&((nl)->e[DEVT_FET].l),(t).devi)
+#define DEVP_FETt(nl,t) ((devfet_t *)DEVP_NODE((nl),(t)))
+
+#define DEVP_CAP(nl,t) list_data(&((nl)->e[DEVT_CAP].l),(t).devi)
+#define DEVP_CAPt(nl,t) ((devcap_t *)DEVP_NODE((nl),(t)))
+
+#define DEVGEN_V 8
+
+typedef struct devgen_st
+{
+ dev_input_t parent;
+ termptr_t n[TERMPTR_MAX_TERMI];
+ eqn_t v[DEVGEN_V];
+}devgen_t;
+
+#define DEVFET_nmos 1
+#define DEVFET_pmos 2
+
+typedef struct devfet_st
+{
+ dev_input_t parent;
+ termptr_t n[4];
+ eqn_t v[DEVFET_V];
+ unsigned type; /* n/p */
+}devfet_t;
+
+
+typedef struct devcap_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}devcap_t;
+
+
+typedef struct devres_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}devres_t;
+
+
+typedef struct devind_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}devind_t;
+
+
+typedef struct devvsrc_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}devvsrc_t;
+
+
+typedef struct devisrc_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}devisrc_t;
+
+
+typedef struct devdiode_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[4];
+}devdiode_t;
+
+
+typedef struct devbjt_st
+{
+ dev_input_t parent;
+ termptr_t n[4];
+ eqn_t v[4];
+}devbjt_t;
+
+typedef struct dev2term_st
+{
+ dev_input_t parent;
+ termptr_t n[2];
+ eqn_t v[1];
+}dev2term_t;
+
+typedef struct dev4term_st
+{
+ dev_input_t parent;
+ termptr_t n[4];
+ eqn_t v[1];
+}dev4term_t;
+
+typedef union devall_un
+{
+ void *p;
+ devgen_t *genp;
+ devnode_t *nodep;
+ devfet_t *fetp;
+ devcap_t *capp;
+ devind_t *indp;
+ devbjt_t *bjtp;
+ devvsrc_t *vsrcp;
+ devisrc_t *isrcp;
+}devall_p;
+
+
+#define NETLIST_DEFSIZES \
+ { \
+ sizeof(devnode_t) , sizeof(devfet_t), sizeof(devcap_t), sizeof(devres_t), \
+ sizeof(devind_t), sizeof(devdiode_t), sizeof(devvsrc_t), \
+ sizeof(devisrc_t) , sizeof(devbjt_t) \
+ }
+
+
+
+
+netlist_t *netlist_copyish(netlist_t *in, int size, int sizes[]);
+void netlist_o_spice(void *of_fp, netlist_t *nl, int n_start);
+netlist_t *netlist_devnew_inplace(netlist_input_t ni, int extrasize, int extrasizes[DEVT_MAX]);
+netlist_t *netlist_devnew(netlist_input_t ni);
+/********* netlist_funcs.c *********/
+netlistfunc_t * netlist_devfet_funcs(netlist_t *nl, netlistfunc_t *fp);
+
+#endif
+
diff --git a/spiceparser/netlist_extract.c b/spiceparser/netlist_extract.c
new file mode 100644
index 0000000..ac856f8
--- /dev/null
+++ b/spiceparser/netlist_extract.c
@@ -0,0 +1,550 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* extract.c : optional magic .ext file input (bypassing ext2spice)
+ links to magic's extract library
+ .ext files have more/better info than what's in the spice file,
+ which gives us better debugging info, and integration with the layout
+
+Conrad Ziesler
+*/
+
+
+/* this is loosely based on magic's extcheck sample program,
+ and links to the magic libraries, so if you don't have them, undef USE_EXTRACT_FORMAT
+
+ the following copyright notice was from extcheck.c, which this code was based on
+
+*/
+
+/*
+ * extcheck.c --
+ *
+ * *********************************************************************
+ * * Copyright (C) 1985, 1990 Regents of the University of California. *
+ * * Permission to use, copy, modify, and distribute this *
+ * * software and its documentation for any purpose and without *
+ * * fee is hereby granted, provided that the above copyright *
+ * * notice appear in all copies. The University of California *
+ * * makes no representations about the suitability of this *
+ * * software for any purpose. It is provided "as is" without *
+ * * express or implied warranty. Export of this software outside *
+ * * of the United States of America may require an export license. *
+ * *********************************************************************
+*/
+
+
+
+
+
+
+
+
+
+#include <stdio.h>
+#include <math.h>
+#include "debug.h"
+
+#include "netlist_extract.h"
+
+#ifndef __NETLIST_H__
+#include "netlist.h"
+#endif
+
+
+
+void *mymalloc(unsigned size)
+{
+ return malloc(size);
+}
+
+
+#define CHECK_EXTINIT(g) if(g!=NULL) if(g->input.generic->magic==EXTRACT_MAGIC) if(g->input.ext->did_EF_init_read)
+
+#ifdef USE_EXTRACT_FORMAT
+
+
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <varargs.h>
+
+#include "include/magic.h"
+#include "include/paths.h"
+#include "include/geometry.h"
+#include "include/hash.h"
+#include "include/utils.h"
+#include "include/pathvisit.h"
+#include "include/extflat.h"
+#include "include/runstats.h"
+
+
+int GeoScale(Transform *t);
+void EFInit(void);
+void EFReadFile(char *name);
+void EFFlatBuild(char *rootName, int flags);
+void EFFlatDone(void);
+void EFVisitFets(
+ int (*fetProc)(Fet *fet, HierName *hname, Transform *t, int l , int w, ClientData data),
+ ClientData cdata
+ );
+
+void EFVisitNodes(
+ int (*nodeProc)(EFNode *node, int r, double c, ClientData cdata),
+ ClientData cdata
+ );
+
+bool EFHNIsGlob(HierName *hname);
+char * EFHNToStr(HierName *hierName);
+
+void EFDone(void);
+
+
+static int ecNumFets;
+static int ecNumCaps;
+static int ecNumResists;
+static int ecNumThreshCaps;
+static int ecNumThreshResists;
+static int ecNumNodes;
+static int ecNumGlobalNodes;
+static int ecNumNodeCaps;
+static int ecNumNodeResists;
+
+
+
+#endif
+
+
+/*
+ make a new extract_t container
+ first create fake argc, *argv[] using extract options from config file
+*/
+
+#ifdef USE_EXTRACT_FORMAT
+extract_t *extract_new(char *rootname)
+{
+ extract_t *p;
+ int i;
+ assert(rootname!=NULL);
+ p=mymalloc(sizeof(extract_t)+(sizeof(char*)*(PARAMS.extract_qty+4)));
+ assert(p!=NULL);
+ memset(p,0,sizeof(extract_t));
+ p->root=strdup(rootname);
+ assert(p->root!=NULL);
+ p->extract_magic=EXTRACT_MAGIC;
+ p->ext_argv=(char **) (&p[1]);
+ p->ext_argv[0]="ext2spice";
+ for(i=1;i< (PARAMS.extract_qty+1);i++)
+ p->ext_argv[i]=PARAMS.extract_params[i-1];
+ p->ext_argv[i]=p->root;
+ p->ext_argv[i+1]=NULL;
+ p->ext_argc=i+1;
+ p->did_EF_init_read=0;
+
+
+
+ /* Process command line arguments */
+ EFInit();
+ p->fname = EFArgs(p->ext_argc, p->ext_argv, (int (*)()) NULL, (ClientData) NULL);
+ if(p->fname==NULL){ fprintf(stderr,"ERROR: extract configuration error\n"); return NULL; }
+
+ /* Read the hierarchical description of the input circuit */
+ EFReadFile(p->fname);
+
+ if(PARAMS.extfix!=NULL) /* tag with extfix data (merge Gnd/Vdd GND/VDD) */
+ EFReadFile(PARAMS.extfix);
+
+ if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
+ if (EFScale==0) EFScale = 1;
+ p->did_EF_init_read=1;
+
+ if(0)
+ {
+ fprintf(stderr,"EXT: %i layers defined\n",EFLayerNumNames);
+ for(i=0;i<EFLayerNumNames;i++)
+ fprintf(stderr,"EXT: layer %i=%s\n",i,EFLayerNames[i]);
+ }
+
+
+
+ return p;
+}
+
+#else
+
+extract_t *extract_new(char *rootname)
+{
+ return NULL;
+}
+#endif
+
+
+
+#ifndef USE_EXTRACT_FORMAT
+
+
+/****************** LINK TO MAGIC EXTFLAT LIBRARY ************/
+#else
+
+
+
+
+void extract_finish(graph_t *gr)
+{
+
+ EFFlatDone();
+ EFDone();
+
+ fprintf(stderr,"EXT: Memory used: %s\n", RunStats(RS_MEM, NULL, NULL));
+ fprintf(stderr,"EXT: %d fets\n", ecNumFets);
+ fprintf(stderr,"EXT: %d nodes (%d global, %d local)\n",
+ ecNumNodes, ecNumGlobalNodes, ecNumNodes - ecNumGlobalNodes);
+ fprintf(stderr,"EXT: %d nodes above capacitance threshold\n", ecNumNodeCaps);
+ fprintf(stderr,"EXT: %d nodes above resistance threshold\n", ecNumNodeResists);
+ fprintf(stderr,"EXT: %d internodal capacitors (%d above threshold)\n",
+ ecNumCaps, ecNumThreshCaps);
+ fprintf(stderr,"EXT: %d explicit resistors (%d above threshold)\n",
+ ecNumResists, ecNumThreshResists);
+}
+
+static int countfetVisit(Fet *fet, HierName *hname, Transform *t, int l , int w, ClientData data)
+{
+ fet->fet_type&=0x07f; /* clear our sneaky bit */
+ ecNumFets++;
+ return 0;
+}
+
+
+static int countnodeVisit(EFNode *node, int res, double cap, ClientData data)
+{
+ ecNumNodes++;
+ return 0;
+}
+
+static EFNode *GetNode(HierName *prefix,HierName *suffix)
+{
+ HashEntry *he;
+
+ he = EFHNConcatLook(prefix, suffix, "output");
+ return(((EFNodeName *) HashGetValue(he))->efnn_node);
+}
+
+
+void extract_setup_graph(graph_t *gr)
+{
+ int er=1;
+ CHECK_EXTINIT(gr)er=0;
+ assert(!er);
+
+ /* Convert the hierarchical description to a flat one */
+ EFFlatBuild(gr->input.ext->fname, EF_FLATNODES | EF_FLATCAPS | EF_FLATRESISTS);
+
+ ecNumFets=0;
+ ecNumNodes=0;
+ EFVisitFets(countfetVisit, (void *) gr);
+ EFVisitNodes(countnodeVisit, (void *) gr);
+ gr->mge=ecNumFets;
+ gr->mgn=ecNumNodes;
+
+ fprintf(stderr,"EXT: setup %i fets %i nodes\n",gr->mge, gr->mgn);
+}
+
+
+
+
+static int buildnodeVisit(EFNode *node, int res, double cap, ClientData data)
+{
+ graph_t *g=(void *)data;
+ hashchain_t *hc;
+ hashload_t pay;
+ char *str;
+ gn_t *gn;
+ int i;
+ PerimArea *diff[2];
+
+ /*
+ cap = (cap + 500) / 1000;
+ res = (res + 500) / 1000;
+ what's up with this?
+ */
+
+ assert(node!=NULL);
+ assert(node->efnode_name!=NULL);
+ str=EFHNToStr(node->efnode_name->efnn_hier);
+
+ ecNumNodes++;
+ if (EFHNIsGlob(node->efnode_name->efnn_hier)) ecNumGlobalNodes++;
+
+ pay.flag=PAYLOAD_node;
+ pay.data=gn=new_gn(g);
+ node->efnode_client=(void *)gn; /* store our node ptr in here so we don't have to compare strings */
+ hc=add_hashtab(g->names,str,pay); /* add some string data for debugging, printing, etc memory hog*/
+ if(EFHNIsGlob(node->efnode_name->efnn_hier))
+ {
+ int l;
+ gn->special=safestrdup(hc->str);
+ l=strlen(gn->special);
+ if(gn->special[l-1]=='!')gn->special[l-1]=0;
+ }
+ else gn->special=NULL;
+ gn->name=hc->str;
+ gn->debug=gn->name;
+ gn->wtotal=0;
+
+ gn->cfixed=cap*1e-18; /* cap in attofarrads 1e-18 */
+ diff[FTpfet]=node->efnode_pa+1; /* resist class 1 from techfile is pdiff */
+ diff[FTnfet]=node->efnode_pa+0; /* resist class 0 from techfile is ndiff */
+
+ for(i=0;i<2;i++)
+ gn->cdiff[i]=
+ (PARAMS.scale * PARAMS.scale * diff[i]->pa_area * PARAMS.c_area_sd[i]) +
+ (PARAMS.scale * diff[i]->pa_perim * PARAMS.c_perim_sd[i])
+ ;
+
+ /*
+ note on capacitance:
+ The above code is very dependent on the magic techfile extract section,
+ namely, it assumes a specific resistance class ordering
+ and it assumes the extractor doesn't sum up diffusion and gate capacitance
+ */
+
+ return 0;
+}
+
+static graph_t *extract_Graph;
+
+static int buildfetVisit(Fet *fet, HierName *hname, Transform *t, int l , int w, ClientData data)
+{
+ ge_t *ep;
+ FetTerm *gate, *source, *drain;
+ EFNode /* *bnode,*/ *snode, *dnode, *gnode;
+ Rect r;
+ int scale;
+ graph_t *gr=extract_Graph;
+ int typ;
+ char *ft;
+ double sc=PARAMS.scale; /* lamda in meters */
+
+ assert(sc>0);
+ assert(fet!=NULL);
+
+ gate = &fet->fet_terms[0];
+ source = drain = &fet->fet_terms[1];
+ if (fet->fet_nterm >= 3)
+ drain = &fet->fet_terms[2];
+
+ gnode = GetNode (hname, gate->fterm_node->efnode_name->efnn_hier);
+ snode = GetNode (hname, source->fterm_node->efnode_name->efnn_hier);
+ dnode = GetNode (hname, drain->fterm_node->efnode_name->efnn_hier);
+ /*bnode = fetSubstrate(hname, fet->fet_subsnode->efnode_name->efnn_hier, fet->fet_type, NULL);*/
+
+ assert(w!=0);
+ assert(l!=0);
+ GeoTransRect(t, &fet->fet_rect, &r);
+ scale = GeoScale(t);
+ assert(scale!=0);
+ typ=fet->fet_type;
+ ft=EFFetTypes[typ];
+ typ=np_type((uchar)ft[0]);
+ ep=new_ge(gr);
+ ep->type=typ;
+
+
+ ep->flatref.x=r.r_ll.p_x;
+ ep->flatref.xx=r.r_ur.p_x;
+ ep->flatref.y=r.r_ll.p_y;
+ ep->flatref.yy=r.r_ur.p_y;
+
+ ep->WL= (PARAMS.gm_woverl[ep->type]*(double)w)/(double)l;
+ ep->Cg= sc*sc*PARAMS.c_area_gate[ep->type]*((double)w*scale)*((double)l*scale);
+ ep->Cs=0; /* compute this from ? */
+ ep->Cd=0; /* same with this */
+
+ /* for above Cs,Cd: strategy, split the diffusion resistance classes between all fet s/d's connected
+ to the node, proportional to the total width of each device
+ this is better than the hspice version, where diffusion is lumped onto a single fet.
+ so one poor fet gets all the diffusion for resizing
+ we have to do this after we visit all the fets once, so node wtotals are updated correctly
+ */
+
+ ep->parent.vp=(void *)fet;
+ ep->gn[GE_G]=(void *)(gnode->efnode_client);
+ ep->gn[GE_S]=(void *)(snode->efnode_client);
+ ep->gn[GE_D]=(void *)(dnode->efnode_client);
+ if(ep->gn[GE_S] > ep->gn[GE_D] ) /* put source/drain in cannonical order (source is lower node number) */
+ { void *tmp=ep->gn[GE_S]; ep->gn[GE_S]=ep->gn[GE_D]; ep->gn[GE_D]=tmp; }
+ ep->gn[GE_S]->wtotal+=(w*scale*sc);
+ ep->gn[GE_D]->wtotal+=(w*scale*sc);
+ return 0;
+}
+
+/*
+static int capVisit(HierName *hn1, HierName *hn2, double cap)
+{
+ ecNumCaps++;
+ cap = (cap + 500) / 1000;
+ if (cap > (double) EFCapThreshold) ecNumThreshCaps++;
+ return 0;
+}
+
+static int resistVisit(HierName *hn1, HierName *hn2, int res)
+{
+ ecNumResists++;
+ res = (res + 500) / 1000;
+ if (res > EFResistThreshold) ecNumThreshResists++;
+ return 0;
+}
+*/
+
+
+
+static int comparesorted(const void *a, const void *b)
+{
+ const ge_t *pa=a,*pb=b;
+
+ if(pa==pb)return 0;
+ if(pa==NULL)return 1;
+ if(pb==NULL)return -1;
+
+
+ if(pa->gn[GE_G] > pb->gn[GE_G])return 1;
+ if(pa->gn[GE_G] < pb->gn[GE_G])return -1;
+
+ if( (pa->gn[GE_S]==pb->gn[GE_S]) )
+ {
+ if(pa->gn[GE_D] > pb->gn[GE_D] ) return 1;
+ else if(pa->gn[GE_D] < pb->gn[GE_D] ) return -1;
+ }
+ if( (pa->gn[GE_D]==pb->gn[GE_D]) )
+ {
+ if(pa->gn[GE_D] > pb->gn[GE_D] ) return 1;
+ else if(pa->gn[GE_D] < pb->gn[GE_D] ) return -1;
+ }
+ else if( (pa->gn[GE_S]==pb->gn[GE_D]) )
+ {
+ if(pa->gn[GE_D] > pb->gn[GE_S] ) return 1;
+ else if(pa->gn[GE_D] < pb->gn[GE_S] ) return -1;
+ }
+ else if( (pa->gn[GE_D]==pb->gn[GE_S]) )
+ {
+ if(pa->gn[GE_S] > pb->gn[GE_D] ) return 1;
+ else if(pa->gn[GE_S] < pb->gn[GE_D] ) return -1;
+ }
+ else
+ {
+ if(pa->gn[GE_S] > pb->gn[GE_S] ) return 1;
+ else if(pa->gn[GE_S] < pb->gn[GE_S] ) return -1;
+ assert(0);
+ }
+ return 0;
+}
+
+
+static double compute_diffcap(gn_t *np, double w, int type)
+{
+ double ws,c;
+ ws=np->wtotal;
+ if(ws<=0.0)assert(0);
+ c= np->cdiff[type]*w/ws;
+ return c;
+}
+
+void extract_build_graph(graph_t *gr)
+{
+ ge_t *ep,*pep,*wep;
+ int i,j;
+ int er=1;
+ CHECK_EXTINIT(gr)er=0;
+ assert(!er);
+
+ extract_Graph=gr;
+ EFVisitNodes(buildnodeVisit, (ClientData) gr);
+ EFVisitFets(buildfetVisit, (ClientData) gr);
+
+ /*
+ if (EFCapThreshold < INFINITE_THRESHOLD) EFVisitCaps(capVisit, (ClientData) NULL);
+ if (EFResistThreshold < INFINITE_THRESHOLD) EFVisitResists(resistVisit, (ClientData) NULL);
+ */
+
+ /* now we want to sort the edges to merge duplicate fets faster */
+ qsort(gr->ge,gr->qge,sizeof(ge_t),comparesorted);
+
+ /* mark and merge parallel transistors */
+ for(i=0,j=0,pep=NULL,ep=gr->ge;i<gr->qge;i++)
+ {
+ ep->flag=0;
+ if(pep!=NULL)
+ if( (ep->gn[GE_G]==pep->gn[GE_G]) &&
+ (ep->gn[GE_S]==pep->gn[GE_S]) &&
+ (ep->gn[GE_D]==pep->gn[GE_D])
+ ) /* parallel fet, merge */
+ {
+ pep->WL+=ep->WL;
+ pep->Cg+=ep->Cg;
+ pep->Cs+=ep->Cs;
+ pep->Cd+=ep->Cd;
+ ep->flag=1;
+ j++;
+ }
+ else pep=ep;
+ else pep=ep;
+
+ ep++;
+ }
+
+ /* eliminate flagged transistors
+ wep moves forward for each new good transistor
+ ep moves forward for each transistor
+ */
+
+ for(j=0,wep=ep=gr->ge,i=0;i<gr->qge;i++)
+ {
+ if(!ep->flag) { if(wep!=ep) { *wep=*ep; } j++; wep++; }
+ ep++;
+ }
+
+ gr->qge=j;
+
+
+ /* now divvy up s/d diffusions between fets */
+
+ for(ep=gr->ge,i=0;i<gr->qge;i++)
+ {
+ double w;
+ w=edge_width(ep);
+ ep->Cs=compute_diffcap(ep->gn[GE_S],w,ep->type);
+ ep->Cd=compute_diffcap(ep->gn[GE_D],w,ep->type);
+ ep++;
+ }
+
+}
+
+
+
+
+
+#endif /* USE_EXTRACT_FORMAT */
+
+
+
+
+
+
diff --git a/spiceparser/netlist_extract.h b/spiceparser/netlist_extract.h
new file mode 100644
index 0000000..733094c
--- /dev/null
+++ b/spiceparser/netlist_extract.h
@@ -0,0 +1,45 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_extract.h definitions for magic extract file reader
+ Conrad Ziesler
+*/
+
+
+#define __NETLIST_EXTRACT_H__
+
+
+
+typedef struct extract_st
+{
+ int extract_magic;
+ char *root;
+ char *fname;
+ int did_EF_init_read;
+ void *merged_list;
+ int ext_argc;
+ char **ext_argv;
+}extract_t;
+
+
+
+
+
+
diff --git a/spiceparser/netlist_funcs.c b/spiceparser/netlist_funcs.c
new file mode 100644
index 0000000..4e0f2d2
--- /dev/null
+++ b/spiceparser/netlist_funcs.c
@@ -0,0 +1,169 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_funcs.c: table of usefull netlistfunc_t's for standard devtypes
+ Conrad Ziesler
+*/
+
+#include <stdio.h>
+#include "debug.h"
+#include "netlist_dev.h"
+
+#define EVALfull(n,a) eqnl_eval(&((n)->nl->eqnl),(a))
+#define EVALquick(n,a) eqn_getval_(&(a))
+#define EVALnm(a) EVALquick(nm,a)
+
+/* accumulate fet properties (areas, perimeters add per fraction of total width) */
+
+static int nlfd_props[]={ DEVFET_as, DEVFET_ad, DEVFET_ps, DEVFET_pd };
+static int nlfd_merge_same[]= { DEVFET_w, DEVFET_as, DEVFET_ad, DEVFET_ps, DEVFET_pd};
+static int nlfd_merge_flip[]= { DEVFET_w, DEVFET_ad, DEVFET_as, DEVFET_pd, DEVFET_ps};
+
+static void nlfd_fet_acc(netlistfunc_t *nm, int devi, int termi, float *nodeprops)
+{
+ devfet_t *f;
+ int w,i;
+
+ f=list_data(&(nm->entity->l),devi);
+ assert(f!=NULL);
+ w= (f->type==DEVFET_nmos)?0:1;
+
+ if((termi==DEVFET_S)||(termi==DEVFET_D))
+ {
+ nodeprops[w]+=EVALnm(f->v[DEVFET_w]);
+ for(i=0;i<4;i++)
+ nodeprops[2+i]+=EVALnm(f->v[nlfd_props[i]]);
+ }
+}
+
+static void nlfd_fet_dist(netlistfunc_t *nm, int devi, int termi, float *nodeprops)
+{
+ devfet_t *f;
+ int w,i;
+ float fraction;
+
+ f=list_data(&(nm->entity->l),devi);
+ assert(f!=NULL);
+ w= (f->type==DEVFET_nmos)?0:1;
+
+ if((termi==DEVFET_S)||(termi==DEVFET_D))
+ {
+ if(nodeprops[w]!=0)
+ fraction=EVALnm(f->v[DEVFET_w])/nodeprops[w];
+ else fraction=0;
+
+ for(i=0;i<4;i++)
+ eqn_setval(&(f->v[nlfd_props[i]]),nodeprops[i+2]*fraction);
+ }
+}
+
+/* source and drain we do separately by in nlfd_fet_sum, since they are symmetrical */
+typedef struct nlfd_cmp_st
+{
+ termptr_t g,b;
+ float l;
+ char type;
+}nlfd_cmp_t;
+
+
+static void nlfd_fet_cmp(netlistfunc_t *nm, int index, void *data)
+{
+ devfet_t *f;
+ nlfd_cmp_t *cmp=data;
+
+ f=list_data(&(nm->entity->l),index);
+ assert(f!=NULL);
+ cmp->type=f->type;
+ cmp->l=EVALnm(f->v[DEVFET_l]);
+ cmp->g=f->n[DEVFET_G];
+ cmp->b=f->n[DEVFET_B];
+}
+
+static int nlfd_fet_sum(struct netlistfunc_st *nm,int ia, int ib)
+{
+ devfet_t *fa,*fb;
+ int i;
+ fa=list_data(&(nm->entity->l),ia);
+ fb=list_data(&(nm->entity->l),ib);
+
+
+ assert(fa!=NULL);
+ assert(fb!=NULL);
+
+
+ if( /* these are checked in mergedup, and should be ok */
+ (!memcmp(&(fa->n[DEVFET_G]),&(fb->n[DEVFET_G]),sizeof(termptr_t))) &&
+ (!memcmp(&(fa->n[DEVFET_B]),&(fb->n[DEVFET_B]),sizeof(termptr_t))) &&
+ (EVALnm(fa->v[DEVFET_l]) == EVALnm(fb->v[DEVFET_l]))
+ )
+ {
+ if((!memcmp(&(fa->n[DEVFET_S]),&(fb->n[DEVFET_S]),sizeof(termptr_t))) &&
+ (!memcmp(&(fa->n[DEVFET_D]),&(fb->n[DEVFET_D]),sizeof(termptr_t))) )
+ {
+ /* merge devices, same orientation */
+ for(i=0;i<(sizeof(nlfd_merge_same)/sizeof(int));i++)
+ eqn_setval(
+ &(fa->v[nlfd_merge_same[i]]),
+ EVALnm(fa->v[nlfd_merge_same[i]])+
+ EVALnm(fb->v[nlfd_merge_same[i]])
+ );
+ return 1;
+ }
+ if((!memcmp(&(fa->n[DEVFET_S]),&(fb->n[DEVFET_D]),sizeof(termptr_t))) &&
+ (!memcmp(&(fa->n[DEVFET_D]),&(fb->n[DEVFET_S]),sizeof(termptr_t))) )
+ {
+ /* merge devices, opposite orientation */
+ for(i=0;i<(sizeof(nlfd_merge_same)/sizeof(int));i++)
+ eqn_setval(
+ &(fa->v[nlfd_merge_same[i]]),
+ EVALnm(fa->v[nlfd_merge_same[i]])+
+ EVALnm(fb->v[nlfd_merge_flip[i]])
+ );
+ return 1;
+ }
+ }
+ else
+ {
+ fprintf(stderr,"mergedup compare failure\n");
+ }
+
+ return 0; /* fail request */
+}
+
+netlistfunc_t * netlist_devfet_funcs(netlist_t *nl, netlistfunc_t *fp)
+{
+ netlistfunc_t f;
+ memset(&f,0,sizeof(f));
+
+ f.nl=nl;
+ f.entity=nl->e+DEVT_FET;
+ f.qproperties=6; /* n/p width + as/ad/ps/pd */
+ f.accumulate=nlfd_fet_acc;
+ f.distribute=nlfd_fet_dist;
+ f.qcmp=sizeof(nlfd_cmp_t);
+ f.sum=nlfd_fet_sum;
+ f.tocompare=nlfd_fet_cmp;
+ f.fixup=NULL; /* this is not needed, only if user wants it */
+
+ if(fp!=NULL)
+ *fp=f;
+
+ return fp;
+}
diff --git a/spiceparser/netlist_lib.c b/spiceparser/netlist_lib.c
new file mode 100644
index 0000000..fb8fbf8
--- /dev/null
+++ b/spiceparser/netlist_lib.c
@@ -0,0 +1,1480 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_lib.c, routines for building a library of netlists
+ Conrad Ziesler
+*/
+
+
+
+/* the goal here is to be able to read/write a file composed of segments
+ each segment has a header describing
+
+ 1. reference name
+ 2. equation parameters to iterate through
+ 3. logic function
+ 4. output ports, output tokens
+ 5. input ports, input tokens
+ 6. spice format netlist block to be parsed by netlist_spice
+
+ we then maintain this library of each version of each gate
+
+ in addition we would like to procedurally add gates to our library.
+ (ie. automatically generate library from templates)
+
+
+*/
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include "debug.h"
+#include "netlist_lib.h"
+#include "netlist_dev.h"
+
+int __debug_nlib__=1;
+
+#ifndef STRIP_DEBUGGING
+#define D(level,a) do { if(__debug_nlib__>(level)) a; } while(0)
+#else
+#define D(level,a)
+#endif
+
+
+
+/* add a new param, to a db */
+int nlib_add_pm(nlib_t *nlib, int dbindex, char *str, float min, float max, int qty)
+{
+ nlibpm_t template;
+ nlibdb_t *db;
+ int index;
+ template.min=min;
+ template.max=max;
+ template.qty=qty;
+ db=list_data(&(nlib->db),dbindex);
+ if(db==NULL)assert(0);
+ if(str!=NULL)
+ template.index=eqnl_find(&(db->nl->eqnl),str);
+ else template.index=-1;
+
+ if(template.index<0)
+ { fprintf(stderr,"couldn't find parameter %s used in netlist, assuming ignoring\n",str); return -1; }
+
+ index=list_add(&(db->params),&template);
+ return index;
+}
+
+/* add a new io definition to a db */
+int nlib_add_io(nlib_t *nlib, int dbindex, nlibiol_t *io, int tokens, int nodes, int dig, char **names)
+{
+ int index,ni;
+ int i;
+ nlibio_t *p,template;
+ nlibdb_t *db;
+ db=list_data(&(nlib->db),dbindex);
+ assert(db!=NULL);
+
+ memset(&template,0,sizeof(template));
+ index=list_add(&(io->iol),&template);
+ p=list_data(&(io->iol),index);
+
+ assert((nodes<NLIBIO_MAXNODES) && "Compile time node limit exceeded, change and recompile");
+
+ io->qtokens= (io->qtokens>0)?io->qtokens*tokens : tokens;
+ p->tokens=tokens;
+ p->qnodes=nodes;
+ p->digitize=dig;
+ for(i=0;i<nodes;i++)
+ {
+ ni=names_check(db->nl->names,names[i]);
+ if(ni<0)
+ {
+ fprintf(stderr,"NLIB: could not find i/o node %s in circuit\n",names[i]);
+ assert(0);
+ }
+ p->nodes[i]=ni;
+ }
+ return index;
+}
+
+
+static void nlib_init_io(nlibiol_t *io)
+{
+ io->qtokens=0;
+ list_init(&(io->iol),sizeof(nlibio_t),LIST_UNITMODE);
+}
+
+
+int nlib_db_netlist(nlib_t *nlib, int index, netlist_t *nl)
+{
+ nlibdb_t *db;
+ db=list_data(&(nlib->db),index);
+ assert(db!=NULL);
+ db->nl=nl;
+ return index;
+}
+
+
+
+/* makes a new db */
+int nlib_new_db(nlib_t *nlib, char *str)
+{
+ int index;
+ nlibdb_t template,*db;
+
+ memset(&template,0,sizeof(template));
+ index=list_add(&(nlib->db),&template);
+ names_add(nlib->dbref,index,str);
+ db=list_data(&(nlib->db),index);
+ list_init(&(db->params),sizeof(nlibpm_t),LIST_DEFMODE);
+ nlib_init_io(&(db->in));
+ nlib_init_io(&(db->out));
+ list_init(&(db->refnodes),sizeof(nlibrefnode_t),LIST_UNITMODE);
+ return index;
+}
+
+
+nlibfref_t nlib_func_lookup(nlib_t *nlib, char *str)
+{
+ nlibfref_t f;
+ f.index=names_check(nlib->funcnames,str);
+ return f;
+}
+
+/* fixme: should look up name of function in nlib->functions and
+ use that index
+*/
+int nlib_db_func(nlib_t *nlib, int index, char *str)
+{
+ nlibdb_t *db;
+ db=list_data(&(nlib->db),index);
+ assert(db!=NULL);
+ db->map=nlib_func_lookup(nlib,str);
+ return 0;
+}
+
+/* makes empty function of specified variables */
+nlibfunc_t *nlib_new_func(nlib_t *nlib, char *str, int qin, int qout,int p_delay, int p_offset, int p_cycle)
+{
+ int l;
+ nlibfunc_t *fp;
+ fp=malloc((l=sizeof(nlibfunc_t)+(sizeof(int)*qin)));
+ assert(fp!=NULL);
+ memset(fp,0,l);
+ fp->qin=qin;
+ fp->qout=qout;
+ fp->p_delay=p_delay;
+ fp->p_offset=p_offset;
+ fp->p_cycle=p_cycle;
+ l=list_add(&(nlib->funcs),&fp);
+ names_add(nlib->funcnames,l,str);
+ return fp;
+}
+/* specify one mapping */
+void nlib_func_addmap(nlib_t *nlib, nlibfunc_t *fp, int in, int out)
+{
+ assert(in<fp->qin);
+ assert(out<fp->qout);
+ assert(in>=0);
+ assert(out>=0);
+ fp->map[in]=out;
+}
+
+
+
+/* inits a nlib, call before any action on nlib */
+int nlib_init(nlib_t *nlib)
+{
+ list_init(&(nlib->db),sizeof(nlibdb_t),LIST_DEFMODE);
+ nlib->dbref=names_new();
+ list_init(&(nlib->iodefs),sizeof(nlibiodef_t), LIST_DEFMODE);
+ eqnl_init(&(nlib->eqnl));
+ list_init(&(nlib->funcs), sizeof(nlibfunc_t *), LIST_DEFMODE); /* list of pointers */
+ list_init(&(nlib->flatdb), sizeof(nlibflatdb_t), LIST_DEFMODE);
+ nlib->funcnames=names_new();
+ nlib->qvref=0;
+ nlib->vref=names_new();
+ nlib->flags=NULL;
+ nlib->eqn_mem=eqn_mem_new();
+ return 0;
+}
+
+void nlib_release_flatdb(nlib_t *nlib)
+{
+ int i;
+ nlibflatdb_t *fdbp;
+ list_iterate(&(nlib->flatdb),i,fdbp)
+ {
+ list_empty(&(fdbp->uservals));
+ if(fdbp->pvals!=NULL)free(fdbp->pvals);
+ fdbp->pvals=NULL;
+ }
+ list_empty(&(nlib->flatdb));
+ bitlist_free(nlib->flags);
+ nlib->flags=NULL;
+}
+
+void nlib_release_io(nlib_t *nlib, nlibiol_t *io)
+{
+ list_empty(&(io->iol));
+}
+
+void nlib_release_db(nlib_t *nlib)
+{
+ int i;
+ nlibdb_t *dbp;
+
+ list_iterate(&(nlib->db),i,dbp)
+ {
+ if(dbp->pvals!=NULL)free(dbp->pvals);
+ dbp->pvals=NULL;
+ list_empty(&(dbp->refnodes));
+ list_empty(&(dbp->params));
+ nlib_release_io(nlib,&(dbp->in));
+ nlib_release_io(nlib,&(dbp->out));
+ netlist_free(dbp->nl);
+ dbp->nl=NULL;
+ }
+ list_empty(&(nlib->db));
+ names_free(nlib->dbref);
+ nlib->dbref=NULL;
+}
+
+void nlib_release_funcs(nlib_t *nlib)
+{
+ int i;
+ void **p;
+ names_free(nlib->funcnames);
+ nlib->funcnames=NULL;
+ list_iterate(&(nlib->funcs),i,p)
+ {
+ if((*p)!=NULL)
+ free((*p));
+ }
+ list_empty(&(nlib->funcs));
+}
+
+void nlib_release_refs(nlib_t *nlib)
+{
+ names_free(nlib->vref);
+ nlib->vref=NULL;
+ nlib->qvref=0;
+}
+
+void nlib_release_iodefs(nlib_t *nlib)
+{
+ int i;
+ nlibiodef_t *p;
+ list_iterate(&(nlib->iodefs),i,p)
+ {
+ if(p->encoding!=NULL)free(p->encoding);
+ p->encoding=NULL;
+ }
+ list_empty(&(nlib->iodefs));
+
+}
+/* frees all data in nlib */
+void nlib_release(nlib_t *nlib)
+{
+ nlib_release_flatdb(nlib);
+ nlib_release_db(nlib);
+ nlib_release_refs(nlib);
+ nlib_release_funcs(nlib);
+ eqnl_free(&(nlib->eqnl));
+ nlib_release_iodefs(nlib);
+ eqn_mem_free(nlib->eqn_mem);
+ nlib->eqn_mem=NULL;
+}
+
+
+
+/* post processing of db structure */
+int nlib_db_fixup(nlib_t *nlib, nlibdb_t *db)
+{
+ int i,q,j;
+ nlibpm_t *p;
+ nlibrefnode_t *rnp;
+ int l=list_qty(&(db->params));
+ db->pvals=malloc((sizeof(float)*l));
+ memset(db->pvals,0,sizeof(float)*l);
+ list_shrink(&(db->params));
+ list_shrink(&(db->refnodes));
+
+ list_iterate(&(db->params),i,p)
+ {
+ if(0)fprintf(stderr,"nlib_db_fixup: trying to define eqn: %i->%s (%p)\n",p->index,eqnl_lookup(&(db->nl->eqnl),p->index),db->pvals+i);
+ eqnl_define(&(db->nl->eqnl),p->index,db->pvals+i);
+ }
+ q=eqnl_qty(&(db->nl->eqnl));
+
+ /* setup equations in our reference nodes */
+ list_iterate(&(db->refnodes),i,rnp)
+ {
+ for(j=0;j<RTqty;j++)
+ eqnl_depend(&(nlib->eqnl), rnp->skew[j]);
+ }
+
+ return 0;
+}
+
+
+/* step through library,
+ (in terms of param qty's, in order)
+ substitute in, and call client process function
+ for each instance of each cell
+*/
+void nlib_process(nlib_process_t *user, int screened)
+{
+ int i,j,k,lib_index;
+ nlib_t *nlib=user->nlib;
+ nlibdb_t *dbp;
+ nlibpm_t *dbpm;
+ int li[64]; /* max 64 parameters */
+ int lq[64];
+ int qp=0;
+
+ assert(nlib!=NULL);
+ memset(li,0,sizeof(li));
+ memset(lq,0,sizeof(lq));
+ lib_index=0;
+ list_iterate(&(nlib->db),i,dbp)
+ {
+ qp=0;
+ list_iterate(&(dbp->params),j,dbpm)
+ {
+ lq[j]=dbpm->qty;
+ li[j]=0;
+ dbp->pvals[j]= dbpm->min;
+ qp++;
+ if(qp>=64)assert(0);
+ }
+ k=0;
+ fprintf(stderr,"\n\nstarting db index %i\n",i);
+ while(1)
+ {
+ if(0)
+ {
+ fprintf(stderr,"iteration:");
+ for(j=0;j<qp;j++)
+ fprintf(stderr," (%i,%i)",li[j]+1,lq[j]);
+ fprintf(stderr,"\n");
+ }
+
+ if(nlib_isdisabled(nlib,lib_index)!=1)
+ {
+ /* eval each parameters */
+ for(j=0;j<qp;j++)
+ {
+ dbpm=list_data(&(dbp->params),j);
+
+ dbp->pvals[j]=dbpm->min+
+ li[j]*(dbpm->max-dbpm->min)/dbpm->qty;
+
+ if(0)fprintf(stderr,"setting %i (%p) val[%i]=%g\n",j,dbp->pvals+j,dbpm->index,dbp->pvals[j]);
+ }
+
+ user->nl=dbp->nl;
+ user->lib_index=lib_index;
+ user->db_index=i;
+ user->process(user);
+ }
+ lib_index++;
+ /* increment loop */
+ for(j=0;j<qp;j++)
+ if(li[j]<(lq[j]-1))
+ {
+ li[j]++;
+ for(j--;j>=0;j--) /* roll over rest of indices */
+ li[j]=0;
+ break;
+ }
+ if(j==qp)break;
+ }
+ }
+
+}
+
+
+static void nlib_fixup_process(nlib_process_t *user)
+{
+ int *ip=user->user;
+ ip[0]++;
+}
+
+void nlib_fixup(nlib_t *nlib)
+{
+ int count=0;
+ nlib_process_t pr;
+
+ eqnl_autodepend(&(nlib->eqnl));
+ eqnl_evaldep(&(nlib->eqnl));
+ if(nlib->flags!=NULL) /* in case we were called multiple times */
+ bitlist_free(nlib->flags);
+ nlib->flags=NULL;
+ if(0)
+ {
+ pr.user=&count;
+ pr.nlib=nlib;
+ pr.process=nlib_fixup_process;
+ nlib_process(&pr,0);
+ nlib->flags=bitlist_new(count+1);
+ }
+}
+
+/* this does the dirty work of updating configurable db netlists from flat db */
+void nlib_doflat(nlib_t *nlib, int index)
+{
+ nlibflatdb_t *fdb;
+ nlibdb_t *db;
+ assert(nlib!=NULL);
+ fdb=list_data(&(nlib->flatdb),index);
+ assert(fdb!=NULL);
+ db=list_data(&(nlib->db),fdb->db_index);
+ assert(db!=NULL);
+ if(fdb->pvals!=NULL)
+ memcpy(db->pvals,fdb->pvals,sizeof(float)*fdb->qvals);
+ else
+ assert(fdb->qvals==0);
+}
+
+/* call this from user process for each gate we want to keep */
+void *nlib_flat(nlib_process_t *user, int s_uservals, int q_uservals)
+{
+ nlib_t *nlib;
+ nlibdb_t *db;
+ int index;
+ nlibflatdb_t *fdb;
+
+ assert(user!=NULL);
+ nlib=user->nlib;
+ assert(nlib!=NULL);
+ index=list_nextz(&(nlib->flatdb));
+ fdb=list_data(&(nlib->flatdb),index);
+ fdb->lib_index=user->lib_index;
+ fdb->db_index=user->db_index;
+ db=list_data(&(nlib->db),fdb->db_index);
+ assert(db!=NULL);
+ fdb->qvals=list_qty(&(db->params));
+
+ list_init(&(fdb->uservals),s_uservals,LIST_UNITMODE);
+ list_hint(&(fdb->uservals),q_uservals);
+
+ if(fdb->qvals>0)
+ {
+ fdb->pvals=malloc(sizeof(float)*fdb->qvals);
+ assert(fdb->pvals!=NULL);
+ memcpy(fdb->pvals,db->pvals,sizeof(float)*fdb->qvals);
+ }
+ else fdb->pvals=NULL;
+
+ return list_block_next(&(fdb->uservals),q_uservals);
+}
+
+
+void nlib_disable(nlib_t *nlib, int index)
+{
+ if(nlib->flags!=NULL)
+ bitlist_set(nlib->flags,index);
+}
+
+int nlib_isdisabled(nlib_t *nlib, int index)
+{
+ if(nlib->flags!=NULL)
+ return bitlist_test(nlib->flags,index);
+ return -1;
+}
+
+
+static void nlib_o_spice_subckt_(nlib_t *nlib, int db_index, int lib_index, void * of_fp)
+{
+ FILE *of=of_fp;
+ nlibdb_t *dbp;
+ nlibrefnode_t *rnp;
+ nlibio_t *iop;
+ int i,j;
+ int z_index=1;
+ int n_start=1;
+
+ dbp=list_data(&(nlib->db),db_index);
+ assert(dbp!=NULL);
+ fprintf(of,"\n.subckt sc%i", lib_index);
+
+ /* reference nodes */
+ list_iterate(&(dbp->refnodes),i,rnp)
+ fprintf(of," rn%i",rnp->vrefi);
+
+ /* input nodes */
+ list_iterate(&(dbp->in.iol),i,iop)
+ for(j=0;j<iop->qnodes;j++)
+ fprintf(of," %i",iop->nodes[j]+n_start);
+
+ /* output nodes */
+ list_iterate(&(dbp->out.iol),i,iop)
+ for(j=0;j<iop->qnodes;j++)
+ fprintf(of," on%i_%i",i,j);
+
+ fprintf(of,"\n");
+
+ /* call netlist_o_spice to output subckt netlist */
+ netlist_o_spice(of, dbp->nl, n_start);
+
+ /* add additional circuitry for output buffers */
+ list_iterate(&(dbp->out.iol),i,iop)
+ for(j=0;j<iop->qnodes;j++)
+ fprintf(of,"Ez%i on%i_%i 0 VCVS PWL(1) %i 0 -10v,-10v 10v,10v\n",z_index++,i,j, iop->nodes[j]+n_start);
+
+ /* add aditional circuitry for delay and rc of references */
+
+ list_iterate(&(dbp->refnodes),i,rnp)
+ {
+ float f[4]={0.0, 0.0, 0.0, 0.0 };
+ int ud[4];
+ assert(RTqty<=3);
+ for(j=0;j<RTqty;j++)
+ {
+ ud[j]=(eqn_is_undefined(rnp->skew[j])!=0);
+ f[j]=eqnl_eval(&(nlib->eqnl),rnp->skew[j]);
+ }
+
+ if( ud[RTdelay] && ud[RTrseries] )
+ fprintf(of,"rz%i rn%i %i 1e-3\n", z_index++,rnp->vrefi,rnp->devnodei+n_start);
+
+ else if (!ud[RTdelay] && ud[RTrseries])
+ fprintf(of,"Ez%i %i 0 VCVS DELAY rn%i 0 TD=%g SCALE=1\n",
+ z_index++, rnp->devnodei+n_start, rnp->vrefi, f[RTdelay]
+ );
+
+ else if ( ud[RTdelay] && !ud[RTrseries])
+ fprintf(of,"rz%i rn%i %i %g\n",z_index++, rnp->vrefi, rnp->devnodei+n_start, f[RTrseries]);
+
+ else
+ {
+ fprintf(of,"dz%i rn%i rn%ia %g\nrz%i rn%ia %i %g\n",
+ z_index, rnp->vrefi, rnp->vrefi, f[RTdelay],
+ z_index+1, rnp->vrefi, rnp->devnodei+n_start, f[RTrseries]
+ );
+ z_index+=2;
+ }
+ if(!ud[RTcshunt])
+ fprintf(of,"cz%i %i 0 %g\n",z_index++,rnp->devnodei+n_start, f[RTcshunt] );
+ }
+ fprintf(of,".ends sc%i\n",lib_index);
+
+}
+
+
+void nlib_o_spice_refs(nlib_t *nlib, void * of_fp)
+{
+ FILE *of=of_fp;
+ int i;
+ char *p;
+ for(i=0;(p=names_lookup(nlib->vref,i))!=NULL;i++)
+ {
+ fprintf(of,"*nref %s\n",p);
+ }
+}
+
+
+static void nlib_o_spice_subckt_process(nlib_process_t *user)
+{ nlib_o_spice_subckt_(user->nlib,user->db_index,user->lib_index, user->user); }
+
+void nlib_o_spice_subckts(nlib_t *nlib, void * of_fp)
+{
+ FILE *of=of_fp;
+ /* if we built a flat db, use it */
+ if(list_qty(&(nlib->flatdb))>0)
+ {
+ int i,j;
+ nlibflatdb_t *fdb;
+ float *dp;
+
+ list_iterate(&(nlib->flatdb),i,fdb)
+ {
+ /* print header with some usefull info */
+ fprintf(of,"****** index=%i db_index=%i lib_index=%i ***",
+ i,fdb->db_index,fdb->lib_index
+ );
+ list_iterate(&(fdb->uservals),j,dp)
+ fprintf(of,"%s%g",((j%5)==0)?"\n*** ":" ",*dp);
+ fprintf(of,"\n");
+
+ nlib_doflat(nlib,i); /* update the netlist */
+ nlib_o_spice_subckt_(nlib,fdb->db_index,fdb->lib_index, of);
+ }
+ }
+ else
+ {
+ nlib_process_t proc;
+ proc.nlib=nlib;
+ proc.user=of;
+ proc.process=nlib_o_spice_subckt_process;
+ nlib_process(&proc,1);
+ }
+}
+
+
+
+
+
+/************ TOFIX: NEED to add multiple input nodes
+ probably the easiest is to pass a list ptr of i_nodes
+
+tree.c needs some helper function in netlist_lib.c which gives the number of inputs
+a given gate needs, so it can figure out it's proper wiring topology.
+perhaps we should allocate the list of input nodes within the flatdb structure
+and then tree would only have to pass *which* node to change in the list?
+or at the very least, tree.c won't have to allocate a bunch of random lists and keep them
+current.
+
+************/
+
+
+
+
+/* output spice style subckt call, mapping i_node and o_node */
+void nlib_o_spice_call(nlib_t *nlib, int index, int i_node, int o_node, int *skt, void * of_fp)
+{
+ FILE *of=of_fp;
+ nlibflatdb_t *fdb;
+ nlibdb_t *db;
+ nlibio_t *iop;
+ nlibrefnode_t *rnp;
+ int i,j;
+ char tmp[64];
+
+ assert(nlib!=NULL);
+ fdb=list_data(&(nlib->flatdb),index);
+ assert(fdb!=NULL);
+ db=list_data(&(nlib->db),fdb->db_index);
+ assert(db!=NULL);
+
+ fprintf(of,"X%i ",(*skt)++);
+
+ /* reference nodes */
+ list_iterate(&(db->refnodes),i,rnp)
+ fprintf(of," %s",names_lookup(nlib->vref,rnp->vrefi));
+
+ if(i_node==-1)sprintf(tmp,"root");
+ else sprintf(tmp,"n%i",i_node);
+
+ /* input nodes, for multi-input gate, tie inputs together */
+ list_iterate(&(db->in.iol),i,iop)
+ for(j=0;j<iop->qnodes;j++)
+ fprintf(of," %s_%i",tmp,j);
+
+ /* output nodes, for multi-output gate, tie outputs together */
+ list_iterate(&(db->out.iol),i,iop)
+ for(j=0;j<iop->qnodes;j++)
+ fprintf(of," n%i_%i",o_node,j);
+
+ fprintf(of," sc%i",fdb->lib_index);
+ fprintf(of,"\n");
+ fprintf(of,"*nlib %i %i %i %i\n",i_node,o_node,fdb->db_index,index);
+}
+
+void nlib_iface_release(nlib_iface_t *iface)
+{
+ list_empty(&(iface->icalls));
+ list_empty(&(iface->frefs));
+}
+
+void nlib_iface_init(nlib_iface_t *iface, nlib_t *nlib)
+{
+ memset(iface->ref_map,0,sizeof(iface->ref_map));
+ list_init(&(iface->icalls),sizeof(nlib_icall_t),LIST_DEFMODE);
+ list_init(&(iface->frefs),sizeof(nlib_ifref_t),LIST_DEFMODE);
+ iface->nlib=nlib;
+ iface->phase=0;
+}
+
+nlib_ifref_t *nlib_iface_getref(nlib_iface_t *iface, int id)
+{
+ nlib_ifref_t *rp;
+ assert(id<NLIBref_max);
+ assert(id>=0);
+ rp=list_data(&(iface->frefs),iface->ref_map[id]);
+ assert(rp!=NULL);
+ return rp;
+}
+
+static int nlib_digitize(float *vals[], int digitize, int tokens[], nlib_iface_t *iface)
+{
+ int i;
+ int token=-1;
+ float dv;
+ float vdd,vss;
+
+ switch(digitize)
+ {
+ case 0: /* default */
+ assert(0);
+ break;
+ case 1: /* delta v */
+ assert(vals[0]!=NULL);
+ assert(vals[1]!=NULL);
+ dv=(*vals[0])-(*vals[1]);
+ if(dv>(1e-3))token=1;
+ if(dv<(-1e-3)) token=0;
+ break;
+ case 2: /* cmos */
+ assert(vals[0]!=NULL);
+ dv=*vals[0];
+ vss=nlib_iface_getref(iface,NLIBref_vss)->val[0];
+ vdd=nlib_iface_getref(iface,NLIBref_vdd)->val[0];
+ if((2*dv)>(vdd-vss)) token=1;
+ else token=0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* update tokens[phases] current phase is always tokens[0].. */
+ if(tokens!=NULL)
+ {
+ for(i=(NLIB_MAXPHASES-1);i>=1;i--)
+ tokens[i]=tokens[i-1];
+ tokens[0]=token;
+ }
+ return token;
+}
+
+int nlib_func_compute(nlibfunc_t *map, int input)
+{
+ assert(map!=NULL);
+ if(input<0)return -1;
+ assert(input<map->qin);
+ return map->map[input];
+}
+
+
+int nlib_icall_digitize(nlib_iface_t *iface, int calli, int phase)
+{
+ nlib_icall_t *cd;
+ nlibdb_t *dp;
+ nlibfunc_t *fp,**fpp;
+
+ cd=list_data(&(iface->icalls),calli);
+ assert(cd!=NULL);
+ dp=list_data(&(iface->nlib->db),cd->dbi);
+ assert(dp!=NULL);
+ fpp=list_data(&(iface->nlib->funcs),dp->map.index);
+ assert(fpp!=NULL);
+ fp=*fpp;
+ assert(fp!=NULL);
+
+ nlib_digitize(cd->in, cd->idigitize, cd->itokens, iface);
+ nlib_digitize(cd->out, cd->odigitize, cd->otokens, iface);
+
+ if(phase> (fp->p_delay+fp->p_offset)) /* wait at least this long before checking valididy */
+ if( (phase%fp->p_cycle)== (fp->p_delay%fp->p_cycle) ) /* are we on the correct phase */
+ {
+ cd->ctoken=nlib_func_compute(fp,cd->itokens[(fp->p_offset%fp->p_delay)]);
+ if(cd->ctoken!=cd->otokens[0]) cd->err++;
+ else cd->ver++;
+ }
+ return cd->err;
+}
+
+void nlib_iface_phase(nlib_iface_t *iface)
+{
+ int i;
+ nlib_icall_t *cp;
+ iface->phase++;
+
+ list_iterate(&(iface->icalls),i,cp)
+ nlib_icall_digitize(iface,i,iface->phase);
+}
+
+int nlib_iface_do_call(nlib_iface_t *iface, int in, int on, int dbi, int fdbi)
+{
+ nlib_t *nlib=iface->nlib;
+ nlibdb_t *db;
+ char nn[64],*nnp;
+ int j;
+ nlib_icall_t *cd;
+ nlibio_t *iop;
+ int z;
+
+ db=list_data(&(nlib->db),dbi);
+ if(db==NULL)return 0;
+
+ z=list_qty(&(iface->icalls));
+ cd=list_next(&(iface->icalls));
+ cd->dbi=dbi;
+ cd->flatdbi=fdbi;
+ cd->err=0;
+ cd->ver=0;
+ for(j=0;j<NLIBIO_MAXNODES;j++)
+ {
+ cd->in[j]=NULL;
+ cd->out[j]=NULL;
+ }
+ for(j=0;j<NLIB_MAXPHASES;j++)
+ cd->itokens[j]=cd->otokens[j]=-1;
+
+ cd->ctoken=-1;
+ cd->inode=in;
+ cd->onode=on;
+
+ /*** lookup input nodes from tracefile interface *****/
+
+ if(in>-1)
+ sprintf(nn,"n%i_",in);
+ else sprintf(nn,"root_");
+
+ nnp=nn+strlen(nn);
+
+ iop=list_data(&(db->in.iol),0); /* only handle inverters right now */
+ assert(iop!=NULL);
+ for(j=0;j<iop->qnodes;j++)
+ {
+ sprintf(nnp,"%i",j);
+ cd->in[j]=iface->lookup_node_f(iface->user, nn);
+ if(cd->in[j]==NULL)
+ fprintf(stderr,"ERROR: did not find trace node %s\n",nn);
+ }
+ cd->idigitize=iop->digitize;
+
+ /*** lookup output nodes from tracefile interface ****/
+
+ sprintf(nn,"n%i_",on);
+ nnp=nn+strlen(nn);
+
+ iop=list_data(&(db->out.iol),0); /* only handle inverters right now */
+ assert(iop!=NULL);
+ for(j=0;j<iop->qnodes;j++)
+ {
+ sprintf(nnp,"%i",j);
+ cd->out[j]=iface->lookup_node_f(iface->user, nn);
+ if(cd->out[j]==NULL)
+ fprintf(stderr,"ERROR: did not find trace node %s\n",nn);
+ }
+ cd->odigitize=iop->digitize;
+
+ return z;
+}
+
+int nlib_i_spice_calls(nlib_iface_t *iface, void * cktf_fp)
+{
+ FILE *cktf=cktf_fp;
+ int dbi,fdbi;
+ int in,on;
+ char line[4096];
+ int q=0;
+ int i;
+ nlib_ifref_t ifref;
+
+ memset(line,0,sizeof(line));
+ while(!feof(cktf))
+ {
+ line[0]=0;
+ line[1]=0;
+ line[sizeof(line)-1]=0;
+ line[sizeof(line)-2]=0;
+ fgets(line,sizeof(line-2),cktf);
+ i=strlen(line)-1;
+ while(i>=0) { if(isspace(line[i])) line[i]=0; else break; i--; }
+
+ if( ( line[0]=='*') && (line[1]=='n') && (line[2]=='l') && (line[3]=='i') && (line[4]=='b') )
+ {
+ dbi=-1;
+ fdbi=-1;
+ in=-2;
+ on=-2;
+ sscanf(line+5," %i %i %i %i",&in,&on,&dbi,&fdbi);
+ if(fdbi==-1)continue;
+ q+=nlib_iface_do_call(iface,in,on,dbi,fdbi);
+ continue;
+ }
+
+ if( (line[0]=='*') && (line[1]=='n') && (line[2]=='r') && (line[3]=='e') && (line[4]=='f'))
+ {
+ if(line[5]!=' ')continue;
+ memset(&ifref,0,sizeof(ifref));
+
+ for(i=6;line[i]!=0;i++)
+ {
+ if(isspace(line[i]))break;
+ ifref.name[i-6]=line[i];
+ }
+
+ for(i=0;i<NLIB_MAXPHASES;i++) ifref.vals[i]=0.0;
+ ifref.val=iface->lookup_node_f(iface->user,ifref.name);
+ dbi=list_add(&(iface->frefs),&ifref);
+ /* this is all just a big consistancy check */
+ fdbi=names_check(iface->nlib->vref,ifref.name);
+ if(dbi!=fdbi)
+ {
+ fprintf(stderr,"FATAL ERROR: this database file does not seem to match given tracefile\n");
+ exit(0);
+ }
+ }
+ continue;
+ }
+
+ return q;
+}
+
+
+/* saving and restoring the flat db
+
+ these are non human readable formatted files because i am lazy
+ note: architecture float format and endianess dependence in user parameters
+*/
+
+static char nlib_flatdb_ver[]="NLIB_FLATDB_a";
+
+int nlib_flatdb_write(nlib_t *nlib, void * file)
+{
+ nlibflatdb_t *p;
+ int i,j,q;
+ unsigned char *c;
+ fprintf(file,"%s %i\n",nlib_flatdb_ver,list_qty(&(nlib->flatdb)));
+ list_iterate(&(nlib->flatdb),i,p)
+ {
+ q=list_sizeof(&(p->uservals))*list_qty(&(p->uservals));
+ c=list_data(&(p->uservals),0);
+ fprintf(file,"lib %i db %i qvals %i user %i %i\n",p->lib_index,p->db_index,p->qvals,
+ list_sizeof(&(p->uservals)),list_qty(&(p->uservals))
+ );
+ for(j=0;j<p->qvals;j++)
+ fprintf(file,"%e%c",p->pvals[j],(j==(p->qvals-1))?'\n':' ');
+ for(j=0;j<q;j++)
+ {
+ fprintf(file,"%i%c",(int)c[j],(j==(q-1))?'\n':' ');
+ if(0)fprintf(stderr,"%i ",c[j]);
+ }
+ }
+ fprintf(file,"NLIB_FLATDB_END\n");
+ return i;
+}
+
+
+int nlib_flatdb_read(nlib_t *nlib, void * file_fp)
+{
+ FILE *file=file_fp;
+ nlib_process_t up;
+ nlibflatdb_t *p;
+ int i,j,q,qty,p_qvals,ua,ub,index;
+ unsigned char *c;
+ char line[4096],*lp;
+ line[0]=0;
+ line[sizeof(line)-1]=0;
+ fgets(line,sizeof(line)-2,file);
+ if(memcmp(line,nlib_flatdb_ver,strlen(nlib_flatdb_ver))!=0)return -1;
+ qty=atoi(line+sizeof(nlib_flatdb_ver));
+ if(qty==0)return -2;
+ list_hint(&(nlib->flatdb),qty);
+ i=0;
+ while(!feof(file))
+ {
+ if(i==qty)break;
+ line[0]=0;
+ fgets(line,sizeof(line)-2,file);
+ memset(&up,0,sizeof(up));
+ up.nlib=nlib;
+ up.lib_index=-1;
+ up.db_index=-1;
+ p_qvals=-1;
+ ua=0;
+ ub=0;
+ if(sscanf(line,"lib %i db %i qvals %i user %i %i",&up.lib_index,&up.db_index,&p_qvals,&ua,&ub)!=5)
+ { assert(0); continue; }
+ index=list_qty(&(nlib->flatdb));
+ c=nlib_flat(&up,ua,ub);
+ p=list_data(&(nlib->flatdb),index);
+ assert(p!=NULL);
+ assert(p_qvals==p->qvals);
+ line[0]=0;
+ fgets(line,sizeof(line)-2,file);
+ for(lp=line,j=0;j<p->qvals;j++)
+ {
+ float f=0.0;
+ while(isspace(lp[0]))lp++;
+ if(sscanf(lp,"%f",&f)!=1)assert(0);
+ while(!isspace(lp[0]))lp++;
+ p->pvals[j]=f;
+ }
+ assert(c!=NULL);
+ q=ua*ub;
+ line[0]=0;
+ fgets(line,sizeof(line)-2,file);
+
+ for(lp=line,j=0;j<q;j++)
+ {
+ unsigned x=0;
+ while(isspace(lp[0]))lp++;
+ if(sscanf(lp,"%i",&x)!=1)assert(0);
+ while(!isspace(lp[0]))lp++;
+ c[j]=x;
+ if(0)fprintf(stderr,"%i ",c[j]);
+ }
+ i++;
+ }
+ return i;
+}
+
+/* parse a library file format
+
+.netlist = name
+.reference=ref_name name=spice_name delay=time rseries=res cshunt=cap
+.reference= ...
+.input=encoding spice_name[0] .... spice_name_[qnodes-1]
+.input=encoding ...
+.output spice_nam.....
+.output ...
+.param=spice_name .min=xxx .max=xxx .qtysteps=xxx
+.param ..
+.function=fname
+.end_netlist
+
+.encoding=encodingname .wires=number .tokens=number .digitize=methodname
+
+.digital=functionname
+ 0=0 1=0 0011=.. ... input_token = output_token
+.end_digital
+
+
+.spice
+
+# spice netlist format
+
+.end_section # end of spice netlist
+
+*/
+
+
+static tokenmap_t nlib_tokens[]=NLIB_TOKENS;
+
+/* assume nlib aready initted, this adds to it */
+int nlib_parse(nlib_t *nlib, scanner_t *scan)
+{
+ netlist_t *nl=NULL;
+ int db_index=-1;
+ deck_t *db_deck=NULL, *digital_deck=NULL;
+ nlibiodef_t encoding_default;
+ nlibfunc_t *digital_func=NULL;
+ deck_t *dplast=NULL;
+ scanner_def_t defs;
+
+ assert(nlib->eqn_mem!=NULL);
+ eqn_mem_push(nlib->eqn_mem);
+
+ defs=*scanner_def_spice();
+ strcpy(defs.line_stop,".end_nlib");
+ encoding_default.encoding="dual_rail";
+ encoding_default.wires=2;
+ encoding_default.tokens=2;
+ encoding_default.digitize=0;
+ scanner_sect_new(scan,&defs,nlib_tokens);
+ while(scanner_parse_line(scan))
+ {
+ card_t *cp=NULL;
+ int flag=0;
+
+ if(scan->sectp!=NULL)
+ if(scan->sectp->dp!=NULL)
+ if((cp=scan->sectp->dp->card)!=NULL)
+ flag++;
+ if(flag&&(scan->sectp->dp!=dplast))
+ {
+ dplast=scan->sectp->dp;
+ scan->errdeck=dplast;
+ scan->errcard=dplast->card;
+ if(0)scanner_debug_all(scan,stderr);
+ switch(cp->token)
+ {
+
+ case Knlib_digital:
+ if(cp->val!=NULL)
+ {
+ card_t *p;
+ int z;
+ int qtyin=-1, qtyout=-1, p_delay=-1, p_offset=-1, p_cycle=-1;
+ for(p=cp->next;p!=NULL;p=p->next)
+ {
+ if(p->val!=NULL)
+ {
+ z=atoi(p->val);
+ switch(p->token)
+ {
+ case Knlib_qtyin:
+ qtyin=z;
+ break;
+ case Knlib_qtyout:
+ qtyout=z;
+ break;
+ case Knlib_p_delay:
+ p_delay=z;
+ break;
+ case Knlib_p_offset:
+ p_offset=z;
+ break;
+ case Knlib_p_cycle:
+ p_cycle=z;
+ break;
+ default:
+ scan->errcard=p;
+ scan->errdeck=dplast;
+ parse_warn(scan,"unknown word in function definition %s\n",p->val);
+ }
+ }
+ }
+
+ if((qtyin!=-1) && (qtyout!=-1) && (p_delay!=-1) && (p_offset!=-1) && (p_cycle!=-1))
+ {
+ digital_deck=scan->sectp->dp;
+ digital_func=nlib_new_func(nlib,cp->val, qtyin, qtyout, p_delay,p_offset,p_cycle);
+ break;
+ }
+ }
+ parse_error(scan,"mangled function definition");
+ break;
+
+ case Knlib_end_digital:
+ if((digital_deck!=NULL) && (digital_func!=NULL))
+ {
+ deck_t *dp;
+ for(dp=digital_deck->next;dp!=NULL;dp=dp->next)
+ {
+ card_t *p;
+ if(dp==scan->sectp->dp)break;
+ for(p=dp->card;p!=NULL;p=p->next)
+ {
+ unsigned int a=0,b=0;
+ char *sp=p->str;
+ scan->errcard=p;
+ scan->errdeck=dp;
+ if(sp!=NULL)
+ {
+ a=parse_binary(&sp);
+ sp=p->val;
+ if(sp!=NULL)
+ {
+ b=parse_binary(&sp);
+ nlib_func_addmap(nlib, digital_func, a, b);
+ }
+ else parse_warn(scan,"ignoring mangled mapping %s=%s\n",cp->str,cp->val);
+ }
+ else parse_warn(scan,"ignoring mangled mapping %s=%s\n",cp->str,cp->val);
+ }
+ }
+ }
+ else
+ parse_error(scan,"mangled function definition");
+ digital_deck=NULL;
+ digital_func=NULL;
+ break;
+
+ case Knlib_encoding: /* io def */
+ if(cp->val!=NULL)
+ {
+ int tokens=0, wires=0, h_tokens=0, h_wires=0;
+ char *digitize=NULL;
+ card_t *p;
+ for(p=cp->next;p!=NULL;p=p->next)
+ {
+ D(20,fprintf(stderr,"encoding: %s=[%s]\n",p->str,p->val));
+ if(p->val!=NULL)
+ {
+ switch(p->token)
+ {
+ case Knlib_wires:
+ wires=atoi(p->val);
+ h_wires++;
+ break;
+ case Knlib_tokens:
+ tokens=atoi(p->val);
+ h_tokens++;
+ break;
+ case Knlib_digitize:
+ digitize=p->val;
+ break;
+ }
+ }
+ }
+ if( h_tokens && h_wires && (digitize!=NULL) )
+ {
+ int index;
+ nlibiodef_t *iop;
+ index=list_add(&(nlib->iodefs),&encoding_default);
+ iop=list_data(&(nlib->iodefs),index);
+ iop->encoding=strdup(cp->val);
+
+ if(strcmp(digitize,"deltav")==0)
+ iop->digitize=1;
+ else if(strcmp(digitize,"cmos")==0)
+ iop->digitize=2;
+ else
+ iop->digitize=0;
+
+ iop->tokens=tokens;
+ iop->wires=wires;
+ D(20,fprintf(stderr,"adding encoding %s, %i %i\n",cp->val,tokens,wires));
+ break;
+ }
+ }
+
+ parse_error(scan,"mangled encoding line ");
+ break;
+
+ case Knlib_define:
+ if(cp->val==NULL)
+ {
+ card_t *p;
+ for(p=cp->next;p!=NULL;p=p->next)
+ {
+ if(p->val!=NULL)
+ {
+ eqnl_add(&(nlib->eqnl),eqn_parse(p->val),p->str);
+ }
+ }
+ }
+ break;
+
+ case Knlib_netlist:
+ if(cp->val!=NULL)
+ {
+ db_index=nlib_new_db(nlib,cp->val);
+ db_deck=scan->sectp->dp; /* store location in deck where netlist occured */
+ }
+ else
+ parse_error(scan,".netlist=name expected");
+ break;
+
+ case Knlib_spice:
+ if(db_index>=0)
+ {
+ nl=netlist_devnew(netlist_parse_input(scan,"spice",NULL));
+ assert(nl!=NULL);
+
+ if(1)netlist_release(nl); /* release spice parse structures */
+ /* why does it crash with this ???? */
+ }
+ else
+ parse_error(scan,".spice section must be preceded by .netlist section");
+ break;
+
+ case Knlib_end_netlist:
+ if(db_index<0)
+ parse_error(scan,".end netlist without .netlist");
+ else
+ {
+ deck_t *dp;
+ card_t *cp;
+ nlibdb_t *dbp;
+ nlib_db_netlist(nlib,db_index,nl);
+ dbp=list_data(&(nlib->db),db_index);
+ nl=NULL;
+ for(dp=db_deck;dp!=NULL;dp=dp->next) /* walk through from db_deck to here */
+ {
+ if(dp->card==NULL)continue;
+ cp=dp->card;
+ scan->errdeck=dp;
+ scan->errcard=cp;
+
+ switch(cp->token)
+ {
+ case Knlib_param:
+ if(cp->val!=NULL)
+ {
+ card_t *p;
+ float min=0,max=0,qty=0,v;
+ int h_min=0, h_max=0, h_qty=0;
+
+ for(p=cp->next;p!=NULL;p=p->next)
+ {
+ if(p->val!=NULL)
+ {
+ v=parse_float(p->val);
+ switch(p->token)
+ {
+ case Knlib_min:
+ min=v; h_min++;
+ break;
+ case Knlib_max:
+ max=v; h_max++;
+ break;
+ case Knlib_qty:
+ qty=v; h_qty++;
+ break;
+ }
+ }
+ }
+ if(h_min&&h_max&&h_qty)
+ {
+ nlib_add_pm(nlib,db_index, cp->val, min, max, floorf(qty));
+ break;
+ }
+ }
+ scan->errdeck=dp;
+ scan->errcard=dp->card;
+ parse_error(scan,"mangled param statement\n");
+ break;
+
+ case Knlib_input:
+ case Knlib_output:
+ if(cp->val!=NULL)
+ {
+ card_t *p;
+ char *names[64]; /* max limit */
+ int i,qnames=0;
+ nlibiodef_t *iop;
+ int tokens=0, wires=0, digital=0, h_stuff=0;
+
+ for(i=0,p=cp->next;(p!=NULL)&&(i<64);p=p->next,i++)
+ names[i]=p->str;
+
+ qnames=i;
+ list_iterate(&(nlib->iodefs),i,iop)
+ {
+ if(strcmp(cp->val,iop->encoding)==0)
+ {
+ tokens=iop->tokens;
+ wires=iop->wires;
+ digital=iop->digitize;
+ h_stuff=1;
+ if(0)fprintf(stderr,"got stuff %s %i %i \n",cp->val,wires,qnames);
+ }
+ }
+
+ if(h_stuff && (wires==qnames)&& (dbp!=NULL) )
+ {
+
+ if(cp->token==Knlib_input)
+ nlib_add_io(nlib,db_index,&(dbp->in),tokens,wires,digital,names);
+ if(cp->token==Knlib_output)
+ nlib_add_io(nlib,db_index,&(dbp->out),tokens,wires,digital,names);
+ break;
+ }
+ }
+ scan->errdeck=dp;
+ scan->errcard=dp->card;
+ parse_error(scan,"mangled input/output statement \n");
+ break;
+ case Knlib_function:
+ if(cp->val!=NULL)
+ {
+ nlib_db_func(nlib,db_index,cp->val);
+ break;
+ }
+ parse_error(scan,"mangled function line \n");
+ break;
+
+ case Knlib_reference:
+ if(cp->val!=NULL)
+ {
+ card_t *p;
+ char *str_name=NULL;
+ eqn_t cshunt,rseries,delay;
+ int h_cshunt=0, h_rseries=0, h_delay=0;
+ int nl_index=-1, top_index=-1;
+
+ for(p=cp->next;p!=NULL;p=p->next)
+ {
+ if(p->val!=NULL)
+ switch(p->token)
+ {
+ case Knlib_name:
+ str_name=p->val;
+ break;
+ case Knlib_cshunt:
+ cshunt=eqn_parse(p->val);
+ h_cshunt++;
+ break;
+ case Knlib_rseries:
+ rseries=eqn_parse(p->val);
+ h_rseries++;
+ break;
+ case Knlib_delay:
+ delay=eqn_parse(p->val);
+ h_delay++;
+ break;
+ default:
+ scan->errdeck=dp;
+ scan->errcard=p;
+ parse_warn(scan,"reference: unknown word %s\n",cp->str);
+ }
+ }
+ if(str_name!=NULL)
+ nl_index=netlist_findnode(dbp->nl,str_name);
+
+ if(nl_index>=0)
+ {
+ nlibrefnode_t rn;
+ int l;
+
+ top_index=names_check(nlib->vref,cp->val);
+ if(top_index<0)
+ {
+ top_index=nlib->qvref;
+ names_add(nlib->vref,top_index,cp->val);
+ nlib->qvref++;
+ }
+
+ for(l=0;l<MAXSKEW_PARAMS;l++)
+ rn.skew[l]=eqn_empty();
+
+ rn.vrefi=top_index;
+ rn.devnodei=nl_index;
+ if(h_delay)
+ rn.skew[RTdelay]=delay;
+ if(h_rseries)
+ rn.skew[RTrseries]=rseries;
+ if(h_cshunt)
+ rn.skew[RTcshunt]=cshunt;
+
+ list_add(&(dbp->refnodes),&rn);
+ break;
+ }
+ else { parse_warn(scan,"reference netlist node %s not found, ignoring\n",str_name); break; }
+ }
+ parse_error(scan,"mangled reference line cp=%s val=%s\n",cp->str,cp->val);
+ break;
+ case Knlib_netlist:
+ break;
+ case Knlib_spice:
+ break;
+ case Knlib_end_netlist:
+ break;
+ default:
+ scan->errdeck=dp;
+ scan->errcard=cp;
+ parse_warn(scan,"ignoring unknown card %s\n",cp->str);
+ break;
+ }
+ }
+ if(dbp!=NULL)
+ nlib_db_fixup(nlib,dbp);
+ else assert(0);
+ dbp=NULL;
+ db_index=-1;
+ break;
+ }
+ }
+ }
+
+
+ }
+ /* check memory after parse */ free(malloc(32));
+ nlib_fixup(nlib);
+ if(eqn_mem_pop()!=nlib->eqn_mem)assert(0);
+ return list_qty(&(nlib->db));
+}
diff --git a/spiceparser/netlist_lib.h b/spiceparser/netlist_lib.h
new file mode 100644
index 0000000..320ef13
--- /dev/null
+++ b/spiceparser/netlist_lib.h
@@ -0,0 +1,275 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_lib.h, definitions for netlist library routines
+ Conrad Ziesler
+*/
+
+#ifndef __EQN_H__
+#include "eqn.h"
+#endif
+
+#ifndef __NETLIST_H__
+#include "netlist.h"
+#endif
+
+#ifndef __BITLIST_H__
+#include "bitlist.h"
+#endif
+
+#define NLIBIO_MAXNODES 4
+
+/* convenience structures */
+typedef struct nlibiodef_st
+{
+ char *encoding;
+ int wires;
+ int tokens;
+ int digitize;
+}nlibiodef_t;
+
+
+/* input definition */
+typedef struct nlibio_st
+{
+ int tokens;
+ int qnodes;
+ int digitize;
+ int nodes[NLIBIO_MAXNODES];
+}nlibio_t;
+
+typedef struct nlibiol_st
+{
+ list_t iol;
+ int qtokens; /* product (iol[k].tokens) */
+}nlibiol_t;
+
+/* parameter range */
+typedef struct nlibpm_st
+{
+ int index; /* index into netlist parameter list */
+ float min, max;
+ int qty;
+}nlibpm_t;
+
+typedef struct nlibfunc_st
+{
+ int p_delay; /* phases of delay before we begin computations */
+ int p_cycle; /* phases per cycle (compute each n phases) */
+ int p_offset; /* phases between inputs sampled and outputs valid */
+ int qin;
+ int qout;
+ int map[2]; /* alloc in place, size = qin*sizeof(int) */
+}nlibfunc_t;
+
+/* function reference */
+typedef struct nlibfref_st
+{
+ int index;
+}nlibfref_t;
+
+
+
+/* reference nodes and associated skew parameters */
+typedef enum nlibreftype_en
+{
+ RTrseries=0,
+ RTcshunt=1,
+ RTdelay=2,
+ RTqty
+}nlibreftype_t;
+
+#define MAXSKEW_PARAMS 3
+typedef struct nlibrefnode_st
+{
+ eqn_t skew[MAXSKEW_PARAMS]; /* RTxxx indices */
+ int vrefi; /* index into vref structure */
+ int devnodei; /* node index in netlist */
+}nlibrefnode_t;
+
+/* database object */
+typedef struct nlibdb_st
+{
+ netlist_t *nl;
+ nlibiol_t in,out;
+ nlibfref_t map; /* mapping between input and output tokens */
+ list_t params;
+ list_t refnodes;
+ float *pvals;
+}nlibdb_t;
+
+
+typedef struct nlibflatdb_st
+{
+ int lib_index; /* index from process */
+ int db_index; /* index into db list */
+ int qvals; /* cache db->params.q */
+ float *pvals; /* copy db pvals to here */
+ list_t uservals; /* array of user gate physical parameters */
+}nlibflatdb_t;
+
+/* container of database objects */
+typedef struct nlib_st
+{
+ list_t iodefs;
+ list_t db; /* our database of nlibdb objects */
+ names_t *dbref; /* database gate reference names */
+ names_t *vref; /* voltage reference node names */
+ int qvref;
+ list_t funcs; /* ptrs */
+ names_t *funcnames;
+ eqnlist_t eqnl; /* top level parameters we can use anywhere in eqns */
+ bitlist_t *flags; /* user can select set of elements to use */
+ list_t flatdb; /* database of flat info */
+ void *eqn_mem;
+}nlib_t;
+
+#define NLIB_MAXPHASES 4
+
+typedef struct nlib_icall_st
+{
+ int dbi;
+ int flatdbi;
+ float *in[NLIBIO_MAXNODES];
+ float *out[NLIBIO_MAXNODES];
+ int itokens[NLIB_MAXPHASES], otokens[NLIB_MAXPHASES], ctoken;
+ int ver;
+ int err;
+ int idigitize, odigitize;
+ int inode,onode;
+}nlib_icall_t;
+
+#define NLIB_MAXFREF 64
+typedef struct nlib_ifref_st
+{
+ float *val;
+ float vals[NLIB_MAXPHASES];
+ char name[NLIB_MAXFREF];
+}nlib_ifref_t;
+
+typedef enum nlib_refid_en
+{
+ NLIBref_vss, /* the vdd/vss values are used by cmos digitalize */
+ NLIBref_vdd,
+ NLIBref_clk, /* clk is generic refering to some clock signal */
+ NLIBref_firstunused, /* user can allocate any ref ids after this point */
+ NLIBref_max=512
+}nlib_refid_e;
+
+typedef struct nlib_iface_st
+{
+ nlib_t *nlib;
+ list_t icalls;
+ list_t frefs;
+ int ref_map[NLIBref_max];
+ int phase;
+ float * (*lookup_node_f)(void *user, char *name);
+ void *user;
+}nlib_iface_t;
+
+typedef enum nlib_tokens_en
+{
+ Knlib_start=1024, Knlib_nlib,Knlib_input, Knlib_output,
+ Knlib_param, Knlib_netlist, Knlib_spice,
+ Knlib_encoding, Knlib_wires,
+ Knlib_tokens, Knlib_digitize, Knlib_digital, Knlib_qtyin, Knlib_qtyout,
+ Knlib_end_digital, Knlib_min, Knlib_max, Knlib_qty,
+ Knlib_function, Knlib_end_netlist, Knlib_define,
+ Knlib_reference, Knlib_name, Knlib_rseries, Knlib_cshunt, Knlib_delay,
+ Knlib_p_delay, Knlib_p_offset, Knlib_p_cycle,
+ Knlib_end
+}nlib_tokens_t;
+
+#define NLIB_TOKENS { \
+ { Knlib_nlib, ".nlib" }, \
+ { Knlib_input, ".input" }, \
+ { Knlib_output, ".output" }, \
+ { Knlib_define, ".define" }, \
+ { Knlib_param, ".param" }, \
+ { Knlib_netlist, ".netlist" }, \
+ { Knlib_end_netlist, ".end_netlist" }, \
+ { Knlib_spice, ".spice" }, \
+ { Knlib_encoding, ".encoding" }, \
+ { Knlib_digital, ".digital" }, \
+ { Knlib_end_digital, ".end_digital" }, \
+ { Knlib_qtyout, ".qtyout" }, \
+ { Knlib_qtyin, ".qtyin" }, \
+ { Knlib_digitize, ".digitize" }, \
+ { Knlib_min, ".min" }, \
+ { Knlib_max, ".max" }, \
+ { Knlib_qty, ".qtysteps" }, \
+ { Knlib_function, ".function" }, \
+ { Knlib_tokens, ".tokens" }, \
+ { Knlib_wires, ".wires" }, \
+ { Knlib_name, ".name" }, \
+ { Knlib_rseries, ".rseries" }, \
+ { Knlib_cshunt, ".cshunt" }, \
+ { Knlib_delay, ".delay" }, \
+ { Knlib_reference, ".reference" }, \
+ { Knlib_p_delay, ".p_delay" }, \
+ { Knlib_p_offset, ".p_offset" }, \
+ { Knlib_p_cycle, ".p_cycle" }, \
+ { Knlib_end, NULL } }
+
+
+typedef struct nlib_process_st
+{
+ /* filled in by user */
+ void (*process)(struct nlib_process_st *proc);
+ void *user;
+ nlib_t *nlib;
+
+ /* filled in by nlib_process before user->process() is called */
+ int lib_index;
+ int db_index;
+ netlist_t *nl;
+}nlib_process_t;
+
+
+int nlib_parse(nlib_t *nlib, scanner_t *scan);
+int nlib_add_io(nlib_t *nlib, int dbindex, nlibiol_t *io, int tokens, int nodes, int dig, char **names);
+int nlib_init(nlib_t *nlib);
+int nlib_add_pm(nlib_t *nlib, int dbi, char *str, float min, float max, int qty);
+int nlib_new_db(nlib_t *nlib, char *str);
+int nlib_db_netlist(nlib_t *nlib, int index, netlist_t *nl);
+int nlib_db_func(nlib_t *nlib, int index, char *str);
+void nlib_process(nlib_process_t *user, int screened);
+void nlib_fixup(nlib_t *nlib);
+void nlib_disable(nlib_t *nlib, int index);
+int nlib_isdisabled(nlib_t *nlib, int index);
+
+void nlib_release(nlib_t *nlib);
+
+void *nlib_flat(nlib_process_t *user, int s_uservals, int q_uservals);
+void nlib_o_spice_subckts(nlib_t *nlib, void * of_fp);
+void nlib_o_spice_call(nlib_t *nlib, int index, int i_node, int o_node, int *skt, void * of);
+void nlib_o_spice_refs(nlib_t *nlib, void * of_fp);
+int nlib_flatdb_write(nlib_t *nlib, void * file_fp);
+int nlib_flatdb_read(nlib_t *nlib, void * file_fp);
+
+/* interface routines */
+
+nlib_ifref_t *nlib_iface_getref(nlib_iface_t *iface, int id);
+void nlib_iface_phase(nlib_iface_t *iface);
+int nlib_i_spice_calls(nlib_iface_t *iface, void * cktf_fp);
+void nlib_iface_init(nlib_iface_t *iface, nlib_t *nlib);
+void nlib_iface_release(nlib_iface_t *iface);
+
+
diff --git a/spiceparser/netlist_spice.c b/spiceparser/netlist_spice.c
new file mode 100644
index 0000000..4d15f77
--- /dev/null
+++ b/spiceparser/netlist_spice.c
@@ -0,0 +1,1455 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* spice.c: read hierachical spice deck composed of M and C and X
+
+ Conrad Ziesler
+*/
+
+
+#include <math.h>
+#include <ctype.h>
+#include <stdio.h>
+#include "debug.h"
+
+/* The following is copied from xcircuit.h */
+#ifdef TCL_WRAPPER
+ #define Fprintf tcl_printf
+ #define Flush tcl_stdflush
+#else
+ #define Fprintf fprintf
+ #define Flush fflush
+#endif
+
+
+int __debug_spice__=2;
+
+#ifndef STRIP_DEBUGGING
+#define D(level,a) do { if(__debug_spice__>(level)) a; } while(0)
+#else
+#define D(level,a)
+#endif
+
+/* spice deck
+
+.SUBCKT CKT1 3 4 5
+M0 6 3 1 1 NMOS W=1.025U L=0.350U AD=0.0 AS=0.0 PD=0.0 PS=0.0
+M1 7 4 6 1 NMOS W=1.025U L=0.350U AD=0.0 AS=0.0 PD=0.0 PS=0.0
+
+C0 3 1 1.92627e-15
+C1 4 1 1.8152e-15
+
+.ENDS
+
+*comment
+
+X1464 3 583 589 CKT6
+*/
+
+#define __NETLIST_SPICE_C__ 1
+
+
+#ifndef __NETLIST_H__
+#include "netlist_dev.h"
+#endif
+
+
+
+#ifndef __NETLIST_SPICE_H__
+#include "netlist_spice.h"
+#endif
+
+tokenmap_t spice_tokens[]=SPICE_TOKENS;
+
+/******* Hashing Clients *******/
+
+uint paramclient_hash(int max, void *data, int size)
+{
+ return hash_strhash(max, ((char *)data)+sizeof(paramload_t), size-sizeof(paramload_t));
+}
+
+
+int paramclient_cmp(int sizea, void *a, int sizeb, void *b)
+{
+ if(a==NULL)return 1;
+ if(b==NULL)return -1;
+ if(sizea > sizeb) return 1;
+ if(sizea < sizeb) return -1;
+ return memcmp( ((char *) a) + sizeof(paramload_t), ((char *)b ) + sizeof(paramload_t),sizeb-sizeof(paramload_t) );
+}
+
+static callparam_t *new_callparam(char *str, eqn_t eqn)
+{
+ callparam_t *pc;
+ pc=malloc(sizeof(callparam_t)+strlen(str));
+ assert(pc!=NULL);
+ strcpy(pc->str,str);
+ pc->eqn=eqn;
+ return pc;
+}
+
+
+static paramclient_t *add_param(hash_t *h, char *str, eqn_t eqn)
+{
+ int l;
+ char data[4096];
+ paramclient_t *pc;
+ pc=(void *)data;
+ l=strlen(str)+1;
+ if(l>(sizeof(data)-sizeof(paramclient_t)))
+ l=sizeof(data)-sizeof(paramclient_t);
+ pc->payload.eqn=eqn;
+ pc->payload.patch_call=NULL;
+ pc->payload.global_i=-1;
+ memcpy(pc->str,str,l);
+ return hash_add(h,pc,l+sizeof(paramload_t));
+}
+
+uint nodeclient_hash(int max, void *data, int size)
+{
+ return hash_strhash(max, ((char *)data)+sizeof(hashload_t), size-sizeof(hashload_t));
+}
+
+int nodeclient_cmp(int sizea, void *a, int sizeb, void *b)
+{
+ if(a==NULL)return 1;
+ if(b==NULL)return -1;
+ if(sizea > sizeb) return 1;
+ if(sizea < sizeb) return -1;
+ return memcmp( ((char *) a) + sizeof(hashload_t), ((char *)b ) + sizeof(hashload_t), sizea-sizeof(hashload_t) );
+}
+
+/* some helper functions for hash clients */
+
+static nodeclient_t *find_hashtab(hash_t *tab, uchar *str)
+{
+ int l;
+ l=strlen(str)+1;
+ return hash_find(tab,str-sizeof(hashload_t),sizeof(hashload_t)+l);
+}
+
+subckt_t *spice_find_subckt(subckt_t *parent, char *name)
+{
+ nodeclient_t *tc;
+ tc=find_hashtab(parent->cktdir,(uchar *)name);
+ return tc->payload.data.subckt;
+}
+
+
+list_t spice_list_subckt(subckt_t *parent)
+{
+ list_t foo;
+ subckt_t *ckt;
+ int i;
+ hash_t *tab;
+ hashbin_t *bp;
+ node_t p;
+
+ list_init(&foo,sizeof(subckt_t *),LIST_EXPMODE);
+ if(parent==NULL)return foo;
+
+ tab=parent->cktdir;
+ FORALL_HASH(tab,i,bp)
+ {
+ p=hash_bin2user(bp);
+ ckt=p->payload.data.subckt;
+ list_add (&foo,&ckt);
+ }
+ return foo;
+}
+
+
+static nodeclient_t *add_hashtab(hash_t *tab, uchar *str, hashload_t payload)
+{
+ int l;
+ uchar *strp=str;
+ nodeclient_t *cp;
+ static unsigned data[16000];
+ nodeclient_t *nd=(void *)data;
+ assert(tab!=NULL);
+ nd->payload=payload;
+ l=0;
+ while(strp[0]!=0)
+ {
+ nd->str[l]=strp[0];
+ strp++; l++;
+ }
+ nd->str[l]=0;
+ l++;
+ assert(l< (16000-sizeof(nodeclient_t)));
+ if(tab->hashfunc!=nodeclient_hash)assert(0);
+ cp=hash_add(tab,nd,(sizeof(hashload_t)+l));
+ D(20,Fprintf(stderr,"add_hashtab(%p,%s,..) cp=%p \n",tab,str,cp));
+ return cp;
+}
+
+
+
+#define warning(d,c,s) do { scan->errdeck=d; scan->errcard=c; parse_warn(scan,s); } while(0)
+#define error(d,c,s) do { scan->errdeck=d; scan->errcard=c; parse_error(scan,s); } while(0)
+#define checkvalid(d,q) scanner_checkvalid(d,q)
+
+static eqn_t parseval(deck_t *d, card_t *c, uchar *val)
+{
+ uchar *ps;
+ eqn_t eqn;
+ eqn=eqn_empty();
+
+ if(val==NULL)return eqn;
+
+ for(ps=val;ps[0]!=0;ps++)
+ if(!isspace(ps[0]))break;
+
+ if(ps[0]=='\'') ps++; /* hack */
+
+ eqn=eqn_parse(ps);
+
+ return eqn;
+}
+
+
+
+/************************************************************************/
+/******* PASS 2 : create subcircuit definitions (for forward ref) ****/
+/******* and count devices (for memory alloc) ****/
+/******* fill in all devices and nodes (except x subckt) ****/
+/************************************************************************/
+
+
+
+static void skip_subckt(deck_t **thedeckpp)
+{
+ int i;
+ deck_t *dp=*thedeckpp;
+ i=0;
+
+ while(dp!=NULL)
+ {
+ if(dp->card!=NULL)
+ {
+ if(dp->card->token==Kends)i--;
+ if(dp->card->token==Ksubckt)i++;
+ }
+ if(i==0)break;
+ dp=dp->next;
+ }
+ *thedeckpp=dp;
+}
+
+static subckt_t *new_subckt(deck_t **thedeckpp, subckt_t *parent, scanner_t *scan)
+{
+ int i, qtynodes, qtyparams, qtycallparams, qtylparams;
+ int qtym, qtyc, qtyx, qtyr, qtyl, qtyv, qtyi;
+ int qtysubckt, qtyglobal;
+ subckt_t *scktp;
+ card_t *cp;
+ deck_t *dp,*d=*thedeckpp,*dplast=NULL;
+ int size;
+ void *p;
+ uchar *name;
+ hashload_t payload={ PAYLOAD_null, {NULL} };
+
+ qtycallparams=0;
+ qtynodes=0;
+ qtyparams=0;
+ qtylparams=0;
+ qtysubckt=0;
+ qtyglobal=0;
+
+ if(!checkvalid(d,2))error(d,d->card,"invalid subckt definition");
+ name=d->card->next->str;
+
+ i = 0;
+ for(cp=d->card->next->next; cp!=NULL; cp=cp->next)
+ {
+ if(cp->val==NULL) qtynodes++;
+ else qtylparams++;
+ i++;
+ }
+
+ qtym = 0;
+ qtyc = 0;
+ qtyr = 0;
+ qtyl = 0;
+ qtyx = 0;
+ qtyv = 0;
+ qtyi = 0;
+
+ for(dp=d; dp!=NULL; dp=dp->next)
+ {
+ uchar a;
+ dplast=dp;
+ if(dp->card==NULL)continue;
+
+ if( (dp->card->token==Ksubckt) && (dp!=d))
+ { skip_subckt(&dp); qtysubckt++; continue; } /* consume .ends token */
+
+ if(dp==NULL)break;
+ if(dp->card==NULL)continue;
+
+ if(dp->card->token==Kend)break;
+ if(dp->card->token==Kends)break;
+
+ /*
+ if(parent!=NULL)
+ { if(dp->card->token==Kends)break; }
+ else { if(dp->card->token==Kend)break; }
+ */
+
+ a=dp->card->str[0];
+ if(a=='x')
+ {
+ qtyx++;
+ for(cp=dp->card->next;cp!=NULL;cp=cp->next)
+ if(cp->val!=NULL)qtycallparams++;
+ }
+
+ if(a=='m') qtym++;
+ if(a=='c') qtyc++;
+ if(a=='r') qtyr++;
+ if(a=='l') qtyl++;
+ if(a=='v') qtyv++;
+ if(a=='i') qtyi++;
+
+ if(dp->card->token==Kparam)
+ {
+ for(cp=dp->card->next;cp!=NULL;cp=cp->next)
+ qtyparams++;
+ }
+ if(dp->card->token==Kglobal)
+ {
+ for(cp=dp->card->next;cp!=NULL;cp=cp->next)
+ qtyglobal++;
+ }
+ }
+
+ if(dp==NULL) {
+ if(parent==NULL)
+ {
+ /*
+ uchar *p,buf[64]=".END ";
+ D(50,Fprintf(stderr,"ignoring lack of .END token\n"));
+ assert(dplast!=NULL);
+ assert(dplast->next==NULL);
+ dp=dplast->next=new_deck();
+ dp->next=NULL;
+ p=buf;
+ dp->card=make_card(&p,PARSE_CASE_TOLOWER);
+ dp->card->token=Kend;
+ */
+ }
+ else
+ {
+ if(parent==NULL)error(d,NULL,"No .END found");
+ else error(d,NULL,"No .ENDS found");
+ }
+ }
+
+ D(10, Fprintf(stderr,"Got %i subckts, %i x's %i m's %i c's %i r's "
+ "%i l %i v %i i's\n",
+ qtysubckt, qtyx, qtym, qtyc, qtyr, qtyl, qtyv, qtyi));
+
+ size=
+ sizeof(subckt_t) +
+ (sizeof(node_t)*qtynodes) +
+ (sizeof(m_t)*qtym) +
+ (sizeof(x_t)*qtyx) +
+ (sizeof(c_t)*qtyc) +
+ (sizeof(r_t)*qtyr) +
+ (sizeof(l_t)*qtyl) +
+ (sizeof(v_t)*qtyv) +
+ (sizeof(i_t)*qtyi) +
+ (strlen(name) + 2);
+
+ scktp=p=malloc(size+1024); /* 1024 is debug pad */
+
+ assert(scktp!=NULL);
+ memset(scktp,0,size);
+ memset(((char *)scktp)+size,'a',1024);
+ p= ((char *)p+sizeof(subckt_t));
+
+ scktp->defn=p;
+ scktp->ndefn=qtynodes;
+ p= ((char *)p+(sizeof(node_t)*qtynodes));
+
+ scktp->m=p;
+ scktp->nm=qtym;
+ p= ((char *)p+(sizeof(m_t)*qtym));
+
+ scktp->c=p;
+ scktp->nc=qtyc;
+ p= ((char *)p+(sizeof(c_t)*qtyc));
+
+ scktp->r=p;
+ scktp->nr=qtyr;
+ p= ((char *)p+(sizeof(r_t)*qtyr));
+
+ scktp->l=p;
+ scktp->nl=qtyl;
+ p= ((char *)p+(sizeof(l_t)*qtyl));
+
+ scktp->v=p;
+ scktp->nv=qtyv;
+ p= ((char *)p+(sizeof(v_t)*qtyv));
+
+ scktp->i=p;
+ scktp->ni=qtyi;
+ p= ((char *)p+(sizeof(i_t)*qtyi));
+
+ scktp->x=p;
+ scktp->nx=qtyx;
+ p= ((char *)p+(sizeof(x_t)*qtyx));
+
+ scktp->name=p;
+ strcpy(scktp->name,name);
+ p= ((char *)p+strlen(name)+2);
+
+
+ scktp->scale=1.0;
+ scktp->mult=1.0;
+ scktp->subckt_magic=SUBCKT_MAGIC;
+ assert((((char *)p)-((char *)scktp))==size); /* sanity check */
+
+ /* estimate good size for hashtable */
+ scktp->nodes=hash_new((qtym*3)+(qtyx*4),nodeclient_hash,nodeclient_cmp);
+
+ scktp->flag=0;
+ scktp->params=hash_new(qtyparams,paramclient_hash,paramclient_cmp);
+ scktp->lparams=hash_new(qtylparams,paramclient_hash,paramclient_cmp);
+ scktp->parent=parent;
+ scktp->cktdir=hash_new(qtysubckt,nodeclient_hash,nodeclient_cmp);
+ scktp->global=hash_new(qtyglobal,nodeclient_hash,nodeclient_cmp);
+
+ /* store defn nodes, and ptrs */
+ for(i=0,cp=d->card->next->next;cp!=NULL;cp=cp->next)
+ {
+ if(cp->val==NULL) /* skip params on line */
+ {
+ if(find_hashtab(scktp->nodes,cp->str)!=NULL)
+ warning(d,cp,"duplicate node in subckt definition");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->defn[i]=add_hashtab(scktp->nodes,cp->str,payload);
+ i++;
+ }
+ }
+
+ /* do subckt params (those on the .subckt line) */
+
+ for(cp=d->card->next->next;cp!=NULL;cp=cp->next)
+ {
+ if(cp->val!=NULL) /* skip nodes on line */
+ add_param(scktp->lparams,cp->str,parseval(d,cp,cp->val));
+ }
+
+ /* do spice deck */
+
+ /* reinitialize device counters */
+ qtyr = 0;
+ qtyl = 0;
+ qtym = 0;
+ qtyc = 0;
+ qtyx = 0;
+ qtyv = 0;
+ qtyi = 0;
+
+ for (dp = d; dp != NULL; dp = dp->next)
+ {
+ uchar a;
+ if (dp->card == NULL) continue;
+
+ if ((dp->card->token == Ksubckt) && (dp != d))
+ {
+ subckt_t *child=NULL;
+ child=new_subckt(&dp,scktp,scan);
+ payload.data.subckt=child;
+ payload.flag=PAYLOAD_subckt;
+ add_hashtab(scktp->cktdir,child->name,payload);
+ continue;
+ }
+ if(dp==NULL)break;
+ if(dp->card==NULL)continue;
+ if(parent!=NULL)
+ { if(dp->card->token==Kends)break; }
+ else { if(dp->card->token==Kend)break; }
+
+ a=dp->card->str[0];
+ if(a=='x')
+ {
+ int k=0;
+ x_t *xp;
+ card_t *last;
+
+ assert(qtyx<scktp->nx);
+ xp=&(scktp->x[qtyx]);
+ xp->nn=0;
+ xp->nl=0;
+ xp->nodes=NULL;
+ xp->locals=NULL;
+
+ if(!checkvalid(dp,2))error(d,NULL,"invalid subckt call");
+ for(i=0,last=cp=dp->card->next;cp!=NULL;cp=cp->next,i++)
+ {
+ if(cp->val!=NULL)break; last=cp;
+ }
+
+ if(cp!=NULL)
+ {
+ for(k=0;cp!=NULL;cp=cp->next,k++);
+ }
+ else k=0;
+
+ xp->deck=dp;
+ xp->rest=last;
+ xp->nodes=malloc((sizeof(node_t)*i)+(sizeof(paramclient_t*)*k));
+ if(k==0)
+ xp->locals=NULL;
+ else
+ xp->locals=(void *)((char *)(xp->nodes))+(sizeof(node_t)*(i));
+ xp->nn=i-1;
+ xp->nl=k;
+ assert(xp->nodes!=NULL);
+
+ payload.flag=PAYLOAD_null;
+ payload.data.s=NULL;
+
+ for(i=0,cp=dp->card->next;(cp!=NULL)&&(cp!=last);cp=cp->next,i++)
+ {
+ xp->nodes[i]=add_hashtab(scktp->nodes,cp->str,payload);
+ if(0)Fprintf(stderr,"X:%s adding node %p cp->str=%s\n",dp->card->str,xp->nodes[i],cp->str);
+ }
+ if(cp!=NULL)
+ {
+ for(k=0,cp=cp->next;(cp!=NULL);cp=cp->next,k++)
+ if(cp->val!=NULL)
+ { xp->locals[k]=new_callparam(cp->str,parseval(dp,cp,cp->val)); }
+ else xp->locals[k]=NULL;
+ }
+ qtyx++;
+ }
+ if(a=='m') /* Mident d g s b model L=val W=val other_params... */
+ {
+ m_t *mp;
+ if(!checkvalid(dp,8))error(d,NULL,"invalid mosfet card");
+ mp=&(scktp->m[qtym]);
+ cp=dp->card->next;
+
+ payload.flag=PAYLOAD_null;
+ payload.data.s=NULL;
+
+ for(i=0;i<4;i++)
+ {
+ mp->nodes[i]=add_hashtab(scktp->nodes,cp->str,payload);
+ cp=cp->next;
+ }
+ mp->type=0;
+ /* hope this is n or p */
+ if((cp->str[0]=='n')||(cp->str[0]=='p'))
+ mp->type=cp->str[0];
+ else
+ {
+ uchar *p;
+ for(p=cp->str;p[0]!=0;p++)
+ if((p[0]=='n')||(p[0]=='p'))
+ mp->type=p[0];
+ }
+ if(mp->type==0)
+ {
+ Fprintf(stderr,"Couldn't determine fet type from model name %s\n",cp->str);
+ }
+
+ mp->rest=cp;
+ mp->deck=dp;
+ cp=cp->next;
+
+ mp->l =eqn_const(1); mp->w=eqn_const(1);
+ mp->as=eqn_const(-1); mp->ad=eqn_const(-1);
+ mp->ps=eqn_const(-1); mp->pd=eqn_const(-1);
+
+ for(i=0;cp!=NULL;cp=cp->next,i++)
+ {
+ if( (cp->str[0]=='l') && (cp->str[1]==0)) mp->l=parseval(dp,cp,cp->val);
+ if( (cp->str[0]=='w') && (cp->str[1]==0)) mp->w=parseval(dp,cp,cp->val);
+ if( (cp->str[0]=='a') && (cp->str[1]=='s') && (cp->str[2]==0) )
+ mp->as=parseval(dp,cp,cp->val);
+ if( (cp->str[0]=='a') && (cp->str[1]=='d') && (cp->str[2]==0) )
+ mp->ad=parseval(dp,cp,cp->val);
+ if( (cp->str[0]=='p') && (cp->str[1]=='s') && (cp->str[2]==0) )
+ mp->ps=parseval(dp,cp,cp->val);
+ if( (cp->str[0]=='p') && (cp->str[1]=='d') && (cp->str[2]==0) )
+ mp->pd=parseval(dp,cp,cp->val);
+ }
+ qtym++;
+ }
+ if(a=='c') /* Cident node0 node1 value */
+ {
+ if(!checkvalid(dp,4))error(d,NULL,"invalid capacitor card");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->c[qtyc].nodes[0]=add_hashtab(scktp->nodes,dp->card->next->str,payload);
+ scktp->c[qtyc].nodes[1]=add_hashtab(scktp->nodes,dp->card->next->next->str,payload);
+ cp=dp->card->next->next->next;
+ scktp->c[qtyc].deck=dp;
+ scktp->c[qtyc].c=parseval(dp,cp,cp->str);
+ scktp->c[qtyc].rest=cp;
+ qtyc++;
+ }
+
+ if (a == 'r') /* Rident node0 node1 value */
+ {
+ if (!checkvalid(dp,4))error(d,NULL,"invalid resistor card");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->r[qtyr].nodes[0] =
+ add_hashtab(scktp->nodes,dp->card->next->str,payload);
+ scktp->r[qtyr].nodes[1] =
+ add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
+ cp=dp->card->next->next->next;
+ scktp->r[qtyr].deck=dp;
+ scktp->r[qtyr].r=parseval(dp,cp,cp->str);
+ scktp->r[qtyr].rest=cp;
+ qtyr++;
+ }
+
+ /* To be done: AC, pulse, and PWL sources */
+
+ if (a == 'v') /* Vident node0 node1 value */
+ {
+ if (!checkvalid(dp,4))error(d,NULL,"invalid voltage source card");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->v[qtyv].nodes[0] =
+ add_hashtab(scktp->nodes,dp->card->next->str,payload);
+ scktp->v[qtyv].nodes[1] =
+ add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
+ cp=dp->card->next->next->next;
+ scktp->v[qtyv].deck=dp;
+ scktp->v[qtyv].v=parseval(dp,cp,cp->str);
+ scktp->v[qtyv].rest=cp;
+ qtyv++;
+ }
+
+ if (a == 'i') /* Iident node0 node1 value */
+ {
+ if (!checkvalid(dp,4))error(d,NULL,"invalid current source card");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->i[qtyi].nodes[0] =
+ add_hashtab(scktp->nodes,dp->card->next->str,payload);
+ scktp->i[qtyi].nodes[1] =
+ add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
+ cp=dp->card->next->next->next;
+ scktp->i[qtyi].deck=dp;
+ scktp->i[qtyi].i=parseval(dp,cp,cp->str);
+ scktp->i[qtyi].rest=cp;
+ qtyi++;
+ }
+
+ if (a == 'l') /* Lident node0 node1 value */
+ {
+ if (!checkvalid(dp,4))error(d,NULL,"invalid inductor card");
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+ scktp->l[qtyl].nodes[0] =
+ add_hashtab(scktp->nodes,dp->card->next->str,payload);
+ scktp->l[qtyl].nodes[1] =
+ add_hashtab(scktp->nodes,dp->card->next->next->str,payload);
+ cp=dp->card->next->next->next;
+ scktp->l[qtyl].deck=dp;
+ scktp->l[qtyl].l=parseval(dp,cp,cp->str);
+ scktp->l[qtyl].rest=cp;
+ qtyl++;
+ }
+
+ if(dp->card->token==Kparam)
+ for(cp=dp->card->next;cp!=NULL;cp=cp->next)
+ {
+ if(cp->val==NULL)error(dp,cp,"couldn't find = in .param statement");
+ add_param(scktp->params,cp->str,parseval(dp,cp,cp->val));
+ D(10, Fprintf(stderr, "spice: adding param %s to scktp->params=%p \n",
+ cp->str, scktp->params));
+ }
+
+ if(dp->card->token==Kscale)
+ {
+ if(dp->card->val!=NULL)
+ scktp->scale=parse_float(dp->card->val);
+ else error(dp,dp->card,"need a value for .scale ");
+ }
+
+ if(dp->card->token==Kmult)
+ {
+ if(dp->card->val!=NULL)
+ scktp->mult=parse_float(dp->card->val);
+ else error(dp,dp->card,"need a value for .scale ");
+ }
+
+ payload.flag=PAYLOAD_null;
+ payload.data.p=NULL;
+
+ if(dp->card->token==Kglobal)
+ for(cp=dp->card->next;cp!=NULL;cp=cp->next)
+ add_hashtab(scktp->global,cp->str,payload);
+
+ if(dp->next==NULL) *thedeckpp=dp; /* ignore lack of end token */
+ }
+ if(dp!=NULL)
+ *thedeckpp=dp; /*dp->next;*/ /* skip .end token if present */
+
+ return scktp;
+}
+
+
+static void do_subckts(subckt_t *ckt, scanner_t *scan)
+{
+ x_t *xp;
+ nodeclient_t *hcp;
+ int i;
+
+ if(ckt==NULL)return;
+ if(ckt->flag)return;
+ ckt->flag=1;
+
+ for(i=0;i<ckt->nx;i++)
+ {
+ uchar *nm=NULL;
+ xp=ckt->x+i;
+ hcp=NULL;
+ if(xp->rest!=NULL)
+ {
+ subckt_t *search;
+ nm=xp->rest->str;
+ for(search=ckt;search!=NULL;search=search->parent)
+ if( (hcp=find_hashtab(search->cktdir,nm)) != NULL) break;
+ }
+ if(hcp==NULL)
+ { Fprintf(stderr,"subcircuit named [%s] not found in ckt [%s]\n",
+ nm,ckt->name); }
+ else {
+ assert(hcp->payload.flag==PAYLOAD_subckt);
+ xp->xp=hcp->payload.data.subckt;
+ assert(xp->xp!=NULL);
+ do_subckts(xp->xp,scan); /* recursion */
+ }
+ }
+
+}
+
+
+static subckt_t *new_ckt(deck_t *d, scanner_t *scan)
+{
+ deck_t *dp;
+ subckt_t *first=NULL;
+ deck_t topdeck;
+ card_t topcard[2];
+ topdeck.line.line=0;
+ topdeck.line.fileindex=0;
+ topdeck.next=d;
+ topdeck.card=&(topcard[0]);
+ topcard[0].next=&(topcard[1]);
+ topcard[0].str[0]=0;
+ topcard[0].token=Ksubckt;
+ strcpy(topcard[0].str,".su"); /* max 4 bytes */
+ topcard[0].val=NULL;
+ topcard[1].next=NULL;
+ topcard[1].token=Kother;
+ topcard[1].val=NULL;
+ strcpy(topcard[1].str,"TOP"); /* MAX 4 bytes */
+
+ dp=&topdeck;
+
+ first=new_subckt(&dp,NULL,scan);
+ first->subckt_magic=SUBCKT_MAGIC;
+ do_subckts(first,scan);
+ return first;
+}
+
+
+static void debug_subckts(void * dbg, subckt_t *ckt, int level)
+{
+ int i;
+ uchar pad[64]=" ";
+
+ if(ckt==NULL)return;
+ /*
+ if(ckt->flag)return;
+ ckt->flag=1;
+ */
+
+ pad[level*2]=0;
+
+ fprintf(dbg,"%s subckt %s nm=%i nc=%i nr=%i nx=%i\n",pad,ckt->name,ckt->nm,ckt->nc,ckt->nr,ckt->nx);
+ for(i=0;i<ckt->nm;i++)
+ {
+ node_t *n=ckt->m[i].nodes;
+ fprintf(dbg,"%s M %s %s %s %s\n%s +",pad,
+ n[0]->str,n[1]->str,n[2]->str,n[3]->str,pad);
+ debug_eqn(dbg,"l",&(ckt->m[i].l));
+ debug_eqn(dbg,"w",&(ckt->m[i].w));
+ debug_eqn(dbg,"as",&(ckt->m[i].as));
+ debug_eqn(dbg,"ad",&(ckt->m[i].ad));
+ debug_eqn(dbg,"ps",&(ckt->m[i].ps));
+ debug_eqn(dbg,"pd",&(ckt->m[i].ps));
+ fprintf(dbg,"\n");
+ }
+
+ for(i=0;i<ckt->nc;i++)
+ {
+ node_t *n=ckt->c[i].nodes;
+ fprintf(dbg,"%s C %s %s ",pad,
+ n[0]->str,n[1]->str);
+ debug_eqn(dbg,"c",&(ckt->c[i].c));
+ fprintf(dbg,"\n");
+ }
+
+ for(i=0;i<ckt->nr;i++)
+ {
+ node_t *n=ckt->r[i].nodes;
+ fprintf(dbg,"%s R %s %s ",pad,
+ n[0]->str,n[1]->str);
+ debug_eqn(dbg,"r",&(ckt->r[i].r));
+ fprintf(dbg,"\n");
+ }
+
+
+ for(i=0;i<ckt->nx;i++)
+ {
+ fprintf(dbg,"%s X %s : %p, %i nodes\n",pad,ckt->x[i].xp->name,ckt->x[i].nodes,ckt->x[i].nn);
+ debug_subckts(dbg,ckt->x[i].xp,level+1); /* recursion */
+ }
+
+}
+
+
+
+
+
+
+
+/**********************************************************************/
+/***************** PASS 3: operations on heirarchy *******************/
+/******************************-- flattening --- **********************/
+
+
+
+
+/* a couple of different lookup functions for equations and parameters
+ with slightly different semantics
+
+ lookup_params is for TERMINAL equations that need multipliers
+ lookup_params_nomult is for equations in '.param' statements
+ lookup_parents_call_eqns is for equations in subckt calls
+ ie: Xdddd blah blah v='eqn blah' ...
+*/
+#ifndef NO_EQUATIONS
+static eqn_t lookup_parents_call_eqns(stack_t *s, eqn_t *ep);
+static eqn_t lookup_params_nomult(stack_t *s, eqn_t *ep);
+static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m);
+#endif
+
+
+static void spice_recurse_subckts(spice_t *spice, subckt_t *ckt, stack_t *parent, void (*process)(stack_t *s, int flag, void *data),void *data)
+{
+ stack_t s;
+ int i;
+ s.nl=NULL;
+ s.scan=spice->scan;
+ if(ckt==NULL)return;
+
+ if(parent==NULL) { s.level=0; s.parent=NULL; s.ckt=ckt; s.call=NULL; s.top=&s; }
+ else { s.level=parent->level+1; s.parent=parent; s.ckt=ckt; s.call=NULL; s.top=s.parent->top; }
+
+ process(&s,0,data);
+
+ for(i=0;i<ckt->nx;i++)
+ { s.call=ckt->x+i; spice_recurse_subckts(spice,s.call->xp,&s,process,data); } /* recursion */
+
+ s.call=NULL;
+ process(&s,1,data);
+}
+
+
+
+static char * do_name(stack_t *s, char *str)
+{
+ static char buf[1024*63];
+ char *bp,*c;
+ stack_t *sp;
+ int l,q=0,sizebuf=sizeof(buf);
+ int m;
+
+ D(10,Fprintf(stderr,"doname: [%s] ",str));
+
+ m=sizebuf -4;
+ buf[sizebuf-1]=0;
+ bp=buf+sizebuf-1;
+
+ l=strlen(str);
+ bp-=l;
+ q+=l; assert(q<m);
+ memcpy(bp,str,l);
+
+ for(sp=s;sp!=NULL;sp=sp->parent)
+ {
+ if(sp->call==NULL)continue;
+ assert(sp->call->deck!=NULL);
+ assert(sp->call->deck->card!=NULL);
+ c=sp->call->deck->card->str;
+ l=strlen(c);
+ q+=l+1; assert(q<m);
+ bp--;
+ bp[0]='.';
+ bp-=l;
+ memcpy(bp,c,l);
+ }
+ D(10,Fprintf(stderr,"(%s)\n",bp));
+ return bp;
+}
+
+
+
+
+
+#ifdef NO_EQUATIONS
+static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m)
+{
+ ep->val=ep->val*m;
+ return *ep;
+}
+#else
+
+
+
+static paramclient_t * find_param_intable(hash_t *h, char *str)
+{
+ int l;
+ paramclient_t *pc,*tofind;
+ /* note to self: this trickery is dependent on hash.c doing the right thing which it does */
+ tofind=(void *)(str-sizeof(paramload_t));
+
+ l=strlen(str)+1;
+ D(30,Fprintf(stderr,"looking for %s in table %p l=%i ",str,h,l));
+ pc=hash_find(h,tofind,sizeof(paramload_t)+l);
+ D(30,Fprintf(stderr," hash_find=%p\n",pc));
+ return pc;
+}
+
+
+/* local (bottom) takes precedence over top (global) */
+static paramclient_t * find_param_bot(stack_t *s, char *str)
+{
+ stack_t *sp;
+ paramclient_t *r=NULL,*toret=NULL;
+
+ subckt_t *ckt;
+
+ for(sp=s;sp!=NULL;sp=sp->parent)
+ {
+ if(sp->ckt!=NULL)
+ {
+ ckt=sp->ckt;
+ r=find_param_intable(ckt->lparams,str);
+ if(toret==NULL)toret=r;
+ r=find_param_intable(ckt->params,str);
+ if(toret==NULL)toret=r;
+ }
+ }
+ return toret;
+}
+
+/* global (top) takes precidence over bottom (local) */
+static paramclient_t * find_param_top(stack_t *s, char *str)
+{
+ paramclient_t *r=NULL,*toret=NULL;
+ subckt_t *ckt;
+ stack_t *sp;
+
+ for(sp=s;sp!=NULL;sp=sp->parent)
+ {
+ if(sp->ckt!=NULL)
+ {
+ ckt=sp->ckt;
+ r=find_param_intable(ckt->lparams,str);
+ if(r!=NULL)toret=r;
+ r=find_param_intable(ckt->params,str);
+ if(r!=NULL)toret=r;
+ }
+ }
+ return toret;
+}
+
+
+
+
+static eqn_litref_t lookup_function(plookup_t *user, char *str)
+{
+ paramlookup_t *me=user->user;
+ paramclient_t *r;
+ eqn_litref_t index=eqn_litref_INIT;
+ char *hname;
+
+ if(1)r=find_param_bot(me->sp,str);
+ else r=find_param_top(me->sp,str);
+ if(r!=NULL)
+ {
+ /* this is not a renameable local parameter */
+ if(r->payload.patch_call==NULL)
+ {
+ /* we want to use this parameter, but don't have a global entry yet */
+ if(r->payload.global_i<0)
+ {
+ /* todo: lookup this param=equation now, in case it has dependencies */
+ eqn_t eq;
+ hname=do_name(me->sp,str);
+ D(5,Fprintf(stderr,"Lookup function: Adding eqn (%s) (%s)\n",str,hname));
+ D(5,debug_eqn(stderr,str,&(r->payload.eqn)));
+ D(5,Fprintf(stderr,"\n"));
+ eq=lookup_params_nomult(me->sp,&(r->payload.eqn));
+ r->payload.global_i=eqnl_add(&(me->nl->eqnl),eq,hname);
+ }
+ index=r->payload.global_i;
+ }
+ else /* we renamed this parameter, follow the indirection, make heir. name */
+ { /* also note we probably want to call lookup params now
+ using parent's context for subckt call
+ */
+ D(50,Fprintf(stderr,"Lookup rename: %s\n",str));
+ D(50,debug_eqn(stderr," eqn ",&(r->payload.patch_call->eqn)));
+ D(50,Fprintf(stderr,"\n"));
+ if(r->payload.global_i<0)
+ {
+ hname=do_name(me->sp,str);
+ D(5,Fprintf(stderr,"Lookup function rename: Adding eqn (%s) (%s)\n",str,hname));
+ D(5,debug_eqn(stderr," eqn ",&(r->payload.patch_call->eqn)));
+ r->payload.global_i=eqnl_add(&(me->nl->eqnl),
+ lookup_parents_call_eqns(me->sp, &(r->payload.patch_call->eqn)),
+ hname);
+ }
+ index=r->payload.global_i;
+ }
+ }
+ else /* an undefined reference, may be a sweep parameter, to be loaded from tracefile */
+ {
+ index=eqnl_find(&(me->nl->eqnl),str);
+ if(index<0)
+ {
+ D(3,Fprintf(stderr,"Netlist_sp: assuming %s is global sweep parameter\n",str));
+ index= eqnl_add(&(me->nl->eqnl),eqn_undefined(),str);
+ }
+ else D(3,Fprintf(stderr,"Netlist_sp: assume %s is a global parameter, not local\n",str));
+ }
+ return index;
+}
+
+
+static eqn_t lookup_parents_call_eqns(stack_t *s, eqn_t *ep)
+{
+ int r=0;
+ eqn_t v;
+ plookup_t plu;
+ paramlookup_t me;
+
+ if(s->parent!=NULL)
+ {
+ me.sp=s->parent;
+ me.nl=s->nl;
+ plu.user=&me;
+ plu.lookup=lookup_function;
+ v=eqn_copy(*ep);
+ D(10,debug_eqn(stderr,"lookup parents:", &v));
+ D(10,Fprintf(stderr,"\n"));
+ r=eqntok_depend(v.eqn,&plu);
+ if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
+ }
+ else D(1,Fprintf(stderr,"lookup parents eqn called, but we are at the top level\n"));
+ assert(s->parent!=NULL);
+ return v;
+}
+
+static eqn_t lookup_params_nomult(stack_t *s, eqn_t *ep)
+{
+ eqn_t v;
+ int r=0;
+ plookup_t plu;
+ paramlookup_t me;
+ me.sp=s;
+ me.nl=s->nl;
+ plu.user=&me;
+ plu.lookup=lookup_function;
+
+ v=eqn_copy(*ep);
+
+ if(v.eqn!=NULL)
+ r=eqntok_depend(v.eqn,&plu);
+
+ if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
+
+ return v;
+
+
+}
+
+static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m)
+{
+ eqn_t v;
+ int r=0;
+ plookup_t plu;
+ paramlookup_t me;
+ me.sp=s;
+ me.nl=s->nl;
+ plu.user=&me;
+ plu.lookup=lookup_function;
+
+ v=eqn_copy_m(*ep,m);
+
+ if(v.eqn!=NULL)
+ r=eqntok_depend(v.eqn,&plu);
+
+ if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
+
+ return v;
+}
+#endif
+
+
+
+static void count_stuff(stack_t *s, int flag, void *data)
+{
+ netlist_t *nl=data;
+ if(flag)return;
+ nl->e[DEVT_FET].qcount+=s->ckt->nm;
+ nl->e[DEVT_CAP].qcount+=s->ckt->nc;
+}
+
+
+
+
+
+static void build_stuff(stack_t *s, int flag, void *data)
+{
+ netlist_t *nl=data;
+ int i,q,j;
+ node_t n;
+ hashbin_t *bp;
+ hash_t *h,*globals,*h1;
+ x_t *call;
+ paramclient_t *pc,*findpc;
+ scanner_t *scan=s->scan;
+ if(flag)return; /* preorder */
+
+ h=s->ckt->nodes;
+ globals=s->top->ckt->global;
+ s->nl=nl;
+
+ D(40,Fprintf(stderr,"processing stack %p: s->top=%p s->parent=%p s->ckt=%p\n",s,s->top,s->parent,s->ckt));
+
+ /* first assign parent payloads to all the nodes in nodedir */
+ if(s->parent!=NULL)
+ {
+ call=s->parent->call;
+ assert(call!=NULL);
+
+ if(call->nn!=s->ckt->ndefn)
+ error(call->deck,call->rest,"Definition does not match use");
+
+ q=minimum(call->nn,s->ckt->ndefn);
+
+ for(i=0;i<q;i++)
+ {
+ assert(call->nodes[i]!=NULL);
+ assert(call->nodes[i]->payload.flag==PAYLOAD_gnptr);
+ s->ckt->defn[i]->payload.data=call->nodes[i]->payload.data;
+ s->ckt->defn[i]->payload.flag=PAYLOAD_parent;
+ }
+
+
+ /* lookup subckt call's and map to local params */
+
+ h1=s->ckt->lparams;
+ hash_forall(h1,i,bp) /* init patch ptrs to Null (so any previous invokation won't be used) */
+ {
+ pc=hash_bin2user(bp); pc->payload.patch_call=NULL; pc->payload.global_i=-1;
+ D(30,Fprintf(stderr,"considering hash table entry %i %s len=%i\n",i,pc->str,bp->size-sizeof(paramload_t)));
+ }
+
+ /* for each param in the x call line, patch local param if found */
+ for(i=0;i<call->nl;i++)
+ {
+ callparam_t *callp;
+ callp=call->locals[i];
+ if(callp==NULL)continue;
+
+ /* hackish hash_find: we pass a bogus object, who's string is at same location */
+ findpc=hash_find(h1,callp->str-sizeof(paramload_t),strlen(callp->str)+sizeof(paramload_t)+1);
+
+ if(findpc!=NULL) /* we link to this subckt eqn call */
+ findpc->payload.patch_call=callp;
+ else
+ D(2,Fprintf(stderr,"subckt call, specified parameter [%s] not found\n",callp->str));
+
+ D(5,Fprintf(stderr,"patching call %s",callp->str));
+ if(findpc!=NULL)D(5,debug_eqn(stderr," orig ",&(findpc->payload.eqn)));
+ D(5,debug_eqn(stderr," patch ",&(callp->eqn)));
+ D(5,Fprintf(stderr,"\n"));
+ }
+ }
+
+ /* if parent is NULL, then we are top level, specially create/process global nodes first */
+ else
+ {
+ assert(s->top->ckt==s->ckt);
+
+ FORALL_HASH(globals,i,bp)
+ {
+ char *flatname;
+ n=hash_bin2user(bp);
+ n->payload.flag=PAYLOAD_gnptr;
+ /* note to self: must use terminal indices, because node table may be reallocated as it grows */
+ flatname=do_name(s,n->str);
+ n->payload.data.t=netlist_node(nl,flatname,(void*)n);
+ }
+ }
+
+
+ /* then assign new node payload to all the rest, doing global checks */
+
+ FORALL_HASH(h,i,bp)
+ {
+ node_t gbn;
+ n=hash_bin2user(bp);
+ if((n->payload.flag==PAYLOAD_gnptr)||(n->payload.flag==PAYLOAD_parent)||(n->payload.flag==PAYLOAD_null))
+ ;
+ else assert(0);
+
+ gbn=find_hashtab(globals,n->str); /* i hope this search is efficient */
+ if(gbn!=NULL)
+ {
+ if(n->payload.flag!=PAYLOAD_parent)
+ n->payload.data=gbn->payload.data;
+ }
+ else
+ {
+ if(n->payload.flag!=PAYLOAD_parent)
+ {
+ char *flatname;
+ flatname=do_name(s,n->str);
+ n->payload.data.t=netlist_node(nl,flatname,(void *)n);
+ }
+ }
+ n->payload.flag=PAYLOAD_gnptr; /* set both types to gnptr */
+
+ }
+
+ /* now we have ptrs to every gn_t in this subckt reference, so we can process elements */
+
+ for(i=0;i<s->ckt->nc;i++) /* FOR EACH capacitor */
+ {
+ dev_input_t devinp;
+ devcap_t *dcp;
+ c_t *cp;
+ termptr_t np[2];
+ for(j=0;j<2;j++)
+ np[j]= s->ckt->c[i].nodes[j]->payload.data.t;
+ devinp.spice_cap=cp=&(s->ckt->c[i]);
+ dcp=list_data(&(nl->e[DEVT_CAP].l),netlist_newdev_fromnode(nl,DEVT_CAP,devinp,np));
+ dcp->v[DEVCAP_c]=lookup_params(s,&(cp->c),s->ckt->mult);
+ }
+
+ for(i=0;i<s->ckt->nm;i++) /* FOR EACH fet */
+ {
+ dev_input_t devinp;
+ termptr_t np[4];
+ m_t *cp;
+ devfet_t *dfp;
+ int spiceorder[4]={INDEX_SOURCE, INDEX_DRAIN, INDEX_GATE, INDEX_BULK };
+ int netlistorder[4]= {DEVFET_S, DEVFET_D, DEVFET_G, DEVFET_B };
+
+ for(j=0;j<4;j++)
+ np[netlistorder[j]]=s->ckt->m[i].nodes[spiceorder[j]]->payload.data.t;
+ devinp.spice_fet=cp=&(s->ckt->m[i]);
+ dfp=list_data(&(nl->e[DEVT_FET].l),netlist_newdev_fromnode(nl,DEVT_FET,devinp,np));
+
+ for(j=0;j<DEVFET_V;j++)
+ dfp->v[j]=eqn_const(0);
+
+ dfp->type=0;
+
+ if(cp->type=='p')
+ { dfp->type=DEVFET_pmos; }
+ else
+ if(cp->type=='n')
+ { dfp->type=DEVFET_nmos; }
+ else
+ assert(0);
+
+ D(30,do
+ {
+ static int mosfet_i=0;
+ Fprintf(stderr,"processing mosfet %i \n",++mosfet_i);
+ } while(0)
+ );
+
+ dfp->v[DEVFET_w] =lookup_params(s,&(cp->w),s->ckt->scale);
+ dfp->v[DEVFET_l] =lookup_params(s,&(cp->l),s->ckt->scale);
+ dfp->v[DEVFET_as]=lookup_params(s,&(cp->as),(s->ckt->scale)*(s->ckt->scale));
+ dfp->v[DEVFET_ad]=lookup_params(s,&(cp->ad),(s->ckt->scale)*(s->ckt->scale));
+ dfp->v[DEVFET_ps]=lookup_params(s,&(cp->ps),s->ckt->scale);
+ dfp->v[DEVFET_pd]=lookup_params(s,&(cp->pd),s->ckt->scale);
+ }
+
+ for(i=0;i<s->ckt->nx;i++) /* FOR EACH SUBCKT CALL */
+ {
+ x_t *xp;
+ xp=s->ckt->x+i;
+ for(j=0;j<xp->nl;j++)
+ if(xp->locals[j]!=NULL)
+ {
+ /* we copy the actual equation at use instantiation time
+ via lookup_parent...
+ */
+ }
+ }
+
+
+
+
+
+
+ return ; /* recurse on subckt calls */
+}
+
+
+
+
+static void free_ckt(subckt_t *ckt)
+{
+ int i;
+ hash_t *tab;
+ hashbin_t *bp;
+ node_t p;
+ subckt_t *tofree;
+
+ if(ckt==NULL)return;
+
+ tab=ckt->cktdir;
+ FORALL_HASH(tab,i,bp)
+ {
+ p=hash_bin2user(bp);
+ tofree=p->payload.data.subckt;
+ p->payload.data.subckt=NULL;
+ free_ckt(tofree);
+ }
+
+ for(i=0;i<ckt->nx;i++)
+ {
+ int j;
+
+ for(j=0;j<ckt->x[i].nl;j++)
+ if(ckt->x[i].locals[j]!=NULL)
+ free(ckt->x[i].locals[j]);
+
+ if(ckt->x[i].nodes!=NULL)
+ free(ckt->x[i].nodes); /* this frees locals also (combined allocation) */
+
+ /* note: equations have their own memory allocation system
+ so NEVER free an eqntoken_t *
+ */
+ }
+ hash_free(ckt->cktdir);
+ hash_free(ckt->nodes);
+ hash_free(ckt->params);
+ hash_free(ckt->lparams);
+ hash_free(ckt->global);
+
+ free(ckt);
+}
+
+
+void spice_count(netlist_t *nl)
+{
+ spice_t *sp=nl->input.spice;
+
+ spice_recurse_subckts(sp,sp->ckt,NULL,&count_stuff,(void *)nl);
+
+}
+
+
+void spice_build(netlist_t *nl)
+{
+ spice_t *sp=nl->input.spice;
+ netlist_eqn_begin(nl);
+ spice_recurse_subckts(sp,sp->ckt,NULL,&build_stuff,(void *)nl);
+ netlist_eqn_end(nl);
+}
+
+
+void spice_release(spice_t *sp)
+{
+ if(sp!=NULL)
+ {
+ free_ckt(sp->ckt);
+ eqn_mem_free(sp->eqn_mem);
+ free(sp);
+ }
+}
+
+spice_t *spice_new(scanner_t *scan)
+{
+ spice_t *p;
+ p=malloc(sizeof(spice_t));
+ assert(p!=NULL);
+ memset(p,0,sizeof(spice_t));
+ p->spice_magic=SPICE_MAGIC;
+ p->scan=scan;
+ p->eqn_mem=eqn_mem_new();
+ eqn_mem_push(p->eqn_mem);
+ scanner_sect_new(p->scan,scanner_def_spice(),spice_tokens);
+ scanner_parse_all(p->scan);
+ D(6,scanner_debug_all(p->scan,stderr));
+ p->deck=p->scan->sectp->dhead;
+ scanner_sect_release(p->scan);
+
+ if(p->deck!=NULL)
+ { p->ckt=new_ckt(p->deck,p->scan); }
+ else { p->ckt=NULL; }
+
+ if(eqn_mem_pop()!=p->eqn_mem)
+ assert(0);
+ return p;
+}
+
+
+
+
+
+void spice_debug(void * dbg_fp, spice_t *sp)
+{
+ FILE *dbg=dbg_fp;
+ fprintf(dbg,"debugging output for spice circuit file \n");
+
+ debug_subckts(dbg,sp->ckt, 0);
+}
+
diff --git a/spiceparser/netlist_spice.h b/spiceparser/netlist_spice.h
new file mode 100644
index 0000000..a988b23
--- /dev/null
+++ b/spiceparser/netlist_spice.h
@@ -0,0 +1,288 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* spice.h, header for spice parsing routines
+ Conrad Ziesler
+*/
+
+/* note: alot of this is imported from legacy/adb
+ so it has some historic baggage still
+*/
+
+#ifndef __NETLIST_SPICE_H__
+#define __NETLIST_SPICE_H__
+
+#ifndef __EQN_H__
+#include "eqn.h"
+#endif
+
+#ifndef __HASH_H__
+#include "hash.h"
+#endif
+
+#ifndef __SCANNER_H__
+#include "scanner.h"
+#endif
+
+
+/*******************************************************/
+/********* SPICE HASH TABLE CLIENTS ********************/
+
+#define PAYLOAD_null 0
+#define PAYLOAD_card_val 1
+#define PAYLOAD_parent 2
+#define PAYLOAD_gnptr 3
+#define PAYLOAD_subckt 4
+#define PAYLOAD_node 5
+
+
+/* HACK **/
+#ifndef __NETLIST_H__
+#define TERMPTR_BITS_DEVI 24
+#define TERMPTR_BITS_TERMI 3
+#define TERMPTR_BITS_DEVT 4
+
+typedef struct termptr_st
+{
+ unsigned devi: TERMPTR_BITS_DEVI;
+ unsigned nonnull: 1;
+ unsigned termi: TERMPTR_BITS_TERMI;
+ unsigned devt: TERMPTR_BITS_DEVT;
+}termptr_t;
+#endif
+
+union paydata_u
+{
+ void *p;
+ char *s;
+ struct subckt_st *subckt;
+ termptr_t t;
+};
+
+typedef struct hashload_st
+{
+ int flag;
+ union paydata_u data;
+}hashload_t;
+
+typedef struct nodeclient_st
+{
+ hashload_t payload;
+ unsigned char str[4]; /* alloc in place */
+}nodeclient_t;
+
+typedef struct nodeclient_st *node_t;
+
+#define FORALL_HASH(h,i,p) hash_forall(h,i,p)
+
+
+typedef struct paramload_st
+{
+ eqn_t eqn;
+ struct callparam_st *patch_call;
+ int global_i;
+}paramload_t;
+
+
+typedef struct paramclient_st
+{
+ paramload_t payload;
+ char str[4];
+}paramclient_t;
+
+typedef struct paramlookup_st
+{
+ struct stack_st *sp;
+ struct netlist_st *nl;
+}paramlookup_t;
+
+
+typedef struct callparam_st
+{
+ eqn_t eqn;
+ char str[4];
+}callparam_t;
+
+
+/*****************************************/
+/****** SPICE NETLIST READING *******/
+
+/***** scanner stuff *****/
+
+
+
+typedef enum keyword_et
+{
+ Kother, Kinclude, Ksubckt, Kends, Kend, Kendm, Kmodel, Kparam, Kglobal, Kmult, Kscale, Knull
+}keyword_t;
+
+#define SPICE_TOKENS { \
+ { Kinclude, ".include" }, \
+ { Ksubckt, ".subckt" }, \
+ { Kends, ".ends" }, \
+ { Kendm, ".endm" }, \
+ { Kmodel, ".model" }, \
+ { Kparam, ".param" }, \
+ { Kglobal, ".global" }, \
+ { Kmult, ".mult" }, \
+ { Kscale, ".scale" }, \
+ { Knull, NULL } \
+}
+
+extern tokenmap_t spice_tokens[];
+
+
+/****** pass 2 ************/
+
+struct subckt_st;
+
+typedef struct x_st
+{
+ int nn;
+ struct subckt_st *xp;
+ node_t *nodes;
+ callparam_t **locals;
+ int nl;
+ deck_t *deck;
+ card_t *rest;
+}x_t;
+
+#define INDEX_GATE 1
+#define INDEX_DRAIN 0
+#define INDEX_SOURCE 2
+#define INDEX_BULK 3
+
+typedef struct m_st
+{
+ node_t nodes[4];
+ eqn_t l,w,as,ad,ps,pd;
+ deck_t *deck;
+ card_t *rest;
+ uchar type;
+}m_t;
+
+typedef struct c_st
+{
+ node_t nodes[2];
+ eqn_t c;
+ deck_t *deck;
+ card_t *rest;
+}c_t;
+
+typedef struct r_st
+{
+ node_t nodes[2];
+ eqn_t r;
+ deck_t *deck;
+ card_t *rest;
+}r_t;
+
+typedef struct l_st
+{
+ node_t nodes[2];
+ eqn_t l;
+ deck_t *deck;
+ card_t *rest;
+}l_t;
+
+typedef struct v_st
+{
+ node_t nodes[2];
+ eqn_t v;
+ deck_t *deck;
+ card_t *rest;
+}v_t;
+
+typedef struct i_st
+{
+ node_t nodes[2];
+ eqn_t i;
+ deck_t *deck;
+ card_t *rest;
+}i_t;
+
+#define SUBCKT_MAGIC 0x43236513
+
+typedef struct subckt_st
+{
+ int subckt_magic;
+ struct subckt_st *parent; /* who are we descended from */
+ hash_t *nodes; /* table of nodes */
+ hash_t *params; /* table of parameters (those defined elsewhere) */
+ hash_t *lparams; /* table of local parameters (those on the .subckt line) */
+ hash_t *cktdir; /* table of locally defined subckts */
+ hash_t *global; /* table of locally defined globals */
+ uchar *name; /* our name */
+ int ndefn;
+ int nm;
+ int nc;
+ int nr;
+ int nl;
+ int nx;
+ int nv;
+ int ni;
+ node_t *defn; /* ptrs into table of [nodes] for definitions */
+ m_t *m; /* array of mosfets */
+ c_t *c; /* array of capacitors */
+ r_t *r; /* array of resistors */
+ l_t *l; /* array of inductors */
+ x_t *x; /* array of subcircuit calls */
+ v_t *v; /* array of voltage sources */
+ i_t *i; /* array of current sources */
+ int flag;
+ float scale,mult;
+}subckt_t;
+
+
+typedef struct stack_st
+{
+ int level;
+ struct stack_st *parent;
+ subckt_t *ckt;
+ x_t *call;
+ struct stack_st *top;
+ struct netlist_st *nl;
+ scanner_t *scan;
+}stack_t;
+
+typedef struct spice_st
+{
+ int spice_magic;
+ scanner_t *scan;
+ deck_t *deck;
+ subckt_t *ckt;
+ void *eqn_mem;
+}spice_t;
+
+
+
+#define minimum(a,b) (((a)<(b))?(a):(b))
+
+
+subckt_t *spice_find_subckt(subckt_t *parent, char *name);
+spice_t *spice_new(scanner_t *scan);
+void spice_release(spice_t *sp);
+void spice_debug(void * dbg_fp, spice_t *sp);
+list_t spice_list_subckt(subckt_t *parent);
+
+
+
+
+#endif /* __NETLIST_SPICE_H__*/
diff --git a/spiceparser/netlist_template.c b/spiceparser/netlist_template.c
new file mode 100644
index 0000000..7fdfc3f
--- /dev/null
+++ b/spiceparser/netlist_template.c
@@ -0,0 +1,55 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* netlist_template.c, code for building graph matching templates.
+ Conrad Ziesler
+*/
+
+/* primary goal:
+
+ We want to build a data structure which represents all library graphs merged into one,
+ in such a way that each merge keeps a list of library cells that were merged at that point.
+ With such a sturcture, we should be able to decompose a complex netlist into its component pieces.
+
+
+
+ Ref1-> cell (nfet_sd) (lib 1,2) -g>
+ -sd>
+
+ -> cell (pfet_g) (lib 3,5) -sd>
+ -sd>
+
+
+ netlist nodes are common and simple
+ netlist devices are complex, shared/merged keeping a list of the library cell associations.
+
+
+
+ to decompose a big netlist,
+ 1. initialize bitmap of library cell numbers
+ 2. start traversing depth first from some reference.
+ 2.1. keep track of traversal in template, eliminating at each step cells in the bitmap.
+ 2.2. keep track of devices and nodes traversed and matched with template in gate internal list.
+ 2.3. stop traversing at template boundaries.
+ 3. examine bitmap. if any remain, we have successful match.
+
+*/
+
+
diff --git a/spiceparser/scanner.c b/spiceparser/scanner.c
new file mode 100644
index 0000000..87ff6ff
--- /dev/null
+++ b/spiceparser/scanner.c
@@ -0,0 +1,780 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* scanner.c, support for scanning text, tokenifies input, uses file_readline
+ Conrad Ziesler
+*/
+
+
+/* goal: support cad tool file reading
+
+ cad tool requirements: large file size, regular file handling
+ needs to: minimize memory allocations, prevent memory leaks
+ should provide: allow higher up layers to never need to call strdup
+ unless they really want to. that is we alloc in place
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include "debug.h"
+
+#include "scanner.h"
+
+
+
+
+
+
+/**** standard error and warning reporting ************/
+
+static void parse_warn_error(int which, scanner_t *scan, char *fmt, va_list va)
+{
+
+ static char buf[4096];
+ card_t *c=scan->errcard;
+ deck_t *d=scan->errdeck;
+ char *bp=buf;
+ char *warnerr="WARNING";
+ int line=-1;
+ int file=-1;
+
+ if(d==NULL)
+ {
+ if (scan->inputp!=NULL)
+ {
+ line=scan->inputp->line;
+ file=scan->inputp->index;
+ }
+ }
+ else { line=d->line.line; file=d->line.fileindex; }
+
+ if(which) warnerr="ERROR";
+ bp[0]=0;
+
+ if(c!=NULL)
+ sprintf(bp,"line %i: %s: near %s : ",line,warnerr,c->str);
+ else sprintf(bp,"line %i: %s: :",line,warnerr);
+
+ if(d!=NULL)
+ for(c=d->card;c!=NULL;c=c->next)
+ {
+ bp+=strlen(bp);
+ if(bp>(buf+sizeof(buf)-256)) assert(0);
+ if(c->val!=NULL)sprintf(bp,"%s=%s ",c->str,c->val);
+ else sprintf(bp,"%s ",c->str);
+ }
+ bp+=strlen(bp);
+ sprintf(bp,"\n --> %s",fmt);
+ bp+=strlen(bp);
+ sprintf(bp,"\n");
+ bp+=strlen(bp);
+ if(which==0)
+ if(scan->warnfunc!=NULL)
+ { scan->warnfunc(scan,buf,va); return; }
+
+ if(scan->errfunc!=NULL)
+ scan->errfunc(scan,buf,va);
+}
+
+void parse_error (scanner_t *scan, char *fmt, ...)
+{
+ va_list va;
+ va_start(va,fmt);
+ parse_warn_error(1,scan,fmt,va);
+ va_end(va);
+}
+
+void parse_warn (scanner_t *scan, char *fmt, ...)
+{
+ va_list va;
+ va_start(va,fmt);
+ parse_warn_error(0,scan,fmt,va);
+ va_end(va);
+}
+
+void scanner_def_err(scanner_t *scan, char *fmt, va_list vp)
+{
+ vfprintf(stderr,fmt,vp);
+}
+
+
+
+/***** private helper functions *********/
+
+#ifdef NO_MEMORY
+static void free_cards(scanner_t *scan, card_t *c)
+{
+ card_t *tofree;
+ while(c!=NULL)
+ {
+ tofree=c;
+ c=c->next;
+ free(tofree);
+ }
+}
+
+
+static void deck_free(scanner_t *scan, deck_t *deck)
+{
+ deck_t *tofree;
+ while(deck!=NULL)
+ {
+ tofree=deck;
+ deck=deck->next;
+ free_cards(tofree->card);
+ free(tofree);
+ }
+}
+#endif
+
+
+static deck_t *new_deck(scanner_t *scan)
+{
+ deck_t *d;
+ d=memory_alloc(&(scan->strmem),sizeof(deck_t));
+ assert(d!=NULL);
+ d->next=NULL;
+ d->card=NULL;
+ d->line=scanner_current_file_line(scan);
+ return d;
+}
+
+
+void scanner_add_tokens(scanner_t *scan, tokenmap_t *map)
+{
+ int i;
+ if(scan->sectp==NULL)assert(0);
+ else
+ {
+ for(i=0;map[i].str!=NULL;i++)
+ names_add(scan->sectp->tokenizer,map[i].token,map[i].str);
+ }
+}
+
+void scanner_reset_tokens(scanner_t *scan)
+{
+ if(scan->sectp!=NULL)
+ {
+ names_free(scan->sectp->tokenizer);
+ scan->sectp->tokenizer=names_new();
+ }
+ else assert(0);
+}
+
+
+#ifdef OLD_WAY
+void scanner_input_new(scanner_t *scan, file_spec_p file)
+{
+ scanner_input_t *p;
+ p=malloc(sizeof(scanner_input_t));
+ if(p!=NULL)memset(p,0,sizeof(scanner_input_t));
+ else assert(0);
+ p->file=file;
+ file_openread(file);
+ p->line=0;
+ if(scan->allinputs==NULL)
+ p->index=0;
+ else
+ p->index=scan->allinputs->index+1;
+ p->next=scan->allinputs;
+ scan->allinputs=p;
+ p->back=scan->inputp;
+ scan->inputp=p;
+}
+#endif
+
+
+
+void scanner_input_newfp(scanner_t *scan, void *fp)
+{
+ scanner_input_t *p;
+ p=malloc(sizeof(scanner_input_t));
+ if(p!=NULL)memset(p,0,sizeof(scanner_input_t));
+ else assert(0);
+ p->file_fp=fp;
+ p->line=0;
+ if(scan->allinputs==NULL)
+ p->index=0;
+ else
+ p->index=scan->allinputs->index+1;
+ p->next=scan->allinputs;
+ scan->allinputs=p;
+ p->back=scan->inputp;
+ scan->inputp=p;
+}
+
+
+void scanner_sect_new(scanner_t *scan, scanner_def_t *defs, tokenmap_t *map)
+{
+ scanner_sect_t *sect;
+
+ sect=malloc(sizeof(scanner_sect_t));
+ if(sect!=NULL)memset(sect,0,sizeof(scanner_sect_t));
+ else assert(0);
+
+ sect->tokenizer=names_new();
+ sect->def=defs;
+ sect->cp=NULL;
+ sect->dp=NULL;
+ sect->dhead=NULL;
+ sect->eolstring=0;
+ sect->line_cont=0;
+ sect->lbuf[0]=0;
+ sect->eoline[0]=0;
+ sect->back=scan->sectp;
+ scan->sectp=sect;
+ scanner_add_tokens(scan,map);
+}
+
+
+void scanner_input_release(scanner_t *scan) /* release top of stack */
+{
+ scanner_input_t *p;
+ if((p=scan->inputp)!=NULL)
+ {
+ scan->inputp=scan->inputp->back;
+ /* we don't free, we keep on list,
+ for error reporting
+ */
+ }
+}
+
+void scanner_sect_release(scanner_t *scan) /* release top of stack */
+{
+ scanner_sect_t *p;
+
+ if((p=scan->sectp)!=NULL)
+ {
+ scan->sectp=scan->sectp->back;
+ names_free(p->tokenizer);
+ free(p);
+ }
+}
+
+void scanner_init(scanner_t *scan)
+{
+ memory_init(&(scan->strmem));
+ scan->sectp=NULL;
+ scan->allinputs=NULL;
+ scan->inputp=NULL;
+ scan->errdeck=NULL;
+ scan->errcard=NULL;
+ scan->errfunc=scanner_def_err;
+ scan->warnfunc=scanner_def_err;
+}
+
+
+void scanner_free_all(scanner_t *scan)
+{
+ memory_freeall(&(scan->strmem));
+}
+
+void scanner_release(scanner_t *scan)
+{
+ scanner_input_t *p,*np;
+
+ while(scan->sectp!=NULL)
+ scanner_sect_release(scan);
+
+ while(scan->inputp!=NULL)
+ scanner_input_release(scan);
+
+ for(p=scan->allinputs;p!=NULL;p=np)
+ {
+ np=p->next;
+ if(p->file_fp!=NULL) fclose(p->file_fp);
+ free(p);
+ }
+
+ scanner_free_all(scan);
+}
+
+
+
+
+int scanner_checkvalid(deck_t *d, int qty)
+{
+ int i;
+ card_t *c;
+ if(d==NULL)return 0;
+ for(i=0,c=d->card;c!=NULL;c=c->next,i++)
+ { if(i>=qty)break; }
+
+ if(i>=qty)return 1;
+ return 0;
+}
+
+
+
+
+
+
+
+
+/***** the actual scanner routines *****/
+
+
+static char *skip_stuff(char *toskip, char *str, int sense)
+{
+ char *cp;
+ char *ws;
+ for(cp=str;cp[0]!=0;cp++)
+ {
+ for(ws=toskip;ws[0]!=0;ws++)
+ if(ws[0]==cp[0]) break;
+ if( (ws[0]==0) && (sense==0) ) break; /* no toskip char found */
+ if( (ws[0]!=0) && (sense!=0) ) break; /* toskip char found */
+ }
+ return cp;
+}
+
+static void skip_space(scanner_t *scan, char **p)
+{ *p=skip_stuff(scan->sectp->def->whitespace,*p,0); }
+
+#if 0
+static void skip_nonspace(scanner_t *scan, char **p)
+{ *p=skip_stuff(scan->sectp->def->whitespace,*p,1); }
+#endif
+
+static void skip_nonspace_quote(scanner_t *scan, char **p)
+{
+ scanner_def_t *def=scan->sectp->def;
+ int quote=0;
+ char *cp;
+ char *ws;
+ cp=*p;
+ /* this is set to 2 origninally since first iteration hits same character */
+ if(cp[0]==def->quote_char)quote=2;
+ for(;cp[0]!=0;cp++)
+ {
+ if(cp[0]==def->quote_char){ quote--; if(quote==0){ if(cp[0]!=0)cp++; break; } }
+ if(quote<=0)
+ {
+ for(ws=def->whitespace;ws[0]!=0;ws++)
+ if(ws[0]==cp[0]) break;
+ if( (ws[0]!=0) ) break; /* whitespace char found */
+ }
+
+ }
+ *p=cp;
+}
+
+
+static int astreq(char *s, char *lng)
+{
+ if(s[0]==0)return 2;
+ while(s[0]!=0)
+ {
+ if(lng[0]==0)return -1;
+ if(s[0]!=lng[0])return 1;
+ s++;
+ lng++;
+ }
+ return 0;
+}
+
+
+static card_t *make_card(scanner_t *scan, char *p1, char *p2, char *p3, char *p4)
+{
+ scanner_def_t *def=scan->sectp->def;
+ card_t *c;
+ int l1=0,l2=0,lc;
+ int i;
+
+ if( (p1!=NULL) && (p2!=NULL)) l1=p2-p1;
+ if( (p3!=NULL) && (p4!=NULL)) l2=p4-p3;
+
+ assert(l1>=0);
+ assert(l2>=0);
+ lc=strlen(def->eol_continue);
+
+ if(p1[0]==0) return NULL; /* nothing here */
+
+ if(lc <= l1)
+ if(!astreq(def->eol_continue,p2-lc))
+ {
+ if(lc < l1 )
+ {
+ memcpy(scan->sectp->eoline,p1,l1-lc);
+ scan->sectp->eoline[l1]=def->assignment;
+ scan->sectp->eoline[l1+1]=0;
+ scan->sectp->eolstring=1;
+ }
+ return NULL;
+ }
+
+ if(p3!=NULL)
+ {
+ if((p3[0]==0)||(!astreq(def->eol_continue,p3)))
+ {
+ memcpy(scan->sectp->eoline,p1,l1);
+ scan->sectp->eoline[l1]=def->assignment;
+ scan->sectp->eoline[l1+1]=0;
+ scan->sectp->eolstring=1;
+ return NULL;
+ }
+ }
+
+ c=memory_alloc(&(scan->strmem),sizeof(card_t)+l1+l2+2);
+ assert(c!=NULL);
+ c->next=NULL;
+ c->token=0;
+ c->str[0]=0;
+ c->val=NULL;
+
+ memcpy(c->str,p1,l1);
+ c->str[l1]=0;
+ if(l2!=0)
+ {
+ memcpy(c->str+l1+1,p3,l2);
+ c->str[l1+1+l2]=0;
+ c->val=c->str+l1+1;
+ }
+
+ if(def->convert_case==PARSE_CASE_TOLOWER)
+ for(i=0;i<(l1+l2+2);i++)
+ c->str[i]=tolower(c->str[i]);
+ else if(def->convert_case==PARSE_CASE_TOUPPER)
+ for(i=0;i<(l1+l2+2);i++)
+ c->str[i]=toupper(c->str[i]);
+
+
+ if((def->tokenize[0]==0) || (!astreq(def->tokenize,c->str)))
+ c->token=names_check(scan->sectp->tokenizer,c->str);
+
+ if(c->val!=NULL)
+ if(c->val[0]==scan->sectp->def->quote_char)c->val++;
+
+ return c;
+}
+
+
+
+
+
+int scanner_parse_line(scanner_t *scan)
+{
+ scanner_def_t *def=scan->sectp->def;
+ char *line=scan->sectp->lbuf;
+ char *lp, *tmp;
+ char *p1=NULL,*p2,*p3,*p4,*p5,*p6;
+ card_t *ncp=NULL;
+ int dbg=0;
+
+ if(scan->inputp==NULL)return 0;
+ if(scan->inputp->file_fp!=NULL) { if(feof(((FILE *)scan->inputp->file_fp)))return 0; }
+ /* return 0; else { if(file_eof(scan->inputp->file)) return 0; } */
+
+ line[0]=0;
+ line[1]=0;
+ line[sizeof(scan->sectp->lbuf)-1]=0;
+ if(scan->inputp->file_fp!=NULL)
+ fgets(line,sizeof(scan->sectp->lbuf)-2,scan->inputp->file_fp);
+ else
+ ; /* file_readline(scan->inputp->file,sizeof(scan->sectp->lbuf)-2,line); */
+
+ scan->inputp->line++;
+ if(line[0]==0)return 3;
+
+ /* read one line */
+ if(dbg)fprintf(stderr,"line: %s",line);
+ lp=line;
+
+ skip_space(scan,&lp);
+
+ if(lp[0]==0) return 4;
+
+ if(!astreq(def->commentstart, lp))return 5;
+ if(!astreq(def->line_stop, lp)) return 0; /* stop scanning */
+ if(!astreq(def->bol_continue,lp)) /* continue line */
+ { scan->sectp->line_cont=1; lp+=strlen(def->bol_continue); }
+
+ if(dbg)fprintf(stderr,"lp: %s",lp);
+ if(dbg)
+ {
+ int l=strlen(lp);
+ if(lp[l-1]=='\n')lp[l-1]=0;
+ }
+
+ if(! (scan->sectp->line_cont||scan->sectp->eolstring)) /* make a new deck unless we are continuing */
+ {
+ deck_t *dp;
+ dp=new_deck(scan);
+ if(scan->sectp->dhead==NULL)
+ { scan->sectp->dhead=scan->sectp->dp=dp; }
+ else
+ { scan->sectp->dp->next=dp; scan->sectp->dp=dp; }
+ }
+ scan->sectp->line_cont=0;
+
+ /* continue last string if necessary */
+ if(scan->sectp->eolstring)
+ {
+ p1=scan->sectp->eoline;
+ skip_space(scan,&p1);
+ p2=p1;
+ skip_nonspace_quote(scan,&p2);
+ p3=p2;
+ skip_space(scan,&p3);
+ p4=p3;
+ skip_nonspace_quote(scan,&p4);
+ p5=p4;
+ skip_space(scan,&p5);
+ p6=p5;
+ skip_nonspace_quote(scan,&p6);
+
+ if(p5[0]==0)p5=NULL;
+ if(p3[0]==0)p3=NULL;
+ if(p1[0]==0)p1=NULL;
+ scan->sectp->eolstring=0;
+ }
+
+ while((lp[0]!=0)||(p1!=NULL))
+ {
+ int arg=0;
+
+ if(p1==NULL)
+ {
+ p1=lp;
+ skip_space(scan,&p1);
+ p2=p1;
+ skip_nonspace_quote(scan,&p2);
+ p3=p2;
+ skip_space(scan,&p3);
+ p4=p3;
+ skip_nonspace_quote(scan,&p4);
+ p5=p4;
+ skip_space(scan,&p5);
+ p6=p5;
+ skip_nonspace_quote(scan,&p6);
+ }
+ else if(p3==NULL)
+ {
+ p3=lp;
+ skip_space(scan,&p3);
+ p4=p3;
+ skip_nonspace_quote(scan,&p4);
+ p5=p4;
+ skip_space(scan,&p5);
+ p6=p5;
+ skip_nonspace_quote(scan,&p6);
+ }
+
+ else if(p5==NULL)
+ {
+ p5=lp;
+ skip_space(scan,&p5);
+ p6=p5;
+ skip_nonspace_quote(scan,&p6);
+ }
+
+ if(dbg)
+ fprintf(stderr,"doing line: line is [%s]\nlp=[%s]\np1=[%s]\np2=[%s]\np3=[%s]\np4=[%s]\np5=[%s]\np6=[%s]\n\n",
+ line,lp,p1,p2,p3,p4,p5,p6);
+
+
+
+ /* cases:
+ {p1}{p2}{p3}[ ]{p4}{p5}{p6} -> end of line
+ {p1}text{p2}[ ]{p3}{p4}{p5}{p6} -> word end of line
+ {p1}text=moretext{p2}... -> one word embedded assignment
+ {p1}text={p2}{p3}{p4}{p5}{p6} -> word assignment spills over line
+ {p1}={p2} .. -> continue assignment from prev line if possible
+ {p1}text={p2} {p3}text{p4} -> word assign 1
+ {p1}text{p2} {p3}=text{p4} -> word assign 2
+ {p1}text{p2} {p3}={p4} {p5}text{p6} -> word assign 3
+ {p1}text{p2} {p3}text={p4} -> word
+ text = EOL {p1}text{p2} .. -> eol continue
+ */
+
+ if(p1==p2){ p1=NULL; break; } /* end of line */
+
+ if(p2>p1)
+ { if(p2[-1]==def->assignment)arg=1; }
+
+ if((arg==0)&&(p2>p1))
+
+ {
+ if( (tmp=memchr(p1,def->assignment,p2-p1))!=NULL)
+ {
+ arg=5;
+ p2=tmp+1;
+ p3=tmp+1;
+ p4=p3;
+ skip_nonspace_quote(scan,&p4);
+ }
+ }
+
+ if(arg==0)
+ {
+ if(p3[0]==def->assignment)
+ arg=2;
+ }
+
+
+
+ switch(arg)
+ {
+ case 0: /* no arg */
+ ncp=make_card(scan,p1,p2,NULL,NULL);
+ p1=p3; p2=p4; p3=p5; p4=p6; p5=NULL; lp=p6;
+ break;
+ case 1: /* arg in p3 */
+ ncp=make_card(scan,p1,p2-1,p3,p4);
+ p1=p5; p2=p6; p3=NULL; p5=NULL; lp=p6;
+ break;
+ case 2: /* arg in p3 or p4 */
+ if((p3+1)<p4)
+ {
+ ncp=make_card(scan,p1,p2,p3+1,p4);
+ p1=p5; p2=p6; p3=NULL; p5=NULL; lp=p6;
+ }
+ else
+ {
+ ncp=make_card(scan,p1,p2,p5,p6);
+ p1=NULL; p3=NULL; p5=NULL; lp=p6;
+ }
+ break;
+ case 5: /* embedded arg, we've fixed up p's */
+ ncp=make_card(scan,p1,p2-1,p3,p4);
+ p1=NULL; p3=NULL; p5=NULL; lp=p4;
+ break;
+ default: assert(0);
+ }
+
+ if(ncp!=NULL)
+ {
+ if(dbg)fprintf(stderr,"Adding card %s %i %s\n",ncp->str,ncp->token,ncp->val);
+ if(scan->sectp->dp==NULL)assert(0);
+
+ if(scan->sectp->dp->card==NULL)
+ scan->sectp->dp->card=scan->sectp->cp=ncp;
+ else
+ {
+ if(scan->sectp->cp!=NULL)
+ {
+ scan->sectp->cp->next=ncp;
+ scan->sectp->cp=scan->sectp->cp->next;
+ }
+ else assert(0);
+ }
+ }
+ else
+ {
+ if(dbg)fprintf(stderr,"card is null, line is [%s]\nlp=[%s]\np1=[%s]\np2=[%s]\np3=[%s]\np4=[%s]\np5=[%s]\np6=[%s]\n\n",
+ line,lp,p1,p2,p3,p4,p5,p6);
+
+
+ }
+ }
+
+ return 6;
+}
+
+
+
+
+
+int scanner_parse_all(scanner_t *scan)
+{
+ scan->sectp->eolstring=0;
+ scan->sectp->line_cont=0;
+ while(scanner_parse_line(scan));
+ return 0;
+}
+
+
+scanner_def_t *scanner_def_spice(void)
+{
+ static scanner_def_t spicedef;
+ strcpy(spicedef.line_stop,".end_spice");
+ strcpy(spicedef.eol_continue,"\\");
+ strcpy(spicedef.bol_continue,"+");
+ spicedef.convert_case=PARSE_CASE_TOLOWER;
+ spicedef.quote_char='\'';
+ spicedef.newline='\n';
+ spicedef.assignment='=';
+ strcpy(spicedef.tokenize,".");
+ strcpy(spicedef.whitespace," \t\n\r");
+ strcpy(spicedef.commentstart,"*");
+ return &spicedef;
+}
+
+char *scanner_token(scanner_t *scan, int token)
+{
+ return names_lookup(scan->sectp->tokenizer,token);
+}
+
+file_line_t scanner_current_file_line(scanner_t *scan)
+{
+ file_line_t l;
+ l.fileindex=scan->inputp->index;
+ l.line=scan->inputp->line;
+ return l;
+}
+
+void scanner_debug_all(scanner_t *scan, void *dbg)
+{
+ FILE *fp=dbg;
+ int q;
+ deck_t *d;
+ card_t *c;
+
+ fprintf(fp,"\n\n** begin \n\n");
+ for(d=scan->sectp->dhead;d!=NULL;d=d->next)
+ {
+ q=0;
+ fprintf(fp,"\nline %i: ",d->line.line);
+ for(c=d->card;c!=NULL;c=c->next)
+ {
+ if(c->token>0)
+ fprintf(fp," **%i=%s** ",c->token,scanner_token(scan,c->token));
+
+ if(c->val==NULL)
+ fprintf(fp," [%s] ",c->str);
+ else fprintf(fp," [%s]=[%s] ",c->str,c->val);
+ q++;
+ if(q>=6){ fprintf(fp,"\n "); q=1; }
+ }
+ }
+
+ fprintf(fp,"\n\n** .end\n\n");
+}
+
+/* parses 0101.0101.0101011.01 */
+unsigned parse_binary(char **str)
+{
+ unsigned result=0;
+ char *p;
+ for(p=*str;p[0]!=0;p++)
+ {
+ if(p[0]=='0')
+ result<<=1;
+
+ else if(p[0]=='1')
+ { result<<=1; result|=1; }
+
+ else if(p[0]=='.');
+ else break;
+ }
+ *str=p;
+ return result;
+}
diff --git a/spiceparser/scanner.h b/spiceparser/scanner.h
new file mode 100644
index 0000000..576b8b1
--- /dev/null
+++ b/spiceparser/scanner.h
@@ -0,0 +1,163 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* scanner.h, header for scanner routines
+ Conrad Ziesler
+*/
+
+#include <stdarg.h>
+
+#ifndef __SCANNER_H__
+#define __SCANNER_H__
+
+
+#ifndef __MEMORY_H__
+#include "memory.h"
+#endif
+
+#ifndef __NAMES_H__
+#include "names.h"
+#endif
+
+/* we provide a consistent way for tools to read large text files
+ of various line oriented formats
+
+ in addition, we manage memory, so freeing these structures is simple
+*/
+typedef struct file_line_st
+{
+ unsigned int fileindex:8;
+ unsigned int line:24;
+}file_line_t;
+
+typedef struct tokenmap_st
+{
+ int token;
+ char *str;
+}tokenmap_t;
+
+
+typedef struct card_st
+{
+ struct card_st *next;
+ int token;
+ char *val;
+ char str[4];
+}card_t;
+
+typedef struct deck_st
+{
+ struct deck_st *next;
+ card_t *card;
+ file_line_t line;
+}deck_t;
+
+
+
+typedef struct scanner_def_st
+{
+ char line_stop[32]; /* stop scanning when we hit this line */
+ char eol_continue[8]; /* continue line if this is detected at the end */
+ char bol_continue[8]; /* continue line if this is detected at beggining */
+ int convert_case; /* convert everything to a case ? */
+ char quote_char; /* what to use as value quote */
+ char newline; /* what to use as new line character */
+ char assignment; /* what to use as assignment '=' delimiter */
+ char tokenize[8]; /* prefix for all tokens of interest */
+ char whitespace[32]; /* ignore all of this */
+ char commentstart[8]; /* this starts a comment */
+}scanner_def_t;
+
+typedef struct scanner_sect_st
+{
+ struct scanner_sect_st *back;
+ names_t *tokenizer; /* we use this as our hasher */
+ scanner_def_t *def; /* we get our defaults from here */
+
+ card_t *cp;
+ deck_t *dp,*dhead;
+ int eolstring; /* got = [space] EOLINE */
+ char lbuf[512]; /* line buffer */
+ char eoline[512]; /* continue buffer */
+ int line_cont;
+}scanner_sect_t;
+
+typedef struct scanner_input_st
+{
+ struct scanner_input_st *back, *next; /* list of all inputs*/
+ void *file_fp; /* FILE * */
+ int line;
+ int index;
+}scanner_input_t;
+
+typedef struct scanner_st
+{
+ memory_t strmem; /* where we allocate our strings */
+ scanner_input_t *inputp; /* current input stack, for #include files */
+ scanner_input_t *allinputs; /* list of all inputs */
+ scanner_sect_t *sectp; /* section stack, who is parsing this */
+ /****** error processing ****/
+ deck_t *errdeck;
+ card_t *errcard;
+ void (*errfunc)(struct scanner_st *sp, char *format, va_list vp);
+ void (*warnfunc)(struct scanner_st *sp, char *format, va_list vp);
+}scanner_t;
+
+#define PARSE_CASE_TOLOWER 1
+#define PARSE_CASE_TOUPPER 2
+#define PARSE_NOCASECVT 0
+
+
+/**** initialization and release ******/
+void scanner_add_tokens(scanner_t *scan, tokenmap_t *map);
+void scanner_reset_tokens(scanner_t *scan);
+
+void scanner_init(scanner_t *scan); /* init all structures */
+void scanner_release(scanner_t *scan); /* free all associated structures */
+
+void scanner_input_newfp(scanner_t *scan, void *fp);
+void scanner_sect_new(scanner_t *scan, scanner_def_t *defs, tokenmap_t *map);
+void scanner_input_release(scanner_t *scan); /* release top of stack */
+void scanner_sect_release(scanner_t *scan); /* release top of stack */
+
+/* some standardized scanner defaults */
+scanner_def_t *scanner_def_spice(void);
+void scanner_def_err(scanner_t *scan, char *fmt, va_list vp);
+
+/* the scanner functions, file section oriented
+ keeps allocating memory, so you get roughly the file size + about 25% overhead
+ of memory usage. free_all dumps it all quickly, though.
+*/
+
+int scanner_parse_all(scanner_t *scan);
+void scanner_free_all(scanner_t *scan); /* free all string (&card/&deck) memory */
+int scanner_parse_line(scanner_t *scan);
+unsigned parse_binary(char **str);
+
+/* misc. */
+
+void parse_error (scanner_t *scan, char *fmt, ...);
+void parse_warn (scanner_t *scan, char *fmt, ...);
+int scanner_checkvalid(deck_t *d, int qty);
+void scanner_debug_all(scanner_t *scan, void *dbg);
+file_line_t scanner_current_file_line(scanner_t *scan);
+
+
+#endif
diff --git a/spiceparser/sort.c b/spiceparser/sort.c
new file mode 100644
index 0000000..d76374e
--- /dev/null
+++ b/spiceparser/sort.c
@@ -0,0 +1,482 @@
+/********************
+ This file is part of the software library CADLIB written by Conrad Ziesler
+ Copyright 2003, Conrad Ziesler, all rights reserved.
+
+*************************
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************/
+/* sort.c, sorting routines
+ Conrad Ziesler
+
+ this code is adapted from gnu glibc qsort.c, and so their header is as follows:
+ reason: stdlib sort interface does not allow for indirection in cmp without using hackish global
+ variables. also, we rely heavily on list already, so this makes the interface cleaner
+*/
+
+
+
+/* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+
+#include "debug.h"
+
+#include "list.h"
+#include "list_search.h"
+
+
+/* Byte-wise swap two items of size SIZE. */
+#define SWAP(a, b, size) \
+ do \
+ { \
+ register size_t __size = (size); \
+ register char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
+ } while (0)
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+ This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+/* Stack node declarations used to store unfulfilled partition obligations. */
+typedef struct
+ {
+ char *lo;
+ char *hi;
+ } stack_node;
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+#define STACK_SIZE (8 * sizeof(unsigned long int))
+#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+#define STACK_NOT_EMPTY (stack < top)
+
+
+/* Order size using quicksort. This implementation incorporates
+ four optimizations discussed in Sedgewick:
+
+ 1. Non-recursive, using an explicit stack of pointer that store the
+ next array partition to sort. To save time, this maximum amount
+ of space required to store an array of MAX_INT is allocated on the
+ stack. Assuming a 32-bit integer, this needs only 32 *
+ sizeof(stack_node) == 136 bits. Pretty cheap, actually.
+
+ 2. Chose the pivot element using a median-of-three decision tree.
+ This reduces the probability of selecting a bad pivot value and
+ eliminates certain extraneous comparisons.
+
+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+ insertion sort to order the MAX_THRESH items within each partition.
+ This is a big win, since insertion sort is faster for small, mostly
+ sorted array segments.
+
+ 4. The larger of the two sub-partitions is always pushed onto the
+ stack first, with the algorithm then concentrating on the
+ smaller partition. This *guarantees* no more than log (n)
+ stack size is needed (actually O(1) in this case)! */
+
+
+#define CMP(a,b) (sf->cmpf(sf,a,b))
+
+
+void list_qsort (sort_func_t *sf)
+{
+ size_t total_elems=sf->tosort->q;
+ size_t size=sf->tosort->s;
+ void *const pbase=sf->tosort->d;
+ register char *base_ptr = (char *) pbase;
+
+ /* Allocating SIZE bytes for a pivot buffer facilitates a better
+ algorithm below since we can do comparisons directly on the pivot. */
+ char *pivot_buffer = (char *) malloc (size);
+ const size_t max_thresh = MAX_THRESH * size;
+ sf->aiskey=0;
+ assert(pivot_buffer!=NULL);
+ memset(pivot_buffer,0,size);
+
+ if (total_elems == 0)
+ /* Avoid lossage with unsigned arithmetic below. */
+ { free(pivot_buffer); return; }
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ /* Largest size needed for 32-bit int!!! */
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack + 1;
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ char *pivot = pivot_buffer;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ if (CMP ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ if (CMP ((void *) hi, (void *) mid) < 0)
+ SWAP (mid, hi, size);
+ else
+ goto jump_over;
+ if (CMP ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ jump_over:;
+ memcpy (pivot, mid, size);
+ pivot = pivot_buffer;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while (CMP ((void *) left_ptr, (void *) pivot) < 0)
+ left_ptr += size;
+
+ while (CMP ((void *) pivot, (void *) right_ptr) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAP (left_ptr, right_ptr, size);
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP (lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH (lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH (left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+ {
+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ register char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if (CMP ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAP (tmp_ptr, base_ptr, size);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while (CMP ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+ { free(pivot_buffer); return; }
+}
+
+
+
+
+
+
+
+
+
+/**** support for search list bindings. we copy and modify the qsort
+ to reduce overhead of extra bindings -- conrad
+***/
+
+
+
+/* swap optimized for integers */
+#define SWAPINT(a, b) \
+ do \
+ { \
+ register int *__a = (void *)(a), *__b = (void *)(b), __tmp; \
+ __tmp=*__a; *__a=*__b; *__a=__tmp; \
+ } while (0)
+
+
+#define CMPIND(a,b) (psp_cmpf( psp->user, source_d+(source_s*(*((int*)a))), source_d+(source_s*(*((int*)b)))))
+#define size (sizeof(int))
+
+void list_search_qsort (list_search_t *lsp, list_psearch_t *psp)
+{
+ char *source_d;
+ int source_s;
+ int (*psp_cmpf)(const void *user ,const void *a, const void *b);
+ size_t total_elems=lsp->list.q;
+
+ void *const pbase=psp->isearchdata;
+ register char *base_ptr;
+ int pivot_buffer_el=0;
+ char *pivot_buffer = (char *) &pivot_buffer_el;
+ const size_t max_thresh = MAX_THRESH * size;
+
+ base_ptr= (char *) pbase;
+ /* copy out of pointers to stack variables so compile can do memory scheduling */
+ source_d=lsp->list.d;
+ source_s=lsp->list.s;
+ psp_cmpf=psp->cmpf;
+
+ if (total_elems == 0) return;
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ /* Largest size needed for 32-bit int!!! */
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack + 1;
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ char *pivot = pivot_buffer;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ assert(hi>=lo);
+
+ if (CMPIND ((void *) mid, (void *) lo) < 0)
+ SWAPINT (mid, lo);
+ if (CMPIND ((void *) hi, (void *) mid) < 0)
+ SWAPINT (mid, hi);
+ else
+ goto jump_over;
+ if (CMPIND ((void *) mid, (void *) lo) < 0)
+ SWAPINT (mid, lo);
+ jump_over:;
+ (*((int*)pivot)) = (*((int*)mid));
+ pivot = pivot_buffer;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while (CMPIND ((void *) left_ptr, (void *) pivot) < 0)
+ left_ptr += size;
+
+ while (CMPIND ((void *) pivot, (void *) right_ptr) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAPINT (left_ptr, right_ptr);
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP (lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH (lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH (left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+ {
+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ register char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if (CMPIND ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAPINT (tmp_ptr, base_ptr);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while (CMPIND ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+ { return; }
+}
diff --git a/spiceparser/test.lib b/spiceparser/test.lib
new file mode 100644
index 0000000..37ca20a
--- /dev/null
+++ b/spiceparser/test.lib
@@ -0,0 +1,1760 @@
+
+** and2m05p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m05p.iclib2,v 9.0.1.6 2002/07/18 14:38:53 rchiang Exp $
+
+.SUBCKT AND2M05P Z A B VDD VSS
+
+* devices:
+m0 8 11 7 VDD pm_hp l=0.118744u w=0.926776u ad=0.156347p as=0.697362p
++ pd=0.348111u ps=3.88u
+m1 9 12 8 VDD pm_hp l=0.118237u w=0.910208u ad=0.35608p as=0.153552p pd=1.43203u
++ ps=0.341888u
+m2 10 13 9 VDD pm_hp l=0.117864u w=1.02521u ad=0.331912p as=0.401069p pd=1.685u
++ ps=1.61296u
+m3 3 11 2 VSS nm_hp l=0.115u w=0.595u ad=0.0820299p as=0.23205p pd=0.275106u
++ ps=1.375u
+m4 4 12 3 VSS nm_hp l=0.119905u w=0.605355u ad=0.292388p as=0.0834575p
++ pd=1.40001u ps=0.279894u
+m5 5 13 4 VSS nm_hp l=0.120619u w=0.670208u ad=0.223637p as=0.323712p pd=1.33u
++ ps=1.54999u
+
+* resistors:
+r6 37 2 40 $[mnc]
+r7 VSS 4 40 $[mnc]
+r8 VSS 4 40 $[mnc]
+r9 Z 5 40 $[mnc]
+r10 VDD 7 40 $[mpc]
+r11 VDD 7 40 $[mpc]
+r12 37 8 40 $[mpc]
+r13 VDD 9 40 $[mpc]
+r14 VDD 9 40 $[mpc]
+r15 Z 10 40 $[mpc]
+r16 A 11 14 $[mpolyc]
+r17 B 12 14 $[mpolyc]
+r18 37 13 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.351161f
+cp2 2 VSS 0.0283066f
+cp3 4 VSS 0.0523448f
+cp4 5 VSS 0.0320563f
+cp5 7 VSS 0.0721056f
+cp6 8 VSS 0.0290149f
+cp7 9 VSS 0.0753449f
+cp8 10 VSS 0.0239399f
+cp9 11 VSS 0.376099f
+cp10 12 VSS 0.458626f
+cp11 13 VSS 0.339844f
+cp12 37 VSS 0.428433f
+cp13 A VSS 0.144954f
+cp14 B VSS 0.118711f
+cp15 Z VSS 0.196733f
+
+.ENDS
+
+
+** and2m10p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m10p.iclib2,v 9.0.1.5 2002/06/20 18:41:49 kensz Exp $
+
+.SUBCKT AND2M10P Z A B VDD VSS
+
+* devices:
+m0 21 37 20 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.701075p pd=0.385u
++ ps=2.615u
+m1 22 37 21 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p pd=0.385u
++ ps=0.385u
+m2 23 37 22 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p pd=0.385u
++ ps=0.385u
+m3 24 37 23 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p pd=0.385u
++ ps=0.385u
+m4 25 37 24 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p pd=0.385u
++ ps=0.385u
+m5 26 37 25 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p pd=0.385u
++ ps=0.385u
+m6 27 37 26 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p pd=0.385u
++ ps=0.385u
+m7 28 37 27 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p pd=0.385u
++ ps=0.385u
+m8 29 37 28 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p pd=0.385u
++ ps=0.385u
+m9 30 37 29 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p pd=0.385u
++ ps=0.385u
+m10 31 38 30 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p
++ pd=0.385u ps=0.385u
+m11 32 39 31 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p
++ pd=0.385u ps=0.385u
+m12 33 39 32 VDD pm_hp l=0.116519u w=1.95228u ad=0.332862p as=0.399462p
++ pd=0.385u ps=0.385u
+m13 34 40 33 VDD pm_hp l=0.116519u w=1.95228u ad=0.399462p as=0.332862p
++ pd=0.385u ps=0.385u
+m14 35 40 34 VDD pm_hp l=0.116519u w=1.95228u ad=0.428612p as=0.399462p
++ pd=0.485u ps=0.385u
+m15 36 41 35 VDD pm_hp l=0.116519u w=1.95228u ad=0.6915p as=0.428612p pd=2.605u
++ ps=0.485u
+m16 3 37 2 VSS nm_hp l=0.117852u w=1.29021u ad=0.215075p as=0.454812p pd=0.38u
++ ps=1.95u
+m17 4 37 3 VSS nm_hp l=0.117852u w=1.29021u ad=0.247737p as=0.215075p pd=0.365u
++ ps=0.38u
+m18 5 37 4 VSS nm_hp l=0.117852u w=1.29021u ad=0.215075p as=0.247737p pd=0.38u
++ ps=0.365u
+m19 6 37 5 VSS nm_hp l=0.117852u w=1.29021u ad=0.25715p as=0.215075p pd=0.38u
++ ps=0.38u
+m20 7 37 6 VSS nm_hp l=0.117852u w=1.29021u ad=0.216727p as=0.25715p
++ pd=0.384383u ps=0.38u
+m21 8 37 7 VSS nm_hp l=0.117943u w=1.29435u ad=0.261568p as=0.217423p
++ pd=0.385617u ps=0.385617u
+m22 9 37 8 VSS nm_hp l=0.117852u w=1.29021u ad=0.216727p as=0.260731p
++ pd=0.384383u ps=0.384383u
+m23 10 37 9 VSS nm_hp l=0.117943u w=1.29435u ad=0.261568p as=0.217423p
++ pd=0.385617u ps=0.385617u
+m24 11 37 10 VSS nm_hp l=0.117852u w=1.29021u ad=0.222814p as=0.260731p
++ pd=0.345562u ps=0.384383u
+m25 12 37 11 VSS nm_hp l=0.118569u w=1.32334u ad=0.348887p as=0.228536p
++ pd=0.832275u ps=0.354437u
+m26 13 38 12 VSS nm_hp l=0.117829u w=1.30021u ad=0.2613p as=0.342787p pd=0.44u
++ ps=0.817724u
+m27 14 39 13 VSS nm_hp l=0.117829u w=1.30021u ad=0.252675p as=0.2613p pd=0.38u
++ ps=0.44u
+m28 15 39 14 VSS nm_hp l=0.117829u w=1.30021u ad=0.238725p as=0.252675p
++ pd=0.365u ps=0.38u
+m29 16 40 15 VSS nm_hp l=0.117829u w=1.30021u ad=0.299337p as=0.238725p pd=0.78u
++ ps=0.365u
+m30 17 40 16 VSS nm_hp l=0.117829u w=1.30021u ad=0.235325p as=0.299337p
++ pd=0.365u ps=0.78u
+m31 18 41 17 VSS nm_hp l=0.117829u w=1.30021u ad=0.458712p as=0.235325p pd=1.96u
++ ps=0.365u
+
+* resistors:
+r32 VSS 2 40 $[mnc]
+r33 VSS 2 40 $[mnc]
+r34 Z 3 40 $[mnc]
+r35 VSS 4 40 $[mnc]
+r36 VSS 4 40 $[mnc]
+r37 Z 5 40 $[mnc]
+r38 VSS 6 40 $[mnc]
+r39 VSS 6 40 $[mnc]
+r40 Z 7 40 $[mnc]
+r41 VSS 8 40 $[mnc]
+r42 VSS 8 40 $[mnc]
+r43 Z 9 40 $[mnc]
+r44 VSS 10 40 $[mnc]
+r45 VSS 10 40 $[mnc]
+r46 Z 11 40 $[mnc]
+r47 VSS 12 40 $[mnc]
+r48 VSS 12 40 $[mnc]
+r49 141 13 40 $[mnc]
+r50 139 14 40 $[mnc]
+r51 141 15 40 $[mnc]
+r52 VSS 16 40 $[mnc]
+r53 141 17 40 $[mnc]
+r54 139 18 40 $[mnc]
+r55 VDD 20 40 $[mpc]
+r56 VDD 20 40 $[mpc]
+r57 Z 21 40 $[mpc]
+r58 VDD 22 40 $[mpc]
+r59 VDD 22 40 $[mpc]
+r60 Z 23 40 $[mpc]
+r61 VDD 24 40 $[mpc]
+r62 VDD 24 40 $[mpc]
+r63 Z 25 40 $[mpc]
+r64 VDD 26 40 $[mpc]
+r65 VDD 26 40 $[mpc]
+r66 Z 27 40 $[mpc]
+r67 VDD 28 40 $[mpc]
+r68 VDD 28 40 $[mpc]
+r69 Z 29 40 $[mpc]
+r70 VDD 30 40 $[mpc]
+r71 VDD 30 40 $[mpc]
+r72 139 31 40 $[mpc]
+r73 VDD 32 40 $[mpc]
+r74 VDD 32 40 $[mpc]
+r75 139 33 40 $[mpc]
+r76 VDD 34 40 $[mpc]
+r77 VDD 34 40 $[mpc]
+r78 139 35 40 $[mpc]
+r79 VDD 36 40 $[mpc]
+r80 VDD 36 40 $[mpc]
+r81 139 37 14 $[mpolyc]
+r82 B 38 14 $[mpolyc]
+r83 A 39 14 $[mpolyc]
+r84 B 40 14 $[mpolyc]
+r85 A 41 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 1.77416f
+cp2 2 VSS 0.0669776f
+cp3 3 VSS 0.0367983f
+cp4 4 VSS 0.0685088f
+cp5 5 VSS 0.0372035f
+cp6 6 VSS 0.0698596f
+cp7 7 VSS 0.0380034f
+cp8 8 VSS 0.070147f
+cp9 9 VSS 0.037995f
+cp10 10 VSS 0.072258f
+cp11 11 VSS 0.0301182f
+cp12 12 VSS 0.101874f
+cp13 13 VSS 0.0581621f
+cp14 14 VSS 0.0391833f
+cp15 15 VSS 0.0401044f
+cp16 16 VSS 0.0518607f
+cp17 17 VSS 0.0549393f
+cp18 18 VSS 0.0303713f
+cp19 20 VSS 0.0670358f
+cp20 21 VSS 0.0390511f
+cp21 22 VSS 0.0753915f
+cp22 23 VSS 0.0398222f
+cp23 24 VSS 0.0756207f
+cp24 25 VSS 0.0611674f
+cp25 26 VSS 0.0756207f
+cp26 27 VSS 0.0398222f
+cp27 28 VSS 0.0756207f
+cp28 29 VSS 0.0312145f
+cp29 30 VSS 0.0876255f
+cp30 31 VSS 0.0363787f
+cp31 32 VSS 0.0727265f
+cp32 33 VSS 0.0318193f
+cp33 34 VSS 0.0711524f
+cp34 35 VSS 0.0436748f
+cp35 36 VSS 0.0714809f
+cp36 37 VSS 2.18688f
+cp37 38 VSS 0.58226f
+cp38 39 VSS 0.844982f
+cp39 40 VSS 0.840807f
+cp40 41 VSS 0.41454f
+cp41 Z VSS 1.11933f
+cp42 139 VSS 1.22948f
+cp43 B VSS 0.425553f
+cp44 141 VSS 0.400358f
+cp45 A VSS 0.382799f
+
+.ENDS
+
+
+** and2m12p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m12p.iclib2,v 9.0.1.5 2002/06/25 06:56:51 tvarga Exp $
+
+.SUBCKT AND2M12P Z A B VDD VSS
+
+* devices:
+m0 23 41 22 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.635312p pd=0.38u
++ ps=2.415u
+m1 24 41 23 VDD pm_hp l=0.116656u w=1.75521u ad=0.351512p as=0.284512p pd=0.365u
++ ps=0.38u
+m2 25 41 24 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.351512p pd=0.38u
++ ps=0.365u
+m3 26 41 25 VDD pm_hp l=0.116656u w=1.75521u ad=0.351512p as=0.284512p pd=0.365u
++ ps=0.38u
+m4 27 41 26 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.351512p pd=0.38u
++ ps=0.365u
+m5 28 41 27 VDD pm_hp l=0.116656u w=1.75521u ad=0.351512p as=0.284512p pd=0.365u
++ ps=0.38u
+m6 29 41 28 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.351512p pd=0.38u
++ ps=0.365u
+m7 30 41 29 VDD pm_hp l=0.116656u w=1.75521u ad=0.351512p as=0.284512p pd=0.365u
++ ps=0.38u
+m8 31 41 30 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.351512p pd=0.38u
++ ps=0.365u
+m9 32 41 31 VDD pm_hp l=0.116656u w=1.75521u ad=0.351512p as=0.284512p pd=0.365u
++ ps=0.38u
+m10 33 41 32 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.351512p pd=0.38u
++ ps=0.365u
+m11 34 41 33 VDD pm_hp l=0.116656u w=1.75521u ad=0.428912p as=0.284512p
++ pd=0.455u ps=0.38u
+m12 35 42 34 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.428912p pd=0.38u
++ ps=0.455u
+m13 36 43 35 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m14 37 43 36 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.364412p pd=0.38u
++ ps=0.38u
+m15 38 44 37 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m16 39 44 38 VDD pm_hp l=0.116656u w=1.75521u ad=0.288812p as=0.364412p
++ pd=0.385u ps=0.38u
+m17 40 45 39 VDD pm_hp l=0.116656u w=1.75521u ad=0.635312p as=0.288812p
++ pd=2.415u ps=0.385u
+m18 3 41 2 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.408012p pd=0.38u
++ ps=1.83u
+m19 4 41 3 VSS nm_hp l=0.118152u w=1.17021u ad=0.220737p as=0.197375p pd=0.365u
++ ps=0.38u
+m20 5 41 4 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.220737p pd=0.38u
++ ps=0.365u
+m21 6 41 5 VSS nm_hp l=0.118152u w=1.17021u ad=0.220737p as=0.197375p pd=0.365u
++ ps=0.38u
+m22 7 41 6 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.220737p pd=0.38u
++ ps=0.365u
+m23 8 41 7 VSS nm_hp l=0.118152u w=1.17021u ad=0.220737p as=0.197375p pd=0.365u
++ ps=0.38u
+m24 9 41 8 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.220737p pd=0.38u
++ ps=0.365u
+m25 10 41 9 VSS nm_hp l=0.118152u w=1.17021u ad=0.220737p as=0.197375p pd=0.365u
++ ps=0.38u
+m26 11 41 10 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.220737p pd=0.38u
++ ps=0.365u
+m27 12 41 11 VSS nm_hp l=0.118152u w=1.17021u ad=0.220737p as=0.197375p
++ pd=0.365u ps=0.38u
+m28 13 41 12 VSS nm_hp l=0.118152u w=1.17021u ad=0.211387p as=0.220737p
++ pd=0.365u ps=0.365u
+m29 14 41 13 VSS nm_hp l=0.118152u w=1.17021u ad=0.320337p as=0.211387p pd=0.91u
++ ps=0.365u
+m30 15 42 14 VSS nm_hp l=0.118152u w=1.17021u ad=0.2048p as=0.320337p pd=0.365u
++ ps=0.91u
+m31 16 43 15 VSS nm_hp l=0.118152u w=1.17021u ad=0.2048p as=0.2048p pd=0.365u
++ ps=0.365u
+m32 17 43 16 VSS nm_hp l=0.118152u w=1.17021u ad=0.217275p as=0.2048p pd=0.375u
++ ps=0.365u
+m33 18 44 17 VSS nm_hp l=0.118152u w=1.17021u ad=0.320125p as=0.217275p pd=0.91u
++ ps=0.375u
+m34 19 44 18 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.320125p pd=0.38u
++ ps=0.91u
+m35 20 45 19 VSS nm_hp l=0.118152u w=1.17021u ad=0.408012p as=0.197375p pd=1.83u
++ ps=0.38u
+
+* resistors:
+r36 VSS 2 40 $[mnc]
+r37 VSS 2 40 $[mnc]
+r38 Z 3 40 $[mnc]
+r39 VSS 4 40 $[mnc]
+r40 VSS 4 40 $[mnc]
+r41 Z 5 40 $[mnc]
+r42 VSS 6 40 $[mnc]
+r43 VSS 6 40 $[mnc]
+r44 Z 7 40 $[mnc]
+r45 VSS 8 40 $[mnc]
+r46 VSS 8 40 $[mnc]
+r47 Z 9 40 $[mnc]
+r48 VSS 10 40 $[mnc]
+r49 VSS 10 40 $[mnc]
+r50 Z 11 40 $[mnc]
+r51 VSS 12 40 $[mnc]
+r52 VSS 12 40 $[mnc]
+r53 Z 13 40 $[mnc]
+r54 VSS 14 40 $[mnc]
+r55 VSS 14 40 $[mnc]
+r56 155 15 40 $[mnc]
+r57 153 16 40 $[mnc]
+r58 155 17 40 $[mnc]
+r59 VSS 18 40 $[mnc]
+r60 155 19 40 $[mnc]
+r61 153 20 40 $[mnc]
+r62 VDD 22 40 $[mpc]
+r63 VDD 22 40 $[mpc]
+r64 Z 23 40 $[mpc]
+r65 VDD 24 40 $[mpc]
+r66 VDD 24 40 $[mpc]
+r67 Z 25 40 $[mpc]
+r68 VDD 26 40 $[mpc]
+r69 VDD 26 40 $[mpc]
+r70 Z 27 40 $[mpc]
+r71 VDD 28 40 $[mpc]
+r72 VDD 28 40 $[mpc]
+r73 Z 29 40 $[mpc]
+r74 VDD 30 40 $[mpc]
+r75 VDD 30 40 $[mpc]
+r76 Z 31 40 $[mpc]
+r77 VDD 32 40 $[mpc]
+r78 VDD 32 40 $[mpc]
+r79 Z 33 40 $[mpc]
+r80 VDD 34 40 $[mpc]
+r81 VDD 34 40 $[mpc]
+r82 153 35 40 $[mpc]
+r83 VDD 36 40 $[mpc]
+r84 VDD 36 40 $[mpc]
+r85 153 37 40 $[mpc]
+r86 VDD 38 40 $[mpc]
+r87 VDD 38 40 $[mpc]
+r88 153 39 40 $[mpc]
+r89 VDD 40 40 $[mpc]
+r90 VDD 40 40 $[mpc]
+r91 153 41 14 $[mpolyc]
+r92 B 42 14 $[mpolyc]
+r93 A 43 14 $[mpolyc]
+r94 B 44 14 $[mpolyc]
+r95 A 45 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 1.94455f
+cp2 2 VSS 0.0669294f
+cp3 3 VSS 0.0367983f
+cp4 4 VSS 0.0664982f
+cp5 5 VSS 0.0372005f
+cp6 6 VSS 0.0664982f
+cp7 7 VSS 0.0371777f
+cp8 8 VSS 0.0664982f
+cp9 9 VSS 0.0363705f
+cp10 10 VSS 0.0664982f
+cp11 11 VSS 0.0372005f
+cp12 12 VSS 0.0697293f
+cp13 13 VSS 0.0296194f
+cp14 14 VSS 0.108156f
+cp15 15 VSS 0.0628747f
+cp16 16 VSS 0.0395401f
+cp17 17 VSS 0.0415426f
+cp18 18 VSS 0.0591968f
+cp19 19 VSS 0.0474836f
+cp20 20 VSS 0.0309044f
+cp21 22 VSS 0.0669294f
+cp22 23 VSS 0.0382232f
+cp23 24 VSS 0.0738112f
+cp24 25 VSS 0.0389894f
+cp25 26 VSS 0.0738112f
+cp26 27 VSS 0.0389666f
+cp27 28 VSS 0.0738112f
+cp28 29 VSS 0.0401976f
+cp29 30 VSS 0.0738112f
+cp30 31 VSS 0.0389894f
+cp31 32 VSS 0.0746449f
+cp32 33 VSS 0.0316214f
+cp33 34 VSS 0.0864697f
+cp34 35 VSS 0.0355994f
+cp35 36 VSS 0.0704575f
+cp36 37 VSS 0.030572f
+cp37 38 VSS 0.0694666f
+cp38 39 VSS 0.0303905f
+cp39 40 VSS 0.0701144f
+cp40 41 VSS 2.59583f
+cp41 42 VSS 0.598906f
+cp42 43 VSS 0.853775f
+cp43 44 VSS 0.850337f
+cp44 45 VSS 0.454421f
+cp45 Z VSS 1.32967f
+cp46 153 VSS 1.18339f
+cp47 B VSS 0.328543f
+cp48 155 VSS 0.361829f
+cp49 A VSS 0.338686f
+
+.ENDS
+
+
+** and2m1p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m1p.iclib2,v 9.0.1.5 2002/06/20 18:50:42 kensz Exp $
+
+.SUBCKT AND2M1P Z A B VDD VSS
+
+* devices:
+m0 8 11 7 VDD pm_hp l=0.117448u w=1.19521u ad=0.201062p as=0.417762p pd=0.38u
++ ps=1.855u
+m1 9 12 8 VDD pm_hp l=0.117448u w=1.19521u ad=0.301859p as=0.201062p
++ pd=0.573131u ps=0.38u
+m2 10 13 9 VDD pm_hp l=0.116666u w=1.74521u ad=0.551512p as=0.440766p pd=2.405u
++ ps=0.836869u
+m3 3 11 2 VSS nm_hp l=0.119762u w=0.785208u ad=0.135287p as=0.258712p pd=0.35u
++ ps=1.445u
+m4 4 12 3 VSS nm_hp l=0.119762u w=0.785208u ad=0.261162p as=0.135287p
++ pd=0.914864u ps=0.35u
+m5 5 13 4 VSS nm_hp l=0.118209u w=1.15021u ad=0.370037p as=0.382562p pd=1.81u
++ ps=1.34013u
+
+* resistors:
+r6 38 2 40 $[mnc]
+r7 VSS 4 40 $[mnc]
+r8 VSS 4 40 $[mnc]
+r9 Z 5 40 $[mnc]
+r10 VDD 7 40 $[mpc]
+r11 VDD 7 40 $[mpc]
+r12 38 8 40 $[mpc]
+r13 VDD 9 40 $[mpc]
+r14 VDD 9 40 $[mpc]
+r15 Z 10 40 $[mpc]
+r16 A 11 14 $[mpolyc]
+r17 B 12 14 $[mpolyc]
+r18 38 13 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.479219f
+cp2 2 VSS 0.0339761f
+cp3 3 VSS 0.0206746f
+cp4 4 VSS 0.0805333f
+cp5 5 VSS 0.0360938f
+cp6 7 VSS 0.0837751f
+cp7 8 VSS 0.0355503f
+cp8 9 VSS 0.0889938f
+cp9 10 VSS 0.0343166f
+cp10 11 VSS 0.40561f
+cp11 12 VSS 0.485111f
+cp12 13 VSS 0.409236f
+cp13 A VSS 0.0990763f
+cp14 38 VSS 0.491529f
+cp15 B VSS 0.11438f
+cp16 Z VSS 0.227802f
+
+.ENDS
+
+
+** and2m2p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m2p.iclib2,v 9.0.1.5 2002/06/20 18:49:41 kensz Exp $
+
+.SUBCKT AND2M2P Z A B VDD VSS
+
+* devices:
+m0 9 13 8 VDD pm_hp l=0.116666u w=1.74521u ad=0.293987p as=0.632262p
++ pd=0.335311u ps=2.405u
+m1 10 13 9 VDD pm_hp l=0.117041u w=1.76799u ad=0.348317p as=0.297825p
++ pd=0.716275u ps=0.339688u
+m2 11 14 10 VDD pm_hp l=0.116734u w=1.74935u ad=0.303886p as=0.344645p
++ pd=0.357712u ps=0.708724u
+m3 12 15 11 VDD pm_hp l=0.1167u w=1.74728u ad=0.63p as=0.303526p pd=2.4u
++ ps=0.357288u
+m4 3 13 2 VSS nm_hp l=0.117764u w=1.33021u ad=0.220975p as=0.470412p pd=0.38u
++ ps=1.99u
+m5 4 13 3 VSS nm_hp l=0.117764u w=1.33021u ad=0.355725p as=0.220975p pd=0.755u
++ ps=0.38u
+m6 5 14 4 VSS nm_hp l=0.117764u w=1.33021u ad=0.1821p as=0.355725p pd=0.275u
++ ps=0.755u
+m7 6 15 5 VSS nm_hp l=0.117764u w=1.33021u ad=0.424937p as=0.1821p pd=1.99u
++ ps=0.275u
+
+* resistors:
+r8 VSS 2 40 $[mnc]
+r9 VSS 2 40 $[mnc]
+r10 Z 3 40 $[mnc]
+r11 VSS 4 40 $[mnc]
+r12 VSS 4 40 $[mnc]
+r13 46 6 40 $[mnc]
+r14 VDD 8 40 $[mpc]
+r15 VDD 8 40 $[mpc]
+r16 Z 9 40 $[mpc]
+r17 VDD 10 40 $[mpc]
+r18 VDD 10 40 $[mpc]
+r19 46 11 40 $[mpc]
+r20 VDD 12 40 $[mpc]
+r21 VDD 12 40 $[mpc]
+r22 46 13 14 $[mpolyc]
+r23 B 14 14 $[mpolyc]
+r24 A 15 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.558962f
+cp2 2 VSS 0.0939312f
+cp3 3 VSS 0.0338934f
+cp4 4 VSS 0.0466969f
+cp5 6 VSS 0.0283539f
+cp6 8 VSS 0.0953829f
+cp7 9 VSS 0.0318202f
+cp8 10 VSS 0.0627591f
+cp9 11 VSS 0.033193f
+cp10 12 VSS 0.0929633f
+cp11 13 VSS 0.651235f
+cp12 14 VSS 0.677715f
+cp13 15 VSS 0.508204f
+cp14 Z VSS 0.290201f
+cp15 46 VSS 0.414581f
+cp16 B VSS 0.134029f
+cp17 A VSS 0.153095f
+
+.ENDS
+
+
+** and2m4p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m4p.iclib2,v 9.0.1.5 2002/06/20 18:47:18 kensz Exp $
+
+.SUBCKT AND2M4P Z A B VDD VSS
+
+* devices:
+m0 11 17 10 VDD pm_hp l=0.116557u w=1.86521u ad=0.310087p as=0.668862p pd=0.38u
++ ps=2.525u
+m1 12 17 11 VDD pm_hp l=0.116557u w=1.86521u ad=0.380637p as=0.310087p pd=0.38u
++ ps=0.38u
+m2 13 17 12 VDD pm_hp l=0.116557u w=1.86521u ad=0.310087p as=0.380637p pd=0.38u
++ ps=0.38u
+m3 14 17 13 VDD pm_hp l=0.116557u w=1.86521u ad=0.380637p as=0.310087p pd=0.38u
++ ps=0.38u
+m4 15 18 14 VDD pm_hp l=0.116557u w=1.86521u ad=0.310087p as=0.380637p pd=0.38u
++ ps=0.38u
+m5 16 19 15 VDD pm_hp l=0.116557u w=1.86521u ad=0.668862p as=0.310087p pd=2.525u
++ ps=0.38u
+m6 3 17 2 VSS nm_hp l=0.118017u w=1.24228u ad=0.209687p as=0.439075p pd=0.385u
++ ps=1.905u
+m7 4 17 3 VSS nm_hp l=0.118017u w=1.24228u ad=0.249287p as=0.209687p pd=0.385u
++ ps=0.385u
+m8 5 17 4 VSS nm_hp l=0.118017u w=1.24228u ad=0.209687p as=0.249287p pd=0.385u
++ ps=0.385u
+m9 6 17 5 VSS nm_hp l=0.118017u w=1.24228u ad=0.34085p as=0.209687p pd=0.835u
++ ps=0.385u
+m10 7 18 6 VSS nm_hp l=0.118017u w=1.24228u ad=0.169962p as=0.34085p pd=0.275u
++ ps=0.835u
+m11 8 19 7 VSS nm_hp l=0.118017u w=1.24228u ad=0.53805p as=0.169962p pd=2.135u
++ ps=0.275u
+
+* resistors:
+r12 VSS 2 40 $[mnc]
+r13 VSS 2 40 $[mnc]
+r14 Z 3 40 $[mnc]
+r15 VSS 4 40 $[mnc]
+r16 VSS 4 40 $[mnc]
+r17 Z 5 40 $[mnc]
+r18 VSS 6 40 $[mnc]
+r19 VSS 6 40 $[mnc]
+r20 62 8 40 $[mnc]
+r21 VDD 10 40 $[mpc]
+r22 VDD 10 40 $[mpc]
+r23 Z 11 40 $[mpc]
+r24 VDD 12 40 $[mpc]
+r25 VDD 12 40 $[mpc]
+r26 Z 13 40 $[mpc]
+r27 VDD 14 40 $[mpc]
+r28 VDD 14 40 $[mpc]
+r29 62 15 40 $[mpc]
+r30 VDD 16 40 $[mpc]
+r31 VDD 16 40 $[mpc]
+r32 62 17 14 $[mpolyc]
+r33 B 18 14 $[mpolyc]
+r34 A 19 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.793447f
+cp2 2 VSS 0.0670167f
+cp3 3 VSS 0.0415182f
+cp4 4 VSS 0.073124f
+cp5 5 VSS 0.0317776f
+cp6 6 VSS 0.0484275f
+cp7 8 VSS 0.0307134f
+cp8 10 VSS 0.0669584f
+cp9 11 VSS 0.0525539f
+cp10 12 VSS 0.0716035f
+cp11 13 VSS 0.0303499f
+cp12 14 VSS 0.0821127f
+cp13 15 VSS 0.040096f
+cp14 16 VSS 0.0592826f
+cp15 17 VSS 1.0376f
+cp16 18 VSS 0.636199f
+cp17 19 VSS 0.498244f
+cp18 Z VSS 0.480911f
+cp19 62 VSS 0.573239f
+cp20 B VSS 0.100422f
+cp21 A VSS 0.122793f
+
+.ENDS
+
+
+** and2m8p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and2m8p.iclib2,v 9.0.1.5 2002/06/20 18:46:25 kensz Exp $
+
+.SUBCKT AND2M8P Z A B VDD VSS
+
+* devices:
+m0 17 29 16 VDD pm_hp l=0.116557u w=1.86521u ad=0.299887p as=0.679062p pd=0.38u
++ ps=2.525u
+m1 18 29 17 VDD pm_hp l=0.116557u w=1.86521u ad=0.390837p as=0.299887p pd=0.38u
++ ps=0.38u
+m2 19 29 18 VDD pm_hp l=0.116557u w=1.86521u ad=0.299887p as=0.390837p pd=0.38u
++ ps=0.38u
+m3 20 29 19 VDD pm_hp l=0.116557u w=1.86521u ad=0.390837p as=0.299887p pd=0.38u
++ ps=0.38u
+m4 21 29 20 VDD pm_hp l=0.116557u w=1.86521u ad=0.299887p as=0.390837p pd=0.38u
++ ps=0.38u
+m5 22 29 21 VDD pm_hp l=0.116557u w=1.86521u ad=0.385737p as=0.299887p pd=0.38u
++ ps=0.38u
+m6 23 29 22 VDD pm_hp l=0.116557u w=1.86521u ad=0.520537p as=0.385737p pd=0.61u
++ ps=0.38u
+m7 24 29 23 VDD pm_hp l=0.116557u w=1.86521u ad=0.467704p as=0.520537p
++ pd=0.540951u ps=0.61u
+m8 25 30 24 VDD pm_hp l=0.116656u w=1.75521u ad=0.293862p as=0.440121p pd=0.38u
++ ps=0.509049u
+m9 26 31 25 VDD pm_hp l=0.116656u w=1.75521u ad=0.355062p as=0.293862p pd=0.38u
++ ps=0.38u
+m10 27 31 26 VDD pm_hp l=0.116656u w=1.75521u ad=0.461562p as=0.355062p
++ pd=0.575u ps=0.38u
+m11 28 32 27 VDD pm_hp l=0.116656u w=1.75521u ad=0.625962p as=0.461562p
++ pd=2.415u ps=0.575u
+m12 3 29 2 VSS nm_hp l=0.118017u w=1.24228u ad=0.209687p as=0.439075p pd=0.385u
++ ps=1.905u
+m13 4 29 3 VSS nm_hp l=0.118017u w=1.24228u ad=0.249287p as=0.209687p pd=0.385u
++ ps=0.385u
+m14 5 29 4 VSS nm_hp l=0.118017u w=1.24228u ad=0.209687p as=0.249287p pd=0.385u
++ ps=0.385u
+m15 6 29 5 VSS nm_hp l=0.118017u w=1.24228u ad=0.249287p as=0.209687p pd=0.385u
++ ps=0.385u
+m16 7 29 6 VSS nm_hp l=0.118017u w=1.24228u ad=0.209687p as=0.249287p pd=0.385u
++ ps=0.385u
+m17 8 29 7 VSS nm_hp l=0.118017u w=1.24228u ad=0.249287p as=0.209687p pd=0.385u
++ ps=0.385u
+m18 9 29 8 VSS nm_hp l=0.118017u w=1.24228u ad=0.230775p as=0.249287p pd=0.42u
++ ps=0.385u
+m19 10 29 9 VSS nm_hp l=0.118017u w=1.24228u ad=0.285607p as=0.230775p
++ pd=0.501661u ps=0.42u
+m20 11 30 10 VSS nm_hp l=0.115u w=1.135u ad=0.264762p as=0.260943p pd=0.484978u
++ ps=0.458339u
+m21 12 31 11 VSS nm_hp l=0.118152u w=1.17021u ad=0.253037p as=0.272975p pd=0.45u
++ ps=0.500022u
+m22 13 31 12 VSS nm_hp l=0.118152u w=1.17021u ad=0.315223p as=0.253037p
++ pd=0.540633u ps=0.45u
+m23 14 32 13 VSS nm_hp l=0.115u w=1.135u ad=0.44265p as=0.305739p pd=1.915u
++ ps=0.524367u
+
+* resistors:
+r24 VSS 2 40 $[mnc]
+r25 VSS 2 40 $[mnc]
+r26 Z 3 40 $[mnc]
+r27 VSS 4 40 $[mnc]
+r28 VSS 4 40 $[mnc]
+r29 Z 5 40 $[mnc]
+r30 VSS 6 40 $[mnc]
+r31 VSS 6 40 $[mnc]
+r32 Z 7 40 $[mnc]
+r33 VSS 8 40 $[mnc]
+r34 VSS 8 40 $[mnc]
+r35 Z 9 40 $[mnc]
+r36 VSS 10 40 $[mnc]
+r37 VSS 10 40 $[mnc]
+r38 113 11 40 $[mnc]
+r39 111 12 40 $[mnc]
+r40 113 13 40 $[mnc]
+r41 VSS 14 40 $[mnc]
+r42 VSS 14 40 $[mnc]
+r43 VDD 16 40 $[mpc]
+r44 VDD 16 40 $[mpc]
+r45 Z 17 40 $[mpc]
+r46 VDD 18 40 $[mpc]
+r47 VDD 18 40 $[mpc]
+r48 Z 19 40 $[mpc]
+r49 VDD 20 40 $[mpc]
+r50 VDD 20 40 $[mpc]
+r51 Z 21 40 $[mpc]
+r52 VDD 22 40 $[mpc]
+r53 VDD 22 40 $[mpc]
+r54 Z 23 40 $[mpc]
+r55 VDD 24 40 $[mpc]
+r56 VDD 24 40 $[mpc]
+r57 111 25 40 $[mpc]
+r58 VDD 26 40 $[mpc]
+r59 VDD 26 40 $[mpc]
+r60 111 27 40 $[mpc]
+r61 VDD 28 40 $[mpc]
+r62 VDD 28 40 $[mpc]
+r63 111 29 14 $[mpolyc]
+r64 B 30 14 $[mpolyc]
+r65 A 31 14 $[mpolyc]
+r66 B 32 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 1.41855f
+cp2 2 VSS 0.0670167f
+cp3 3 VSS 0.0339461f
+cp4 4 VSS 0.0523969f
+cp5 5 VSS 0.0284561f
+cp6 6 VSS 0.052626f
+cp7 7 VSS 0.0278551f
+cp8 8 VSS 0.0529962f
+cp9 9 VSS 0.0305014f
+cp10 10 VSS 0.0833849f
+cp11 11 VSS 0.0449052f
+cp12 12 VSS 0.0466324f
+cp13 13 VSS 0.0344949f
+cp14 14 VSS 0.075112f
+cp15 16 VSS 0.0669584f
+cp16 17 VSS 0.0351186f
+cp17 18 VSS 0.0546883f
+cp18 19 VSS 0.0304703f
+cp19 20 VSS 0.054862f
+cp20 21 VSS 0.0300126f
+cp21 22 VSS 0.0571222f
+cp22 23 VSS 0.0398241f
+cp23 24 VSS 0.0575249f
+cp24 25 VSS 0.0468614f
+cp25 26 VSS 0.0727373f
+cp26 27 VSS 0.0511403f
+cp27 28 VSS 0.0732119f
+cp28 29 VSS 1.79882f
+cp29 30 VSS 0.53576f
+cp30 31 VSS 0.745306f
+cp31 32 VSS 0.345019f
+cp32 Z VSS 0.863828f
+cp33 111 VSS 0.701749f
+cp34 B VSS 0.352914f
+cp35 113 VSS 0.237335f
+cp36 A VSS 0.11993f
+
+.ENDS
+
+
+** and3m05p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and3m05p.iclib2,v 9.0.1.5 2002/07/18 14:39:04 rchiang Exp $
+
+.SUBCKT AND3M05P Z A B C VDD VSS
+
+* devices:
+m0 9 13 8 VDD pm_hp l=0.115u w=1.005u ad=0.226125p as=0.39195p pd=0.45u
++ ps=1.785u
+m1 10 14 9 VDD pm_hp l=0.115u w=1.005u ad=0.226125p as=0.226125p pd=0.45u
++ ps=0.45u
+m2 11 15 10 VDD pm_hp l=0.115u w=1.005u ad=0.226125p as=0.226125p pd=0.45u
++ ps=0.45u
+m3 12 16 11 VDD pm_hp l=0.115u w=1.005u ad=0.396975p as=0.226125p pd=1.795u
++ ps=0.45u
+m4 3 13 2 VSS nm_hp l=0.119677u w=0.647426u ad=0.1221p as=0.298675p pd=0.39u
++ ps=1.575u
+m5 4 14 3 VSS nm_hp l=0.119677u w=0.647426u ad=0.118987p as=0.1221p pd=0.375u
++ ps=0.39u
+m6 5 15 4 VSS nm_hp l=0.119677u w=0.647426u ad=0.341486p as=0.118987p
++ pd=1.54531u ps=0.375u
+m7 6 16 5 VSS nm_hp l=0.120619u w=0.670208u ad=0.223637p as=0.353502p pd=1.33u
++ ps=1.59969u
+
+* resistors:
+r8 46 2 40 $[mnc]
+r9 VSS 5 40 $[mnc]
+r10 VSS 5 40 $[mnc]
+r11 Z 6 40 $[mnc]
+r12 46 8 40 $[mpc]
+r13 VDD 9 40 $[mpc]
+r14 VDD 9 40 $[mpc]
+r15 46 10 40 $[mpc]
+r16 VDD 11 40 $[mpc]
+r17 VDD 11 40 $[mpc]
+r18 Z 12 40 $[mpc]
+r19 A 13 14 $[mpolyc]
+r20 B 14 14 $[mpolyc]
+r21 C 15 14 $[mpolyc]
+r22 46 16 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.636591f
+cp2 2 VSS 0.0290607f
+cp3 5 VSS 0.0721881f
+cp4 6 VSS 0.0391547f
+cp5 8 VSS 0.0322457f
+cp6 9 VSS 0.0807842f
+cp7 10 VSS 0.0387073f
+cp8 11 VSS 0.085382f
+cp9 12 VSS 0.0314358f
+cp10 13 VSS 0.371906f
+cp11 14 VSS 0.467658f
+cp12 15 VSS 0.415995f
+cp13 16 VSS 0.36607f
+cp14 46 VSS 0.53657f
+cp15 A VSS 0.12523f
+cp16 B VSS 0.13926f
+cp17 C VSS 0.10389f
+cp18 Z VSS 0.256418f
+
+.ENDS
+
+
+** and3m1p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and3m1p.iclib2,v 9.0.1.6 2002/07/18 14:39:06 rchiang Exp $
+
+.SUBCKT AND3M1P Z A B C VDD VSS
+
+* devices:
+m0 9 13 8 VDD pm_hp l=0.117238u w=1.30521u ad=0.242981p as=0.417312p
++ pd=0.348342u ps=1.965u
+m1 10 14 9 VDD pm_hp l=0.11751u w=1.31763u ad=0.221833p as=0.245294p
++ pd=0.351658u ps=0.351658u
+m2 11 15 10 VDD pm_hp l=0.117238u w=1.30521u ad=0.287866p as=0.219741p
++ pd=0.534848u ps=0.348342u
+m3 12 16 11 VDD pm_hp l=0.116666u w=1.74521u ad=0.551512p as=0.384909p pd=2.405u
++ ps=0.715151u
+m4 3 13 2 VSS nm_hp l=0.118449u w=0.850355u ad=0.129287p as=0.314662p pd=0.305u
++ ps=1.595u
+m5 4 14 3 VSS nm_hp l=0.118449u w=0.850355u ad=0.104087p as=0.129287p pd=0.245u
++ ps=0.305u
+m6 5 15 4 VSS nm_hp l=0.118449u w=0.850355u ad=0.301834p as=0.104087p
++ pd=0.961919u ps=0.245u
+m7 6 16 5 VSS nm_hp l=0.118166u w=1.16521u ad=0.374612p as=0.413591p pd=1.825u
++ ps=1.31808u
+
+* resistors:
+r8 45 2 40 $[mnc]
+r9 VSS 5 40 $[mnc]
+r10 VSS 5 40 $[mnc]
+r11 Z 6 40 $[mnc]
+r12 45 8 40 $[mpc]
+r13 VDD 9 40 $[mpc]
+r14 VDD 9 40 $[mpc]
+r15 45 10 40 $[mpc]
+r16 VDD 11 40 $[mpc]
+r17 VDD 11 40 $[mpc]
+r18 Z 12 40 $[mpc]
+r19 A 13 14 $[mpolyc]
+r20 B 14 14 $[mpolyc]
+r21 C 15 14 $[mpolyc]
+r22 45 16 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.51545f
+cp2 2 VSS 0.0287003f
+cp3 3 VSS 0.0204619f
+cp4 4 VSS 0.0144722f
+cp5 5 VSS 0.0838524f
+cp6 6 VSS 0.0265267f
+cp7 8 VSS 0.0340576f
+cp8 9 VSS 0.0785224f
+cp9 10 VSS 0.0331284f
+cp10 11 VSS 0.0841101f
+cp11 12 VSS 0.0249463f
+cp12 13 VSS 0.421279f
+cp13 14 VSS 0.589448f
+cp14 15 VSS 0.547472f
+cp15 16 VSS 0.407897f
+cp16 A VSS 0.124394f
+cp17 45 VSS 0.686422f
+cp18 B VSS 0.123534f
+cp19 C VSS 0.144458f
+cp20 Z VSS 0.210486f
+
+.ENDS
+
+
+** and3m2p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and3m2p.iclib2,v 9.0.1.5 2002/06/20 18:48:37 kensz Exp $
+
+.SUBCKT AND3M2P Z A B C VDD VSS
+
+* devices:
+m0 10 15 9 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.632262p pd=0.38u
++ ps=2.405u
+m1 11 15 10 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.282187p pd=0.38u
++ ps=0.38u
+m2 12 16 11 VDD pm_hp l=0.116666u w=1.74521u ad=0.406162p as=0.362937p pd=0.525u
++ ps=0.38u
+m3 13 17 12 VDD pm_hp l=0.116666u w=1.74521u ad=0.486912p as=0.406162p pd=0.525u
++ ps=0.525u
+m4 14 18 13 VDD pm_hp l=0.116666u w=1.74521u ad=0.551512p as=0.486912p pd=2.405u
++ ps=0.525u
+m5 3 15 2 VSS nm_hp l=0.118166u w=1.16521u ad=0.196637p as=0.406062p pd=0.38u
++ ps=1.825u
+m6 4 15 3 VSS nm_hp l=0.118166u w=1.16521u ad=0.329962p as=0.196637p pd=0.905u
++ ps=0.38u
+m7 5 16 4 VSS nm_hp l=0.118166u w=1.16521u ad=0.246987p as=0.329962p pd=0.43u
++ ps=0.905u
+m8 6 17 5 VSS nm_hp l=0.118166u w=1.16521u ad=0.165062p as=0.246987p pd=0.285u
++ ps=0.43u
+m9 7 18 6 VSS nm_hp l=0.118166u w=1.16521u ad=0.674062p as=0.165062p pd=2.355u
++ ps=0.285u
+
+* resistors:
+r10 VSS 2 40 $[mnc]
+r11 VSS 2 40 $[mnc]
+r12 Z 3 40 $[mnc]
+r13 VSS 4 40 $[mnc]
+r14 VSS 4 40 $[mnc]
+r15 55 7 40 $[mnc]
+r16 VDD 9 40 $[mpc]
+r17 VDD 9 40 $[mpc]
+r18 Z 10 40 $[mpc]
+r19 VDD 11 40 $[mpc]
+r20 VDD 11 40 $[mpc]
+r21 55 12 40 $[mpc]
+r22 VDD 13 40 $[mpc]
+r23 VDD 13 40 $[mpc]
+r24 55 14 40 $[mpc]
+r25 55 15 14 $[mpolyc]
+r26 C 16 14 $[mpolyc]
+r27 B 17 14 $[mpolyc]
+r28 A 18 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.683924f
+cp2 2 VSS 0.0742825f
+cp3 3 VSS 0.0378567f
+cp4 4 VSS 0.0484689f
+cp5 7 VSS 0.0370081f
+cp6 9 VSS 0.0669337f
+cp7 10 VSS 0.0286857f
+cp8 11 VSS 0.075655f
+cp9 12 VSS 0.0430763f
+cp10 13 VSS 0.0930873f
+cp11 14 VSS 0.040152f
+cp12 15 VSS 0.649459f
+cp13 16 VSS 0.557927f
+cp14 17 VSS 0.575231f
+cp15 18 VSS 0.460976f
+cp16 Z VSS 0.228263f
+cp17 55 VSS 0.519969f
+cp18 C VSS 0.107776f
+cp19 B VSS 0.13741f
+cp20 A VSS 0.116509f
+
+.ENDS
+
+
+** and3m4p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and3m4p.iclib2,v 9.0.1.5 2002/06/25 06:53:39 tvarga Exp $
+
+.SUBCKT AND3M4P Z A B C VDD VSS
+
+* devices:
+m0 12 19 11 VDD pm_hp l=0.11669u w=1.72021u ad=0.2785p as=0.622512p pd=0.38u
++ ps=2.38u
+m1 13 19 12 VDD pm_hp l=0.11669u w=1.72021u ad=0.357125p as=0.2785p pd=0.38u
++ ps=0.38u
+m2 14 19 13 VDD pm_hp l=0.11669u w=1.72021u ad=0.2785p as=0.357125p pd=0.38u
++ ps=0.38u
+m3 15 19 14 VDD pm_hp l=0.11669u w=1.72021u ad=0.357125p as=0.2785p pd=0.38u
++ ps=0.38u
+m4 16 20 15 VDD pm_hp l=0.11669u w=1.72021u ad=0.3796p as=0.357125p pd=0.5u
++ ps=0.38u
+m5 17 21 16 VDD pm_hp l=0.11669u w=1.72021u ad=0.357125p as=0.3796p pd=0.38u
++ ps=0.5u
+m6 18 22 17 VDD pm_hp l=0.11669u w=1.72021u ad=0.543887p as=0.357125p pd=2.38u
++ ps=0.38u
+m7 3 19 2 VSS nm_hp l=0.118201u w=1.13314u ad=0.19025p as=0.3966p pd=0.375u
++ ps=1.8u
+m8 4 19 3 VSS nm_hp l=0.118201u w=1.13314u ad=0.21785p as=0.19025p pd=0.375u
++ ps=0.375u
+m9 5 19 4 VSS nm_hp l=0.118201u w=1.13314u ad=0.191057p as=0.21785p pd=0.377155u
++ ps=0.375u
+m10 6 19 5 VSS nm_hp l=0.118252u w=1.13521u ad=0.329839p as=0.191406p
++ pd=0.954602u ps=0.377844u
+m11 7 20 6 VSS nm_hp l=0.118267u w=1.13021u ad=0.203875p as=0.328386p pd=0.365u
++ ps=0.950397u
+m12 8 21 7 VSS nm_hp l=0.118267u w=1.13021u ad=0.190187p as=0.203875p pd=0.34u
++ ps=0.365u
+m13 9 22 8 VSS nm_hp l=0.118267u w=1.13021u ad=0.489862p as=0.190187p pd=2.02u
++ ps=0.34u
+
+* resistors:
+r14 VSS 2 40 $[mnc]
+r15 Z 3 40 $[mnc]
+r16 VSS 4 40 $[mnc]
+r17 VSS 4 40 $[mnc]
+r18 Z 5 40 $[mnc]
+r19 VSS 6 40 $[mnc]
+r20 VSS 6 40 $[mnc]
+r21 68 9 40 $[mnc]
+r22 VDD 11 40 $[mpc]
+r23 VDD 11 40 $[mpc]
+r24 Z 12 40 $[mpc]
+r25 VDD 13 40 $[mpc]
+r26 VDD 13 40 $[mpc]
+r27 Z 14 40 $[mpc]
+r28 VDD 15 40 $[mpc]
+r29 VDD 15 40 $[mpc]
+r30 68 16 40 $[mpc]
+r31 VDD 17 40 $[mpc]
+r32 VDD 17 40 $[mpc]
+r33 68 18 40 $[mpc]
+r34 68 19 14 $[mpolyc]
+r35 C 20 14 $[mpolyc]
+r36 B 21 14 $[mpolyc]
+r37 A 22 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.860845f
+cp2 2 VSS 0.0647564f
+cp3 3 VSS 0.033657f
+cp4 4 VSS 0.0595684f
+cp5 5 VSS 0.0313281f
+cp6 6 VSS 0.0485204f
+cp7 9 VSS 0.0368949f
+cp8 11 VSS 0.0669228f
+cp9 12 VSS 0.0348794f
+cp10 13 VSS 0.0546883f
+cp11 14 VSS 0.0283784f
+cp12 15 VSS 0.0754251f
+cp13 16 VSS 0.0382087f
+cp14 17 VSS 0.0836821f
+cp15 18 VSS 0.0400116f
+cp16 19 VSS 1.03962f
+cp17 20 VSS 0.579237f
+cp18 21 VSS 0.58947f
+cp19 22 VSS 0.456138f
+cp20 Z VSS 0.47425f
+cp21 68 VSS 0.51157f
+cp22 C VSS 0.122544f
+cp23 B VSS 0.144857f
+cp24 A VSS 0.116581f
+
+.ENDS
+
+
+** and3m8p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and3m8p.iclib2,v 9.0.1.4 2002/06/20 18:52:35 kensz Exp $
+
+.SUBCKT AND3M8P Z A B C VDD VSS
+
+* devices:
+m0 19 33 18 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.632262p pd=0.38u
++ ps=2.405u
+m1 20 33 19 VDD pm_hp l=0.116666u w=1.74521u ad=0.350112p as=0.282187p pd=0.365u
++ ps=0.38u
+m2 21 33 20 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.350112p pd=0.38u
++ ps=0.365u
+m3 22 33 21 VDD pm_hp l=0.116666u w=1.74521u ad=0.350112p as=0.282187p pd=0.365u
++ ps=0.38u
+m4 23 33 22 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.350112p pd=0.38u
++ ps=0.365u
+m5 24 33 23 VDD pm_hp l=0.116666u w=1.74521u ad=0.332687p as=0.282187p pd=0.365u
++ ps=0.38u
+m6 25 34 24 VDD pm_hp l=0.116666u w=1.74521u ad=0.315218p as=0.332687p
++ pd=0.377724u ps=0.365u
+m7 26 35 25 VDD pm_hp l=0.116631u w=1.74314u ad=0.325763p as=0.314844p
++ pd=0.377276u ps=0.377276u
+m8 27 36 26 VDD pm_hp l=0.116666u w=1.74521u ad=0.317037p as=0.32615p pd=0.38u
++ ps=0.377724u
+m9 28 36 27 VDD pm_hp l=0.116666u w=1.74521u ad=0.328087p as=0.317037p pd=0.38u
++ ps=0.38u
+m10 29 37 28 VDD pm_hp l=0.116666u w=1.74521u ad=0.317037p as=0.328087p pd=0.38u
++ ps=0.38u
+m11 30 38 29 VDD pm_hp l=0.116666u w=1.74521u ad=0.332687p as=0.317037p
++ pd=0.365u ps=0.38u
+m12 31 39 30 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.332687p pd=0.38u
++ ps=0.365u
+m13 32 39 31 VDD pm_hp l=0.116666u w=1.74521u ad=0.632262p as=0.282187p
++ pd=2.405u ps=0.38u
+m14 3 33 2 VSS nm_hp l=0.11818u w=1.16021u ad=0.1959p as=0.404112p pd=0.38u
++ ps=1.82u
+m15 4 33 3 VSS nm_hp l=0.11818u w=1.16021u ad=0.226925p as=0.1959p pd=0.38u
++ ps=0.38u
+m16 5 33 4 VSS nm_hp l=0.11818u w=1.16021u ad=0.1959p as=0.226925p pd=0.38u
++ ps=0.38u
+m17 6 33 5 VSS nm_hp l=0.11818u w=1.16021u ad=0.226925p as=0.1959p pd=0.38u
++ ps=0.38u
+m18 7 33 6 VSS nm_hp l=0.11818u w=1.16021u ad=0.1959p as=0.226925p pd=0.38u
++ ps=0.38u
+m19 8 33 7 VSS nm_hp l=0.11818u w=1.16021u ad=0.323862p as=0.1959p pd=0.84u
++ ps=0.38u
+m20 9 34 8 VSS nm_hp l=0.11818u w=1.16021u ad=0.167162p as=0.323862p pd=0.29u
++ ps=0.84u
+m21 10 35 9 VSS nm_hp l=0.11818u w=1.16021u ad=0.1756p as=0.167162p pd=0.305u
++ ps=0.29u
+m22 11 36 10 VSS nm_hp l=0.11818u w=1.16021u ad=0.1959p as=0.1756p pd=0.38u
++ ps=0.305u
+m23 12 36 11 VSS nm_hp l=0.11818u w=1.16021u ad=0.2206p as=0.1959p pd=0.385u
++ ps=0.38u
+m24 13 37 12 VSS nm_hp l=0.11818u w=1.16021u ad=0.14185p as=0.2206p pd=0.245u
++ ps=0.385u
+m25 14 38 13 VSS nm_hp l=0.11818u w=1.16021u ad=0.357612p as=0.14185p pd=0.9u
++ ps=0.245u
+m26 15 39 14 VSS nm_hp l=0.11818u w=1.16021u ad=0.1959p as=0.357612p pd=0.38u
++ ps=0.9u
+m27 16 39 15 VSS nm_hp l=0.11818u w=1.16021u ad=0.404112p as=0.1959p pd=1.82u
++ ps=0.38u
+
+* resistors:
+r28 VSS 2 40 $[mnc]
+r29 VSS 2 40 $[mnc]
+r30 Z 3 40 $[mnc]
+r31 VSS 4 40 $[mnc]
+r32 VSS 4 40 $[mnc]
+r33 Z 5 40 $[mnc]
+r34 VSS 6 40 $[mnc]
+r35 VSS 6 40 $[mnc]
+r36 Z 7 40 $[mnc]
+r37 VSS 8 40 $[mnc]
+r38 VSS 8 40 $[mnc]
+r39 124 11 40 $[mnc]
+r40 VSS 14 40 $[mnc]
+r41 VSS 14 40 $[mnc]
+r42 Z 15 40 $[mnc]
+r43 VSS 16 40 $[mnc]
+r44 VSS 16 40 $[mnc]
+r45 VDD 18 40 $[mpc]
+r46 VDD 18 40 $[mpc]
+r47 Z 19 40 $[mpc]
+r48 VDD 20 40 $[mpc]
+r49 VDD 20 40 $[mpc]
+r50 Z 21 40 $[mpc]
+r51 VDD 22 40 $[mpc]
+r52 VDD 22 40 $[mpc]
+r53 Z 23 40 $[mpc]
+r54 VDD 24 40 $[mpc]
+r55 VDD 24 40 $[mpc]
+r56 124 25 40 $[mpc]
+r57 VDD 26 40 $[mpc]
+r58 VDD 26 40 $[mpc]
+r59 124 27 40 $[mpc]
+r60 VDD 28 40 $[mpc]
+r61 VDD 28 40 $[mpc]
+r62 124 29 40 $[mpc]
+r63 VDD 30 40 $[mpc]
+r64 VDD 30 40 $[mpc]
+r65 Z 31 40 $[mpc]
+r66 VDD 32 40 $[mpc]
+r67 VDD 32 40 $[mpc]
+r68 124 33 14 $[mpolyc]
+r69 C 34 14 $[mpolyc]
+r70 B 35 14 $[mpolyc]
+r71 A 36 14 $[mpolyc]
+r72 B 37 14 $[mpolyc]
+r73 C 38 14 $[mpolyc]
+r74 124 39 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 1.56329f
+cp2 2 VSS 0.066909f
+cp3 3 VSS 0.0329567f
+cp4 4 VSS 0.053738f
+cp5 5 VSS 0.0311139f
+cp6 6 VSS 0.0589038f
+cp7 7 VSS 0.0343163f
+cp8 8 VSS 0.0845744f
+cp9 9 VSS 0.0313892f
+cp10 10 VSS 0.0295062f
+cp11 11 VSS 0.0355657f
+cp12 12 VSS 0.0272432f
+cp13 13 VSS 0.0374993f
+cp14 14 VSS 0.0743539f
+cp15 15 VSS 0.040173f
+cp16 16 VSS 0.0772047f
+cp17 18 VSS 0.0669662f
+cp18 19 VSS 0.0343023f
+cp19 20 VSS 0.0537532f
+cp20 21 VSS 0.0292001f
+cp21 22 VSS 0.0537718f
+cp22 23 VSS 0.02742f
+cp23 24 VSS 0.0961625f
+cp24 25 VSS 0.0541043f
+cp25 26 VSS 0.0806768f
+cp26 27 VSS 0.0474487f
+cp27 28 VSS 0.0809222f
+cp28 29 VSS 0.0503317f
+cp29 30 VSS 0.0980707f
+cp30 31 VSS 0.031499f
+cp31 32 VSS 0.0712853f
+cp32 33 VSS 1.5824f
+cp33 34 VSS 0.702386f
+cp34 35 VSS 0.71486f
+cp35 36 VSS 0.956247f
+cp36 37 VSS 0.736203f
+cp37 38 VSS 0.695164f
+cp38 39 VSS 0.722612f
+cp39 Z VSS 1.54225f
+cp40 124 VSS 1.26666f
+cp41 C VSS 0.572138f
+cp42 B VSS 0.269761f
+cp43 A VSS 0.135527f
+
+.ENDS
+
+
+** and4m05p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and4m05p.iclib2,v 9.0.1.6 2002/07/18 14:39:13 rchiang Exp $
+
+.SUBCKT AND4M05P Z A B C D VDD VSS
+
+* devices:
+m0 10 15 9 VDD pm_hp l=0.117328u w=1.09278u ad=0.200462p as=0.395712p pd=0.395u
++ ps=1.795u
+m1 11 16 10 VDD pm_hp l=0.117328u w=1.09278u ad=0.219162p as=0.200462p pd=0.395u
++ ps=0.395u
+m2 12 17 11 VDD pm_hp l=0.117328u w=1.09278u ad=0.200462p as=0.219162p pd=0.395u
++ ps=0.395u
+m3 13 18 12 VDD pm_hp l=0.117328u w=1.09278u ad=0.244587p as=0.200462p
++ pd=0.48183u ps=0.395u
+m4 14 19 13 VDD pm_hp l=0.117479u w=1.02778u ad=0.420562p as=0.230038p pd=1.86u
++ ps=0.45317u
+m5 3 15 2 VSS nm_hp l=0.119204u w=0.717426u ad=0.112125p as=0.330525p pd=0.32u
++ ps=1.645u
+m6 4 16 3 VSS nm_hp l=0.119204u w=0.717426u ad=0.113737p as=0.112125p pd=0.325u
++ ps=0.32u
+m7 5 17 4 VSS nm_hp l=0.119204u w=0.717426u ad=0.0958125p as=0.113737p pd=0.275u
++ ps=0.325u
+m8 6 18 5 VSS nm_hp l=0.119204u w=0.717426u ad=0.367823p as=0.0958125p
++ pd=1.58982u ps=0.275u
+m9 7 19 6 VSS nm_hp l=0.120619u w=0.670208u ad=0.223637p as=0.343614p pd=1.33u
++ ps=1.48518u
+
+* resistors:
+r10 53 2 40 $[mnc]
+r11 VSS 6 40 $[mnc]
+r12 VSS 6 40 $[mnc]
+r13 Z 7 40 $[mnc]
+r14 VDD 9 40 $[mpc]
+r15 53 10 40 $[mpc]
+r16 VDD 11 40 $[mpc]
+r17 VDD 11 40 $[mpc]
+r18 53 12 40 $[mpc]
+r19 VDD 13 40 $[mpc]
+r20 VDD 13 40 $[mpc]
+r21 Z 14 40 $[mpc]
+r22 A 15 14 $[mpolyc]
+r23 B 16 14 $[mpolyc]
+r24 C 17 14 $[mpolyc]
+r25 D 18 14 $[mpolyc]
+r26 53 19 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.755985f
+cp2 2 VSS 0.0370352f
+cp3 4 VSS 0.00742427f
+cp4 5 VSS 0.00382252f
+cp5 6 VSS 0.0534347f
+cp6 7 VSS 0.0397901f
+cp7 9 VSS 0.0872681f
+cp8 10 VSS 0.0304373f
+cp9 11 VSS 0.0684828f
+cp10 12 VSS 0.0314364f
+cp11 13 VSS 0.0816418f
+cp12 14 VSS 0.0317797f
+cp13 15 VSS 0.372691f
+cp14 16 VSS 0.498733f
+cp15 17 VSS 0.531127f
+cp16 18 VSS 0.519558f
+cp17 19 VSS 0.423686f
+cp18 53 VSS 0.689956f
+cp19 A VSS 0.129825f
+cp20 B VSS 0.129243f
+cp21 C VSS 0.0974697f
+cp22 D VSS 0.122331f
+cp23 Z VSS 0.241547f
+
+.ENDS
+
+
+** and4m1p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and4m1p.iclib2,v 9.0.1.4 2002/06/20 18:49:38 kensz Exp $
+
+.SUBCKT AND4M1P Z A B C D VDD VSS
+
+* devices:
+m0 10 15 9 VDD pm_hp l=0.117032u w=1.43521u ad=0.236462p as=0.511362p pd=0.38u
++ ps=2.095u
+m1 11 16 10 VDD pm_hp l=0.117032u w=1.43521u ad=0.290862p as=0.236462p pd=0.38u
++ ps=0.38u
+m2 12 17 11 VDD pm_hp l=0.117032u w=1.43521u ad=0.281962p as=0.290862p pd=0.445u
++ ps=0.38u
+m3 13 18 12 VDD pm_hp l=0.117032u w=1.43521u ad=0.332148p as=0.281962p
++ pd=0.502483u ps=0.445u
+m4 14 19 13 VDD pm_hp l=0.116675u w=1.73521u ad=0.658962p as=0.401577p pd=2.525u
++ ps=0.607517u
+m5 3 15 2 VSS nm_hp l=0.118972u w=0.935208u ad=0.14375p as=0.380962p pd=0.31u
++ ps=1.765u
+m6 4 16 3 VSS nm_hp l=0.118972u w=0.935208u ad=0.137162p as=0.14375p pd=0.31u
++ ps=0.31u
+m7 5 17 4 VSS nm_hp l=0.118972u w=0.935208u ad=0.129937p as=0.137162p pd=0.31u
++ ps=0.31u
+m8 6 18 5 VSS nm_hp l=0.118972u w=0.935208u ad=0.353809p as=0.129937p
++ pd=1.05134u ps=0.31u
+m9 7 19 6 VSS nm_hp l=0.118194u w=1.15521u ad=0.371562p as=0.43704p pd=1.815u
++ ps=1.29866u
+
+* resistors:
+r10 54 2 40 $[mnc]
+r11 VSS 6 40 $[mnc]
+r12 VSS 6 40 $[mnc]
+r13 Z 7 40 $[mnc]
+r14 VDD 9 40 $[mpc]
+r15 VDD 9 40 $[mpc]
+r16 54 10 40 $[mpc]
+r17 VDD 11 40 $[mpc]
+r18 VDD 11 40 $[mpc]
+r19 54 12 40 $[mpc]
+r20 VDD 13 40 $[mpc]
+r21 VDD 13 40 $[mpc]
+r22 Z 14 40 $[mpc]
+r23 A 15 14 $[mpolyc]
+r24 B 16 14 $[mpolyc]
+r25 C 17 14 $[mpolyc]
+r26 D 18 14 $[mpolyc]
+r27 54 19 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.668808f
+cp2 2 VSS 0.0288445f
+cp3 4 VSS 0.00425421f
+cp4 5 VSS 0.00736845f
+cp5 6 VSS 0.0535487f
+cp6 7 VSS 0.0418897f
+cp7 9 VSS 0.0836126f
+cp8 10 VSS 0.0309527f
+cp9 11 VSS 0.0761958f
+cp10 12 VSS 0.037819f
+cp11 13 VSS 0.0868835f
+cp12 14 VSS 0.031722f
+cp13 15 VSS 0.420047f
+cp14 16 VSS 0.577185f
+cp15 17 VSS 0.564959f
+cp16 18 VSS 0.533858f
+cp17 19 VSS 0.469582f
+cp18 54 VSS 0.656012f
+cp19 A VSS 0.125542f
+cp20 B VSS 0.131007f
+cp21 C VSS 0.0967615f
+cp22 D VSS 0.128138f
+cp23 Z VSS 0.229475f
+
+.ENDS
+
+
+** and4m2p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and4m2p.iclib2,v 9.0.1.4 2002/06/20 19:29:06 kensz Exp $
+
+.SUBCKT AND4M2P Z A B C D VDD VSS
+
+* devices:
+m0 11 17 10 VDD pm_hp l=0.116656u w=1.75521u ad=0.283662p as=0.636162p pd=0.38u
++ ps=2.415u
+m1 12 17 11 VDD pm_hp l=0.116656u w=1.75521u ad=0.364837p as=0.283662p pd=0.38u
++ ps=0.38u
+m2 13 18 12 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.364837p pd=0.38u
++ ps=0.38u
+m3 14 19 13 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m4 15 20 14 VDD pm_hp l=0.116656u w=1.75521u ad=0.460812p as=0.364412p pd=0.585u
++ ps=0.38u
+m5 16 21 15 VDD pm_hp l=0.116656u w=1.75521u ad=0.635312p as=0.460812p pd=2.415u
++ ps=0.585u
+m6 3 17 2 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.408012p pd=0.38u
++ ps=1.83u
+m7 4 17 3 VSS nm_hp l=0.118152u w=1.17021u ad=0.326575p as=0.197375p pd=0.915u
++ ps=0.38u
+m8 5 18 4 VSS nm_hp l=0.118152u w=1.17021u ad=0.2282p as=0.326575p pd=0.395u
++ ps=0.915u
+m9 6 19 5 VSS nm_hp l=0.118152u w=1.17021u ad=0.191312p as=0.2282p pd=0.33u
++ ps=0.395u
+m10 7 20 6 VSS nm_hp l=0.118152u w=1.17021u ad=0.316162p as=0.191312p pd=0.55u
++ ps=0.33u
+m11 8 21 7 VSS nm_hp l=0.118152u w=1.17021u ad=0.376137p as=0.316162p pd=1.83u
++ ps=0.55u
+
+* resistors:
+r12 VSS 2 40 $[mnc]
+r13 VSS 2 40 $[mnc]
+r14 Z 3 40 $[mnc]
+r15 VSS 4 40 $[mnc]
+r16 VSS 4 40 $[mnc]
+r17 63 8 40 $[mnc]
+r18 VDD 10 40 $[mpc]
+r19 VDD 10 40 $[mpc]
+r20 Z 11 40 $[mpc]
+r21 VDD 12 40 $[mpc]
+r22 VDD 12 40 $[mpc]
+r23 63 13 40 $[mpc]
+r24 VDD 14 40 $[mpc]
+r25 VDD 14 40 $[mpc]
+r26 63 15 40 $[mpc]
+r27 VDD 16 40 $[mpc]
+r28 VDD 16 40 $[mpc]
+r29 63 17 14 $[mpolyc]
+r30 D 18 14 $[mpolyc]
+r31 C 19 14 $[mpolyc]
+r32 B 20 14 $[mpolyc]
+r33 A 21 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.805408f
+cp2 2 VSS 0.0744319f
+cp3 3 VSS 0.0381096f
+cp4 4 VSS 0.0484689f
+cp5 8 VSS 0.0295542f
+cp6 10 VSS 0.0668804f
+cp7 11 VSS 0.031473f
+cp8 12 VSS 0.0539689f
+cp9 13 VSS 0.0374769f
+cp10 14 VSS 0.0712234f
+cp11 15 VSS 0.0449856f
+cp12 16 VSS 0.0934304f
+cp13 17 VSS 0.634257f
+cp14 18 VSS 0.612393f
+cp15 19 VSS 0.611031f
+cp16 20 VSS 0.561056f
+cp17 21 VSS 0.380966f
+cp18 Z VSS 0.218002f
+cp19 63 VSS 0.610683f
+cp20 D VSS 0.123016f
+cp21 C VSS 0.139425f
+cp22 B VSS 0.108584f
+cp23 A VSS 0.129863f
+
+.ENDS
+
+
+** and4m4p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and4m4p.iclib2,v 9.0.1.5 2002/06/20 18:50:40 kensz Exp $
+
+.SUBCKT AND4M4P Z A B C D VDD VSS
+
+* devices:
+m0 13 21 12 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.635312p pd=0.38u
++ ps=2.415u
+m1 14 21 13 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m2 15 21 14 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.364412p pd=0.38u
++ ps=0.38u
+m3 16 21 15 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m4 17 22 16 VDD pm_hp l=0.116656u w=1.75521u ad=0.284512p as=0.364412p pd=0.38u
++ ps=0.38u
+m5 18 23 17 VDD pm_hp l=0.116656u w=1.75521u ad=0.364412p as=0.284512p pd=0.38u
++ ps=0.38u
+m6 19 24 18 VDD pm_hp l=0.116656u w=1.75521u ad=0.314612p as=0.364412p pd=0.415u
++ ps=0.38u
+m7 20 25 19 VDD pm_hp l=0.116656u w=1.75521u ad=0.635312p as=0.314612p pd=2.415u
++ ps=0.415u
+m8 3 21 2 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.408012p pd=0.38u
++ ps=1.83u
+m9 4 21 3 VSS nm_hp l=0.118152u w=1.17021u ad=0.22925p as=0.197375p pd=0.38u
++ ps=0.38u
+m10 5 21 4 VSS nm_hp l=0.118152u w=1.17021u ad=0.197375p as=0.22925p pd=0.38u
++ ps=0.38u
+m11 6 21 5 VSS nm_hp l=0.118152u w=1.17021u ad=0.322087p as=0.197375p pd=0.9u
++ ps=0.38u
+m12 7 22 6 VSS nm_hp l=0.118152u w=1.17021u ad=0.1374p as=0.322087p pd=0.235u
++ ps=0.9u
+m13 8 23 7 VSS nm_hp l=0.118152u w=1.17021u ad=0.28495p as=0.1374p pd=0.495u
++ ps=0.235u
+m14 9 24 8 VSS nm_hp l=0.118152u w=1.17021u ad=0.219687p as=0.28495p pd=0.38u
++ ps=0.495u
+m15 10 25 9 VSS nm_hp l=0.118152u w=1.17021u ad=0.376137p as=0.219687p pd=1.83u
++ ps=0.38u
+
+* resistors:
+r16 VSS 2 40 $[mnc]
+r17 VSS 2 40 $[mnc]
+r18 Z 3 40 $[mnc]
+r19 VSS 4 40 $[mnc]
+r20 VSS 4 40 $[mnc]
+r21 Z 5 40 $[mnc]
+r22 VSS 6 40 $[mnc]
+r23 VSS 6 40 $[mnc]
+r24 77 10 40 $[mnc]
+r25 VDD 12 40 $[mpc]
+r26 VDD 12 40 $[mpc]
+r27 Z 13 40 $[mpc]
+r28 VDD 14 40 $[mpc]
+r29 VDD 14 40 $[mpc]
+r30 Z 15 40 $[mpc]
+r31 VDD 16 40 $[mpc]
+r32 VDD 16 40 $[mpc]
+r33 77 17 40 $[mpc]
+r34 VDD 18 40 $[mpc]
+r35 VDD 18 40 $[mpc]
+r36 77 19 40 $[mpc]
+r37 VDD 20 40 $[mpc]
+r38 VDD 20 40 $[mpc]
+r39 77 21 14 $[mpolyc]
+r40 D 22 14 $[mpolyc]
+r41 C 23 14 $[mpolyc]
+r42 B 24 14 $[mpolyc]
+r43 A 25 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 0.976713f
+cp2 2 VSS 0.0669337f
+cp3 3 VSS 0.0399503f
+cp4 4 VSS 0.0728176f
+cp5 5 VSS 0.0326792f
+cp6 6 VSS 0.0483475f
+cp7 10 VSS 0.0296893f
+cp8 12 VSS 0.0669337f
+cp9 13 VSS 0.0426534f
+cp10 14 VSS 0.0697763f
+cp11 15 VSS 0.0259259f
+cp12 16 VSS 0.0741454f
+cp13 17 VSS 0.0296032f
+cp14 18 VSS 0.0731667f
+cp15 19 VSS 0.0321976f
+cp16 20 VSS 0.0917249f
+cp17 21 VSS 1.04403f
+cp18 22 VSS 0.671622f
+cp19 23 VSS 0.660961f
+cp20 24 VSS 0.596943f
+cp21 25 VSS 0.452201f
+cp22 Z VSS 0.481297f
+cp23 77 VSS 0.70876f
+cp24 D VSS 0.103867f
+cp25 C VSS 0.129789f
+cp26 B VSS 0.102416f
+cp27 A VSS 0.133726f
+
+.ENDS
+
+
+** and4m8p.lpe extracted by xCalibre v9.1_1.1 **
+
+** Version: $LSILogic: and4m8p.iclib2,v 9.0.1.4 2002/06/20 18:50:20 kensz Exp $
+
+.SUBCKT AND4M8P Z A B C D VDD VSS
+
+* devices:
+m0 22 39 21 VDD pm_hp l=0.116481u w=1.96021u ad=0.39465p as=0.654612p pd=0.38u
++ ps=2.64u
+m1 23 39 22 VDD pm_hp l=0.116481u w=1.96021u ad=0.332175p as=0.39465p pd=0.38u
++ ps=0.38u
+m2 24 40 23 VDD pm_hp l=0.116481u w=1.96021u ad=0.39465p as=0.332175p pd=0.38u
++ ps=0.38u
+m3 25 40 24 VDD pm_hp l=0.116481u w=1.96021u ad=0.635362p as=0.39465p pd=2.62u
++ ps=0.38u
+m4 27 41 26 VDD pm_hp l=0.116666u w=1.74521u ad=0.585712p as=0.632262p pd=0.735u
++ ps=2.405u
+m5 28 42 27 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.585712p pd=0.38u
++ ps=0.735u
+m6 29 42 28 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.362937p pd=0.38u
++ ps=0.38u
+m7 30 43 29 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.282187p pd=0.38u
++ ps=0.38u
+m8 31 44 30 VDD pm_hp l=0.116666u w=1.74521u ad=0.329212p as=0.362937p pd=0.435u
++ ps=0.38u
+m9 32 44 31 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.329212p pd=0.38u
++ ps=0.435u
+m10 33 44 32 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.362937p pd=0.38u
++ ps=0.38u
+m11 34 45 33 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.282187p pd=0.38u
++ ps=0.38u
+m12 35 45 34 VDD pm_hp l=0.116666u w=1.74521u ad=0.333487p as=0.362937p pd=0.44u
++ ps=0.38u
+m13 36 45 35 VDD pm_hp l=0.116666u w=1.74521u ad=0.362937p as=0.333487p pd=0.38u
++ ps=0.44u
+m14 37 46 36 VDD pm_hp l=0.116666u w=1.74521u ad=0.282187p as=0.362937p pd=0.38u
++ ps=0.38u
+m15 38 46 37 VDD pm_hp l=0.116666u w=1.74521u ad=0.632262p as=0.282187p
++ pd=2.405u ps=0.38u
+m16 3 39 2 VSS nm_hp l=0.117796u w=1.31521u ad=0.311262p as=0.573362p pd=0.49u
++ ps=2.145u
+m17 4 39 3 VSS nm_hp l=0.117796u w=1.31521u ad=0.241272p as=0.311262p
++ pd=0.411295u ps=0.49u
+m18 5 40 4 VSS nm_hp l=0.117616u w=1.30692u ad=0.262162p as=0.239753p pd=0.385u
++ ps=0.408705u
+m19 6 40 5 VSS nm_hp l=0.117616u w=1.30692u ad=0.438262p as=0.262162p pd=1.995u
++ ps=0.385u
+m20 8 41 7 VSS nm_hp l=0.118209u w=1.15021u ad=0.194061p as=0.604862p
++ pd=0.376355u ps=2.86u
+m21 9 42 8 VSS nm_hp l=0.118004u w=1.14192u ad=0.225037p as=0.192664p pd=0.385u
++ ps=0.373645u
+m22 10 42 9 VSS nm_hp l=0.118004u w=1.14192u ad=0.264877p as=0.225037p
++ pd=0.503175u ps=0.385u
+m23 11 43 10 VSS nm_hp l=0.118209u w=1.15021u ad=0.241325p as=0.266798p pd=0.41u
++ ps=0.506825u
+m24 12 44 11 VSS nm_hp l=0.118209u w=1.15021u ad=0.194425p as=0.241325p pd=0.38u
++ ps=0.41u
+m25 13 44 12 VSS nm_hp l=0.118209u w=1.15021u ad=0.2246p as=0.194425p pd=0.38u
++ ps=0.38u
+m26 14 44 13 VSS nm_hp l=0.118209u w=1.15021u ad=0.194425p as=0.2246p pd=0.38u
++ ps=0.38u
+m27 15 45 14 VSS nm_hp l=0.118209u w=1.15021u ad=0.2246p as=0.194425p pd=0.38u
++ ps=0.38u
+m28 16 45 15 VSS nm_hp l=0.118209u w=1.15021u ad=0.21115p as=0.2246p pd=0.41u
++ ps=0.38u
+m29 17 45 16 VSS nm_hp l=0.118209u w=1.15021u ad=0.2246p as=0.21115p pd=0.38u
++ ps=0.41u
+m30 18 46 17 VSS nm_hp l=0.118209u w=1.15021u ad=0.194425p as=0.2246p pd=0.38u
++ ps=0.38u
+m31 19 46 18 VSS nm_hp l=0.118209u w=1.15021u ad=0.400212p as=0.194425p pd=1.81u
++ ps=0.38u
+
+* resistors:
+r32 152 2 40 $[mnc]
+r33 151 3 40 $[mnc]
+r34 152 4 40 $[mnc]
+r35 154 5 40 $[mnc]
+r36 152 6 40 $[mnc]
+r37 VSS 7 40 $[mnc]
+r38 VSS 7 40 $[mnc]
+r39 157 8 40 $[mnc]
+r40 154 9 40 $[mnc]
+r41 157 10 40 $[mnc]
+r42 VSS 11 40 $[mnc]
+r43 VSS 11 40 $[mnc]
+r44 Z 12 40 $[mnc]
+r45 VSS 13 40 $[mnc]
+r46 VSS 13 40 $[mnc]
+r47 Z 14 40 $[mnc]
+r48 VSS 15 40 $[mnc]
+r49 VSS 15 40 $[mnc]
+r50 Z 16 40 $[mnc]
+r51 VSS 17 40 $[mnc]
+r52 VSS 17 40 $[mnc]
+r53 Z 18 40 $[mnc]
+r54 VSS 19 40 $[mnc]
+r55 151 21 40 $[mpc]
+r56 VDD 22 40 $[mpc]
+r57 VDD 22 40 $[mpc]
+r58 151 23 40 $[mpc]
+r59 VDD 24 40 $[mpc]
+r60 VDD 24 40 $[mpc]
+r61 151 25 40 $[mpc]
+r62 VDD 26 40 $[mpc]
+r63 VDD 26 40 $[mpc]
+r64 151 27 40 $[mpc]
+r65 VDD 28 40 $[mpc]
+r66 VDD 28 40 $[mpc]
+r67 151 29 40 $[mpc]
+r68 VDD 30 40 $[mpc]
+r69 VDD 30 40 $[mpc]
+r70 Z 31 40 $[mpc]
+r71 VDD 32 40 $[mpc]
+r72 VDD 32 40 $[mpc]
+r73 Z 33 40 $[mpc]
+r74 VDD 34 40 $[mpc]
+r75 VDD 34 40 $[mpc]
+r76 Z 35 40 $[mpc]
+r77 VDD 36 40 $[mpc]
+r78 VDD 36 40 $[mpc]
+r79 Z 37 40 $[mpc]
+r80 VDD 38 40 $[mpc]
+r81 VDD 38 40 $[mpc]
+r82 A 39 14 $[mpolyc]
+r83 B 40 14 $[mpolyc]
+r84 D 41 14 $[mpolyc]
+r85 C 42 14 $[mpolyc]
+r86 D 43 14 $[mpolyc]
+r87 151 44 14 $[mpolyc]
+r88 151 45 14 $[mpolyc]
+r89 151 46 14 $[mpolyc]
+
+* lumped capacitances:
+cp1 VDD VSS 1.88539f
+cp2 2 VSS 0.0733921f
+cp3 3 VSS 0.0517399f
+cp4 4 VSS 0.0595972f
+cp5 5 VSS 0.0403998f
+cp6 6 VSS 0.0411972f
+cp7 7 VSS 0.0727517f
+cp8 8 VSS 0.0360192f
+cp9 9 VSS 0.0387512f
+cp10 10 VSS 0.0267839f
+cp11 11 VSS 0.0602358f
+cp12 12 VSS 0.0316335f
+cp13 13 VSS 0.0654892f
+cp14 14 VSS 0.0334395f
+cp15 15 VSS 0.0682219f
+cp16 16 VSS 0.0355611f
+cp17 17 VSS 0.0650075f
+cp18 18 VSS 0.036368f
+cp19 19 VSS 0.0690729f
+cp20 21 VSS 0.0413738f
+cp21 22 VSS 0.0846182f
+cp22 23 VSS 0.0502937f
+cp23 24 VSS 0.0756185f
+cp24 25 VSS 0.0362481f
+cp25 26 VSS 0.0774668f
+cp26 27 VSS 0.0627529f
+cp27 28 VSS 0.0728926f
+cp28 29 VSS 0.034799f
+cp29 30 VSS 0.0750678f
+cp30 31 VSS 0.0310642f
+cp31 32 VSS 0.0710903f
+cp32 33 VSS 0.0312666f
+cp33 34 VSS 0.0711433f
+cp34 35 VSS 0.0351933f
+cp35 36 VSS 0.0703017f
+cp36 37 VSS 0.0367407f
+cp37 38 VSS 0.0712393f
+cp38 39 VSS 0.714853f
+cp39 40 VSS 0.715523f
+cp40 41 VSS 0.470212f
+cp41 42 VSS 0.769196f
+cp42 43 VSS 0.580036f
+cp43 44 VSS 1.04419f
+cp44 45 VSS 1.06122f
+cp45 46 VSS 0.703884f
+cp46 151 VSS 1.43567f
+cp47 152 VSS 0.454536f
+cp48 A VSS 0.123952f
+cp49 154 VSS 0.35775f
+cp50 B VSS 0.106251f
+cp51 D VSS 0.379062f
+cp52 157 VSS 0.224034f
+cp53 C VSS 0.133522f
+cp54 Z VSS 1.09684f
+
+.ENDS
+
+
diff --git a/spiceparser/xcircspice.c b/spiceparser/xcircspice.c
new file mode 100644
index 0000000..0dcc335
--- /dev/null
+++ b/spiceparser/xcircspice.c
@@ -0,0 +1,153 @@
+/* xcircspice.c --- implements routine ReadSpice() for xcircuit
+ * SPICE import.
+ * Conrad Ziesler, Tim Edwards
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "debug.h"
+#include "scanner.h"
+#include "netlist_spice.h"
+
+#define fprintf tcl_printf
+
+/*--------------------------------------------------------------*/
+/* Get the node name from a node structure */
+/*--------------------------------------------------------------*/
+
+char *node(node_t n)
+{
+ char *p;
+ p=n->str;
+ return p;
+}
+
+/*--------------------------------------------------------------*/
+/* Make a pass through the internal representation of the */
+/* SPICE input file and translate to the internal */
+/* representation of the SPAR ASG code. */
+/*--------------------------------------------------------------*/
+
+void generate_asg(spice_t *spice)
+{
+ subckt_t *ckt = NULL, **cktpp;
+ list_t subckts;
+ int i, j;
+ int uniq = 1;
+
+ /* Iterate over all subcircuits */
+ subckts = spice_list_subckt(spice->ckt);
+ list_iterate(&subckts, i, cktpp) {
+ ckt = *cktpp;
+
+do_ckt:
+ assert(ckt != NULL);
+ fprintf(stdout, "spiceparser: cell(%i) is \"%s\"\n", i, ckt->name);
+
+ for (j = 0; j < ckt->ndefn; j++) {
+ char *nn;
+ nn = ckt->defn[j]->str;
+ fprintf(stdout, "pin: %s\n",nn);
+ }
+
+ /* Loop through circuit MOSFET devices */
+ /* (to be done---use model information to determine if this is a */
+ /* pMOS or nMOS device). */
+
+ for (j = 0; j < ckt->nm; j++) {
+
+ /* For now, ignoring substrate node ckt->m[j].nodes[3] */
+ /* We should have two devices; if substrate is VDD or GND, */
+ /* then use the 3-terminal device; otherwise, use the 4- */
+ /* terminal device. */
+
+ AddNTermModule(ckt->m[j].deck->card->str, "MSFET", 4,
+ "D", node(ckt->m[j].nodes[0]),
+ "G", node(ckt->m[j].nodes[1]),
+ "S", node(ckt->m[j].nodes[2]),
+ "B", node(ckt->m[j].nodes[3]));
+ }
+
+ /* Loop through circuit capacitor devices */
+ for(j = 0; j < ckt->nc; j++) {
+ AddNTermModule(ckt->c[j].deck->card->str, "CAPC", 2,
+ "1", node(ckt->c[j].nodes[0]),
+ "2", node(ckt->c[j].nodes[1]));
+ }
+
+ /* Loop through circuit resistor devices */
+ for (j = 0; j < ckt->nr; j++)
+ {
+ AddNTermModule(ckt->r[j].deck->card->str, "RESTR", 2,
+ "1", node(ckt->r[j].nodes[0]),
+ "2", node(ckt->r[j].nodes[1]));
+ }
+
+ /* Loop through circuit inductor devices */
+ for (j = 0; j < ckt->nl; j++)
+ {
+ AddNTermModule(ckt->l[j].deck->card->str, "INDR", 2,
+ "1", node(ckt->l[j].nodes[0]),
+ "2", node(ckt->l[j].nodes[1]));
+ }
+
+ /* Loop through circuit voltage sources */
+ for (j = 0; j < ckt->nv; j++)
+ {
+ AddNTermModule(ckt->v[j].deck->card->str, "VAMP", 2,
+ "1", node(ckt->v[j].nodes[0]),
+ "2", node(ckt->v[j].nodes[1]));
+ }
+
+ /* Loop through circuit current sources */
+ for (j = 0; j < ckt->ni; j++)
+ {
+ AddNTermModule(ckt->i[j].deck->card->str, "IAMP", 2,
+ "1", node(ckt->i[j].nodes[0]),
+ "2", node(ckt->i[j].nodes[1]));
+ }
+
+ /* Loop through circuit subcircuit calls, where those */
+ /* calls are not defined within the file and are assumed */
+ /* to be primitives (this may require more checking---may */
+ /* need to remove the x[] records when they are expanded */
+
+ for (j = 0; j < ckt->nx; j++)
+ {
+ AddNTermModule(ckt->x[j].deck->card->str,
+ ckt->x[j].rest->str, 0);
+
+ for (i = 0; i < ckt->x[j].nn; i++)
+ AddModuleTerm(ckt->x[j].rest->str, node(ckt->x[j].nodes[i]), i,
+ ckt->x[j].nn);
+ }
+
+ }
+
+ /* kludge for getting the top-level circuit */
+ if (ckt == spice->ckt) return;
+ else {
+ ckt = spice->ckt;
+ goto do_ckt;
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Top-level call used in xcircuit (files.c) to read in a SPICE */
+/* file. */
+/*--------------------------------------------------------------*/
+
+int ReadSpice(FILE *fp)
+{
+ scanner_t scan;
+ spice_t *spice;
+
+ scanner_init(&scan);
+ scanner_input_newfp(&scan, fp);
+ spice = spice_new(&scan);
+ generate_asg(spice);
+ spice_release(spice);
+ return 0;
+}
+
diff --git a/svg.c b/svg.c
new file mode 100644
index 0000000..78ac70c
--- /dev/null
+++ b/svg.c
@@ -0,0 +1,1132 @@
+/*----------------------------------------------------------------------*/
+/* svg.c */
+/* Copyright (c) 2009 Tim Edwards, Open Circuit Design */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef XC_WIN32
+#include <unistd.h>
+#endif
+#include <math.h>
+#include <limits.h>
+#include <sys/stat.h>
+#ifndef XC_WIN32
+#include <sys/wait.h>
+#else
+#include <process.h>
+#endif
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifndef HAVE_VFORK
+#define vfork fork
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+void SVGDrawString(labelptr, int, objinstptr);
+
+/*----------------------------------------------------------------------*/
+/* External Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern Pixmap STIPPLE[8];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern int *appcolors;
+extern colorindex *colorlist;
+extern int number_colors;
+extern fontinfo *fonts;
+extern short fontcount;
+
+/*----------------------------------------------------------------------*/
+/* The output file is a global variable used by all routines. */
+/*----------------------------------------------------------------------*/
+
+FILE *svgf;
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+void svg_printcolor(int passcolor, char *prefix)
+{
+ int i;
+ if (passcolor != DEFAULTCOLOR) {
+ for (i = 0; i < number_colors; i++) {
+ if (colorlist[i].color.pixel == passcolor) break;
+ }
+ if (i < number_colors) {
+ fprintf(svgf, "%s\"#%02x%02x%02x\" ",
+ prefix,
+ (colorlist[i].color.red >> 8),
+ (colorlist[i].color.green >> 8),
+ (colorlist[i].color.blue >> 8));
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Since we can't do stipples in SVG, and since the whole stipple thing */
+/* was only put in because we can't (easily) do transparency effects */
+/* in X11, we convert stipples to transparency when the stipple is a */
+/* mask, and do a color blend with white when the stipple is opaque. */
+/* */
+/* Blend amount is 1 (almost original color) to 7 (almost white) */
+/*----------------------------------------------------------------------*/
+
+void svg_blendcolor(int passcolor, char *prefix, int amount)
+{
+ int i, bred, bgreen, bblue;
+
+ if (passcolor != DEFAULTCOLOR) {
+ for (i = 0; i < number_colors; i++) {
+ if (colorlist[i].color.pixel == passcolor) break;
+ }
+ if (i < number_colors) {
+ bred = colorlist[i].color.red >> 8;
+ bgreen = colorlist[i].color.green >> 8;
+ bblue = colorlist[i].color.blue >> 8;
+ }
+ }
+ else {
+ bred = bgreen = bblue = 0;
+ }
+ bred = ((bred * amount) + (255 * (8 - amount))) >> 3;
+ bgreen = ((bgreen * amount) + (255 * (8 - amount))) >> 3;
+ bblue = ((bblue * amount) + (255 * (8 - amount))) >> 3;
+
+ fprintf(svgf, "%s\"#%02x%02x%02x\" ", prefix, bred, bgreen, bblue);
+}
+
+/*----------------------------------------------------------------------*/
+/* Fill and/or draw a border around an element */
+/*----------------------------------------------------------------------*/
+
+void svg_stroke(int passcolor, short style, float width)
+{
+ float tmpwidth;
+ short minwidth, solidpart, shade;
+
+ tmpwidth = UTopTransScale(xobjs.pagelist[areawin->page]->wirewidth * width);
+ minwidth = max(1, (short)tmpwidth);
+
+ if (style & FILLED || (!(style & FILLED) && style & OPAQUE)) {
+ if ((style & FILLSOLID) == FILLSOLID) {
+ svg_printcolor(passcolor, "fill=");
+ }
+ else if (!(style & FILLED)) {
+ fprintf(svgf, "fill=\"white\" ");
+ }
+ else {
+ shade = 1 + ((style & FILLSOLID) >> 5);
+ if (style & OPAQUE) {
+ svg_blendcolor(passcolor, "fill=", shade);
+ }
+ else {
+ svg_printcolor(passcolor, "fill=");
+ fprintf(svgf, "fill-opacity=\"%g\" ", (float)shade / 8);
+ }
+ }
+ }
+ else
+ fprintf(svgf, "fill=\"none\" ");
+
+ if (!(style & NOBORDER)) {
+ /* set up dots or dashes */
+ if (style & DASHED) solidpart = 4 * minwidth;
+ else if (style & DOTTED) solidpart = minwidth;
+ if (style & (DASHED | DOTTED)) {
+ fprintf(svgf, "style=\"stroke-dasharray:%d,%d\" ", solidpart, 4 * minwidth);
+
+ fprintf(svgf, "stroke-width=\"%g\" ", tmpwidth);
+ fprintf(svgf, "stroke-linecap=\"butt\" ");
+ if (style & SQUARECAP)
+ fprintf(svgf, "stroke-linejoin=\"miter\" ");
+ else
+ fprintf(svgf, "stroke-linejoin=\"bevel\" ");
+ }
+ else {
+ fprintf(svgf, "stroke-width=\"%g\" ", tmpwidth);
+ if (style & SQUARECAP) {
+ fprintf(svgf, "stroke-linejoin=\"miter\" ");
+ fprintf(svgf, "stroke-linecap=\"projecting\" ");
+ }
+ else {
+ fprintf(svgf, "stroke-linejoin=\"bevel\" ");
+ fprintf(svgf, "stroke-linecap=\"round\" ");
+ }
+ }
+ svg_printcolor(passcolor, "stroke=");
+ }
+ else
+ fprintf(svgf, "stroke=\"none\" ");
+ fprintf(svgf, "/>\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* Finish a path and fill and/or stroke */
+/*----------------------------------------------------------------------*/
+
+void svg_strokepath(int passcolor, short style, float width)
+{
+ /* Finish the path, closing if necessary */
+ if (!(style & UNCLOSED))
+ fprintf(svgf, "z\" ");
+ else
+ fprintf(svgf, "\" ");
+
+ svg_stroke(passcolor, style, width);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGCreateImages(int page)
+{
+ Imagedata *img;
+ int i, x, y;
+ short *glist;
+ FILE *ppf;
+ union {
+ u_char b[4];
+ u_long i;
+ } pixel;
+ char *fname, outname[128], *pptr;
+#ifndef XC_WIN32
+ pid_t pid;
+#endif
+
+ /* Check which images are used on this page */
+ glist = (short *)malloc(xobjs.images * sizeof(short));
+ for (i = 0; i < xobjs.images; i++) glist[i] = 0;
+ count_graphics(xobjs.pagelist[page]->pageinst->thisobject, glist);
+
+ for (i = 0; i < xobjs.images; i++) {
+ if (glist[i] == 0) continue;
+ img = xobjs.imagelist + i;
+
+ /* Generate a PPM file, then convert it to PNG */
+
+ fname = tmpnam(NULL);
+ ppf = fopen(fname, "w");
+ if (ppf != NULL) {
+ fprintf(ppf, "P6 %d %d 255\n", img->image->width, img->image->height);
+ for (y = 0; y < img->image->height; y++) {
+ for (x = 0; x < img->image->width; x++) {
+ pixel.i = XGetPixel(img->image, x, y);
+ fwrite(&pixel.b[2], 1, 1, ppf);
+ fwrite(&pixel.b[1], 1, 1, ppf);
+ fwrite(&pixel.b[0], 1, 1, ppf);
+ }
+ }
+ }
+ fclose(ppf);
+
+ /* Run "convert" to make this into a png file */
+
+ strcpy(outname, img->filename);
+ if ((pptr = strrchr(outname, '.')) != NULL)
+ strcpy(pptr, ".png");
+ else
+ strcat(outname, ".png");
+
+#ifndef XC_WIN32
+ if ((pid = vfork()) == 0) {
+ execlp("convert", "convert", fname, outname, NULL);
+ exit(0); /* not reached */
+ }
+ waitpid(pid, NULL, 0);
+ unlink(fname);
+#else
+ _spawnl(_P_WAIT, GM_EXEC, GM_EXEC, "convert", fname, outname, NULL);
+ _unlink(fname);
+#endif
+ Fprintf(stdout, "Generated standalone PNG image file %s\n", outname);
+ }
+ free(glist);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGDrawGraphic(graphicptr gp)
+{
+ XPoint ppt, corner;
+ Imagedata *img;
+ int i;
+ char outname[128], *pptr;
+ float tscale;
+ int rotation;
+
+ for (i = 0; i < xobjs.images; i++) {
+ img = xobjs.imagelist + i;
+ if (img->image == gp->source)
+ break;
+ }
+ if (i == xobjs.images) return;
+
+ strcpy(outname, img->filename);
+ if ((pptr = strrchr(outname, '.')) != NULL)
+ strcpy(pptr, ".png");
+ else
+ strcat(outname, ".png");
+
+ UPushCTM();
+ UPreMultCTM(DCTM, gp->position, gp->scale, gp->rotation);
+ corner.x = -(gp->source->width >> 1);
+ corner.y = (gp->source->height >> 1);
+ UTransformbyCTM(DCTM, &corner, &ppt, 1);
+ UPopCTM();
+
+ tscale = gp->scale * UTopScale();
+ rotation = gp->rotation + UTopRotation();
+ if (rotation >= 360) rotation -= 360;
+ else if (rotation < 0) rotation += 360;
+
+ fprintf(svgf, "<image transform=\"translate(%d,%d) scale(%g) rotate(%d)\"\n",
+ ppt.x, ppt.y, tscale, rotation);
+ fprintf(svgf, " width=\"%dpx\" height=\"%dpx\"",
+ gp->source->width, gp->source->height);
+ fprintf(svgf, " xlink:href=\"%s\">\n", outname);
+ fprintf(svgf, "</image>\n");
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGDrawSpline(splineptr thespline, int passcolor)
+{
+ XPoint tmppoints[4];
+
+ UTransformbyCTM(DCTM, thespline->ctrl, tmppoints, 4);
+
+ fprintf(svgf, "<path d=\"M%d,%d C%d,%d %d,%d %d,%d ",
+ tmppoints[0].x, tmppoints[0].y,
+ tmppoints[1].x, tmppoints[1].y,
+ tmppoints[2].x, tmppoints[2].y,
+ tmppoints[3].x, tmppoints[3].y);
+ svg_strokepath(passcolor, thespline->style, thespline->width);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGDrawPolygon(polyptr thepoly, int passcolor)
+{
+ int i;
+ XPoint *tmppoints = (pointlist) malloc(thepoly->number * sizeof(XPoint));
+
+ UTransformbyCTM(DCTM, thepoly->points, tmppoints, thepoly->number);
+
+ fprintf(svgf, "<path ");
+ if (thepoly->style & BBOX) fprintf(svgf, "visibility=\"hidden\" ");
+ fprintf(svgf, "d=\"M%d,%d L", tmppoints[0].x, tmppoints[0].y);
+ for (i = 1; i < thepoly->number; i++) {
+ fprintf(svgf, "%d,%d ", tmppoints[i].x, tmppoints[i].y);
+ }
+
+ svg_strokepath(passcolor, thepoly->style, thepoly->width);
+ free(tmppoints);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGDrawArc(arcptr thearc, int passcolor)
+{
+ XPoint endpoints[2];
+ int radius[2];
+ int tarc;
+
+ radius[0] = UTopTransScale(thearc->radius);
+ radius[1] = UTopTransScale(thearc->yaxis);
+
+ tarc = (thearc->angle2 - thearc->angle1);
+ if (tarc == 360) {
+ UTransformbyCTM(DCTM, &(thearc->position), endpoints, 1);
+ fprintf(svgf, "<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" ",
+ endpoints[0].x, endpoints[0].y, radius[0], radius[1]);
+ svg_stroke(passcolor, thearc->style, thearc->width);
+ }
+ else {
+ UfTransformbyCTM(DCTM, thearc->points, endpoints, 1);
+ UfTransformbyCTM(DCTM, thearc->points + thearc->number - 1, endpoints + 1, 1);
+
+ /* When any arc is flipped, the direction of travel reverses. */
+ fprintf(svgf, "<path d=\"M%d,%d A%d,%d 0 %d,%d %d,%d ",
+ endpoints[0].x, endpoints[0].y,
+ radius[0], radius[1],
+ ((tarc > 180) ? 1 : 0),
+ (((DCTM->a * DCTM->e) >= 0) ? 1 : 0),
+ endpoints[1].x, endpoints[1].y);
+ svg_strokepath(passcolor, thearc->style, thearc->width);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+void SVGDrawPath(pathptr thepath, int passcolor)
+{
+ XPoint *tmppoints = (pointlist) malloc(sizeof(XPoint));
+ genericptr *genpath;
+ polyptr thepoly;
+ splineptr thespline;
+ int i, firstpt = 1;
+
+ fprintf(svgf, "<path d=\"");
+
+ for (genpath = thepath->plist; genpath < thepath->plist + thepath->parts;
+ genpath++) {
+ switch(ELEMENTTYPE(*genpath)) {
+ case POLYGON:
+ thepoly = TOPOLY(genpath);
+ tmppoints = (pointlist) realloc(tmppoints, thepoly->number * sizeof(XPoint));
+ UTransformbyCTM(DCTM, thepoly->points, tmppoints, thepoly->number);
+ if (firstpt) {
+ fprintf(svgf, "M%d,%d ", tmppoints[0].x, tmppoints[0].y);
+ firstpt = 0;
+ }
+ fprintf(svgf, "L");
+ for (i = 1; i < thepoly->number; i++) {
+ fprintf(svgf, "%d,%d ", tmppoints[i].x, tmppoints[i].y);
+ }
+ break;
+ case SPLINE:
+ thespline = TOSPLINE(genpath);
+ tmppoints = (pointlist) realloc(tmppoints, 4 * sizeof(XPoint));
+ UTransformbyCTM(DCTM, thespline->ctrl, tmppoints, 4);
+ if (firstpt) {
+ fprintf(svgf, "M%d,%d ", tmppoints[0].x, tmppoints[0].y);
+ firstpt = 0;
+ }
+ fprintf(svgf, "C%d,%d %d,%d %d,%d ",
+ tmppoints[1].x, tmppoints[1].y,
+ tmppoints[2].x, tmppoints[2].y,
+ tmppoints[3].x, tmppoints[3].y);
+ break;
+ }
+ }
+ svg_strokepath(passcolor, thepath->style, thepath->width);
+ free(tmppoints);
+}
+
+/*----------------------------------------------------------------------*/
+/* Main recursive object instance drawing routine. */
+/* context is the instance information passed down from above */
+/* theinstance is the object instance to be drawn */
+/* level is the level of recursion */
+/* passcolor is the inherited color value passed to object */
+/*----------------------------------------------------------------------*/
+
+void SVGDrawObject(objinstptr theinstance, short level, int passcolor, pushlistptr *stack)
+{
+ genericptr *areagen;
+ float tmpwidth;
+ int defaultcolor = passcolor;
+ int curcolor = passcolor;
+ int thispart;
+ objectptr theobject = theinstance->thisobject;
+
+ /* All parts are given in the coordinate system of the object, unless */
+ /* this is the top-level object, in which they will be interpreted as */
+ /* relative to the screen. */
+
+ UPushCTM();
+
+ if (stack) push_stack(stack, theinstance, NULL);
+ if (level != 0)
+ UPreMultCTM(DCTM, theinstance->position, theinstance->scale,
+ theinstance->rotation);
+
+ /* make parameter substitutions */
+ psubstitute(theinstance);
+
+ /* draw all of the elements */
+
+ tmpwidth = UTopTransScale(xobjs.pagelist[areawin->page]->wirewidth);
+
+ /* Here---set a default style using "g" like PostScript "gsave" */
+ /* stroke-width = tmpwidth, stroke = passcolor */
+
+ /* guard against plist being regenerated during a redraw by the */
+ /* expression parameter mechanism (should that be prohibited?) */
+
+ for (thispart = 0; thispart < theobject->parts; thispart++) {
+ areagen = theobject->plist + thispart;
+ if ((*areagen)->type & DRAW_HIDE) continue;
+
+ if (defaultcolor != DOFORALL) {
+ if ((*areagen)->color != curcolor) {
+ if ((*areagen)->color == DEFAULTCOLOR)
+ curcolor = defaultcolor;
+ else
+ curcolor = (*areagen)->color;
+ }
+ }
+
+ switch(ELEMENTTYPE(*areagen)) {
+ case(POLYGON):
+ if (level == 0 || !((TOPOLY(areagen))->style & BBOX))
+ SVGDrawPolygon(TOPOLY(areagen), curcolor);
+ break;
+
+ case(SPLINE):
+ SVGDrawSpline(TOSPLINE(areagen), curcolor);
+ break;
+
+ case(ARC):
+ SVGDrawArc(TOARC(areagen), curcolor);
+ break;
+
+ case(PATH):
+ SVGDrawPath(TOPATH(areagen), curcolor);
+ break;
+
+ case(GRAPHIC):
+ SVGDrawGraphic(TOGRAPHIC(areagen));
+ break;
+
+ case(OBJINST):
+ if (areawin->editinplace && stack && (TOOBJINST(areagen)
+ == areawin->topinstance)) {
+ /* If stack matches areawin->stack, then don't */
+ /* draw because it would be redundant. */
+ pushlistptr alist = *stack, blist = areawin->stack;
+ while (alist && blist) {
+ if (alist->thisinst != blist->thisinst) break;
+ alist = alist->next;
+ blist = blist->next;
+ }
+ if ((!alist) || (!blist)) break;
+ }
+ SVGDrawObject(TOOBJINST(areagen), level + 1, curcolor, stack);
+ break;
+
+ case(LABEL):
+ if (level == 0 || TOLABEL(areagen)->pin == False ||
+ (TOLABEL(areagen)->justify & PINVISIBLE))
+ SVGDrawString(TOLABEL(areagen), curcolor, theinstance);
+ break;
+ }
+ }
+
+ UPopCTM();
+ if (stack) pop_stack(stack);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define addlinepoint(pointlist, numvals, xval, yval) \
+{ if (!numvals) pointlist = (XPoint *)malloc(sizeof(XPoint)); \
+ else pointlist = (XPoint *)realloc(pointlist, (numvals + 1) * sizeof(XPoint)); \
+ pointlist[numvals].x = xval; \
+ pointlist[numvals++].y = -yval; \
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw an entire string, including parameter substitutions */
+/*----------------------------------------------------------------------*/
+
+void SVGDrawString(labelptr drawlabel, int passcolor, objinstptr localinst)
+{
+ stringpart *strptr;
+ char *textptr;
+ short fstyle, ffont, tmpjust, baseline, deltay;
+ int pos, defaultcolor, curcolor, scolor;
+ short oldx, oldfont, oldstyle;
+ int olinerise = 4;
+ float tmpscale = 1.0, natscale = 1.0;
+ XPoint newpoint;
+ TextExtents tmpext;
+ short *tabstops = NULL;
+ short tabno, numtabs = 0, group = 0;
+ int open_text, open_span, open_decor;
+ XPoint *decorations = NULL;
+ short nvals = 0;
+
+ char *symbol_html_encoding[] = {
+ " ", "!", "&#8704;", "#", "&#8707;", "%", "&", "?", "(", ")",
+ "*", "+", ",", "&#8722;", ".", "/", "0", "1", "2", "3", "4",
+ "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "&#8773;",
+ "&#913;", "&#914;", "&#935;", "&#916;", "&#917;", "&#934;",
+ "&#915;", "&#919;", "&#921;", "&#977;", "&#922;", "&#923;",
+ "&#924;", "&#925;", "&#927;", "&#928;", "&#920;", "&#929;",
+ "&#931;", "&#932;", "&#933;", "&#963;", "&#937;", "&#926;",
+ "&#936;", "&#918;", "[", "&#8756;", "]", "&#8869;", "_",
+ "&#8254;", "&#945;", "&#946;", "&#967;", "&#948;", "&#949;",
+ "&#966;", "&#947;", "&#951;", "&#953;", "&#966;", "&#954;",
+ "&#955;", "&#956;", "&#957;", "&#959;", "&#960;", "&#952;",
+ "&#961;", "&#963;", "&#964;", "&#965;", "&#969;", "&#969;",
+ "&#958;", "&#968;", "&#950;", "{", "|", "}", "~", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "&#978;", "&#8242;", "&#8804;", "&#8260;", "&#8734;", "&#402;",
+ "&#9827;", "&#9830;", "&#9829;", "&#9824;", "&#8596;",
+ "&#8592;", "&#8593;", "&#8594;", "&#8595;", "&#176;", "&#177;",
+ "&#8243;", "&#8805;", "&#215;", "&#8733;", "&#8706;", "&#8226;",
+ "&#247;", "&#8800;", "&#8801;", "&#8773;", "&#8230;"
+ };
+
+ /* Standard encoding vector, in HTML, from character 161 to 255 */
+ u_int standard_html_encoding[] = {
+ 161, 162, 163, 8725, 165, 131, 167, 164, 146, 147, 171, 8249,
+ 8250, 64256, 64258, 0, 8211, 8224, 8225, 183, 0, 182, 8226,
+ 8218, 8222, 8221, 187, 8230, 8240, 0, 191, 0, 96, 180, 710,
+ 126, 713, 728, 729, 168, 0, 730, 184, 0, 733, 731, 711, 8212,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 508, 0,
+ 170, 0, 0, 0, 0, 321, 216, 338, 186, 0, 0, 0, 0, 0, 230, 0,
+ 0, 0, 185, 0, 0, 322, 248, 339, 223};
+
+ if (fontcount == 0) return;
+
+ /* Don't draw temporary labels from schematic capture system */
+ if (drawlabel->string->type != FONT_NAME) return;
+
+ if (passcolor == DOSUBSTRING)
+ defaultcolor = curcolor = drawlabel->color;
+ else
+ defaultcolor = curcolor = passcolor;
+
+ if (defaultcolor != DOFORALL) {
+ if (drawlabel->color != DEFAULTCOLOR)
+ curcolor = drawlabel->color;
+ else
+ curcolor = defaultcolor;
+ }
+
+ /* calculate the transformation matrix for this object */
+ /* in natural units of the alphabet vectors */
+ /* (conversion to window units) */
+
+ /* Labels don't rotate in Firefox, so use <g> record for transform */
+
+ UPushCTM();
+ UPreMultCTM(DCTM, drawlabel->position, drawlabel->scale, drawlabel->rotation);
+
+ /* check for flip invariance; recompute CTM and justification if necessary */
+ tmpjust = flipadjust(drawlabel->justify);
+
+ /* Note that the Y-scale is inverted or text comes out upside-down. But we */
+ /* need to adjust to the Y baseline. */
+
+ fprintf(svgf, "<g transform=\"matrix(%4g %4g %4g %4g %3g %3g)\" ",
+ DCTM->a, DCTM->d, -(DCTM->b), -(DCTM->e), DCTM->c, DCTM->f);
+
+ svg_printcolor(passcolor, "fill=");
+ fprintf(svgf, ">\n");
+
+ /* "natural" (unscaled) length */
+ tmpext = ULength(drawlabel, localinst, 0, NULL);
+
+ newpoint.x = (tmpjust & NOTLEFT ?
+ (tmpjust & RIGHT ? -tmpext.maxwidth : -tmpext.maxwidth >> 1) : 0);
+ newpoint.y = (tmpjust & NOTBOTTOM ?
+ (tmpjust & TOP ? -tmpext.ascent : -(tmpext.ascent + tmpext.base) >> 1)
+ : -tmpext.base);
+
+ /* Pinlabels have an additional offset spacing to pad */
+ /* them from the circuit point to which they attach. */
+
+ if (drawlabel->pin) {
+ pinadjust(tmpjust, &(newpoint.x), &(newpoint.y), 1);
+ }
+
+ oldx = newpoint.x;
+ baseline = newpoint.y;
+
+ open_text = -1;
+ open_span = 0;
+ open_decor = 0;
+ pos = 0;
+ for (strptr = drawlabel->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+
+ /* All segments other than text cancel any */
+ /* existing overline/underline in effect. */
+
+ if (strptr->type != TEXT_STRING)
+ fstyle &= 0xfc7;
+
+ switch(strptr->type) {
+ case RETURN:
+ while (open_span > 0) {
+ fprintf(svgf, "</tspan>");
+ open_span--;
+ }
+ while (open_text > 0) {
+ fprintf(svgf, "</text>");
+ open_text--;
+ }
+ if (open_decor) {
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ open_decor--;
+ }
+ break;
+
+ case FONT_SCALE:
+ case FONT_NAME:
+ while (open_span > 0) {
+ fprintf(svgf, "</tspan>");
+ open_span--;
+ }
+ while (open_text > 0) {
+ fprintf(svgf, "</text>");
+ open_text--;
+ }
+ if (open_decor) {
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ open_decor--;
+ }
+ break;
+
+ case KERN:
+ case TABFORWARD:
+ case TABBACKWARD:
+ case TABSTOP:
+ case HALFSPACE:
+ case QTRSPACE:
+ case NOLINE:
+ case UNDERLINE:
+ case OVERLINE:
+ case SUBSCRIPT:
+ case SUPERSCRIPT:
+ case NORMALSCRIPT:
+ while (open_span > 1) {
+ fprintf(svgf, "</tspan>");
+ open_span--;
+ }
+ if (open_decor) {
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ open_decor--;
+ }
+ break;
+
+ /* These do not need to be handled */
+ case TEXT_STRING:
+ case PARAM_START:
+ case PARAM_END:
+ break;
+
+ /* These are not handled yet, but should be */
+ case FONT_COLOR:
+ break;
+
+ default:
+ break;
+ }
+
+ /* deal with each text segment type */
+
+ switch(strptr->type) {
+ case FONT_SCALE:
+ case FONT_NAME:
+ if (strptr->data.font < fontcount) {
+ ffont = strptr->data.font;
+ fstyle = 0; /* style reset by font change */
+ if (baseline == newpoint.y) { /* set top-level font and style */
+ oldfont = ffont;
+ oldstyle = fstyle;
+ }
+ }
+ fprintf(svgf, "<text stroke=\"none\" ");
+ fprintf(svgf, "font-family=");
+ if (issymbolfont(ffont))
+ fprintf(svgf, "\"Times\" ");
+ else if (!strncmp(fonts[ffont].family, "Times", 5))
+ fprintf(svgf, "\"Times\" ");
+ else
+ fprintf(svgf, "\"%s\" ", fonts[ffont].family);
+
+ if (fonts[ffont].flags & 0x1)
+ fprintf(svgf, " font-weight=\"bold\" ");
+ if (fonts[ffont].flags & 0x2) {
+ if (issansfont(ffont))
+ fprintf(svgf, " font-style=\"oblique\" ");
+ else
+ fprintf(svgf, " font-style=\"italic\" ");
+ }
+ olinerise = (issansfont(ffont)) ? 7 : 4;
+
+ if (strptr->type == FONT_SCALE) {
+ tmpscale = natscale * strptr->data.scale;
+ if (baseline == newpoint.y) /* reset top-level scale */
+ natscale = tmpscale;
+ }
+ else
+ tmpscale = 1;
+
+ /* Actual scale taken care of by transformation matrix */
+ fprintf(svgf, "font-size=\"%g\" >", tmpscale * 40);
+ fprintf(svgf, "<tspan x=\"%d\" y=\"%d\">", newpoint.x, -newpoint.y);
+ open_text++;
+ open_span++;
+ break;
+
+ case KERN:
+ newpoint.x += strptr->data.kern[0];
+ newpoint.y += strptr->data.kern[1];
+ fprintf(svgf, "<text dx=\"%d\" dy=\"%d\">",
+ strptr->data.kern[0], strptr->data.kern[1]);
+ open_text++;
+ break;
+
+ case FONT_COLOR:
+ if (defaultcolor != DOFORALL) {
+ if (strptr->data.color != DEFAULTCOLOR)
+ curcolor = colorlist[strptr->data.color].color.pixel;
+ else {
+ curcolor = DEFAULTCOLOR;
+ }
+ }
+ break;
+
+ case TABBACKWARD: /* find first tab value with x < xtotal */
+ for (tabno = numtabs - 1; tabno >= 0; tabno--) {
+ if (tabstops[tabno] < newpoint.x) {
+ newpoint.x = tabstops[tabno];
+ break;
+ }
+ }
+ fprintf(svgf, "<tspan x=\"%d\">", newpoint.x);
+ open_span++;
+ break;
+
+ case TABFORWARD: /* find first tab value with x > xtotal */
+ for (tabno = 0; tabno < numtabs; tabno++) {
+ if (tabstops[tabno] > newpoint.x) {
+ newpoint.x = tabstops[tabno];
+ break;
+ }
+ }
+ fprintf(svgf, "<tspan x=\"%d\">", newpoint.x);
+ open_span++;
+ break;
+
+ case TABSTOP:
+ numtabs++;
+ if (tabstops == NULL) tabstops = (short *)malloc(sizeof(short));
+ else tabstops = (short *)realloc(tabstops, numtabs * sizeof(short));
+ tabstops[numtabs - 1] = newpoint.x;
+ /* Force a tab at this point so that the output aligns */
+ /* to our computation of the position, not its own. */
+ fprintf(svgf, "<tspan x=\"%d\">", newpoint.x);
+ open_span++;
+ break;
+
+ case RETURN:
+ tmpscale = natscale = 1.0;
+ baseline -= BASELINE;
+ newpoint.y = baseline;
+ newpoint.x = oldx;
+ fprintf(svgf, "<tspan x=\"%d\" y=\"%d\">", newpoint.x, -newpoint.y);
+ open_span++;
+ break;
+
+ case SUBSCRIPT:
+ natscale *= SUBSCALE;
+ tmpscale = natscale;
+ deltay = (short)((TEXTHEIGHT >> 1) * natscale);
+ newpoint.y -= deltay;
+ fprintf(svgf, "<tspan dy=\"%d\" font-size=\"%g\">", deltay,
+ 40 * natscale);
+ open_span++;
+ break;
+
+ case SUPERSCRIPT:
+ natscale *= SUBSCALE;
+ tmpscale = natscale;
+ deltay = (short)(TEXTHEIGHT * natscale);
+ newpoint.y += deltay;
+ fprintf(svgf, "<tspan dy=\"%d\" font-size=\"%g\">", -deltay,
+ 40 * natscale);
+ open_span++;
+ break;
+
+ case NORMALSCRIPT:
+ tmpscale = natscale = 1.0;
+ ffont = oldfont; /* revert to top-level font and style */
+ fstyle = oldstyle;
+ newpoint.y = baseline;
+ fprintf(svgf, "<tspan y=\"%d\">", baseline);
+ open_span++;
+ break;
+
+ case UNDERLINE:
+ fstyle |= 8;
+ group = newpoint.y - 6;
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ open_decor++;
+ break;
+
+ case OVERLINE:
+ if (strptr->nextpart != NULL && strptr->nextpart->type == TEXT_STRING) {
+ objectptr charptr;
+ int tmpheight;
+
+ group = 0;
+ for (textptr = strptr->nextpart->data.string;
+ textptr && *textptr != '\0'; textptr++) {
+ charptr = fonts[ffont].encoding[*(u_char *)textptr];
+ tmpheight = (int)((float)charptr->bbox.height
+ * fonts[ffont].scale);
+ if (group < tmpheight) group = (short)tmpheight;
+ }
+ fstyle |= 16;
+ group += olinerise + newpoint.y;
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ }
+ open_decor++;
+ break;
+
+ case NOLINE:
+ break;
+
+ case HALFSPACE: case QTRSPACE: {
+ short addx;
+ objectptr drawchar = fonts[ffont].encoding[(u_char)32];
+ addx = (drawchar->bbox.lowerleft.x + drawchar->bbox.width) *
+ fonts[ffont].scale;
+ addx >>= ((strptr->type == HALFSPACE) ? 1 : 2);
+ newpoint.x += addx;
+ fprintf(svgf, "<tspan dx=\"%d\">", addx);
+ open_span++;
+
+ } break;
+
+ case TEXT_STRING:
+ textptr = strptr->data.string;
+
+ if (issymbolfont(ffont)) {
+ for (; *textptr != '\0'; textptr++)
+ if (((u_char)(*textptr) >= 32) && ((u_char)(*textptr) < 158))
+ fprintf(svgf, "%s", symbol_html_encoding[(*textptr) - 32]);
+ }
+ else {
+ /* Handle "&" and non-ASCII characters in the text */
+ if (isisolatin1(ffont)) {
+ for (; *textptr != '\0'; textptr++) {
+ if (*textptr == '&')
+ fprintf(svgf, "&amp;");
+ else if ((u_char)(*textptr) >= 128)
+ fprintf(svgf, "&#%d;", (int)((u_char)*textptr));
+ else if ((u_char)(*textptr) >= 32)
+ fprintf(svgf, "%c", *textptr);
+ }
+ }
+ else {
+ for (; *textptr != '\0'; textptr++) {
+ if (*textptr == '&')
+ fprintf(svgf, "&amp;");
+ else if ((u_char)(*textptr) >= 161)
+ fprintf(svgf, "&#%d;",
+ standard_html_encoding[(u_char)(*textptr)
+ - 161]);
+ else if ((u_char)(*textptr) >= 32 && (u_char)(*textptr) < 161)
+ fprintf(svgf, "%c", *textptr);
+ }
+ }
+ }
+ pos--;
+
+ /* Compute the new X position */
+
+ for (textptr = strptr->data.string; *textptr != '\0'; textptr++) {
+ objectptr drawchar = fonts[ffont].encoding[(u_char)(*textptr)];
+ short addx = (drawchar->bbox.lowerleft.x + drawchar->bbox.width) *
+ fonts[ffont].scale;
+ newpoint.x += addx;
+ }
+ break;
+ }
+ pos++;
+ }
+ while (open_span > 0) {
+ fprintf(svgf, "</tspan>");
+ open_span--;
+ }
+ while (open_text > 0) {
+ fprintf(svgf, "</text>");
+ open_text--;
+ }
+ fprintf(svgf, "\n</text>");
+
+ UPopCTM();
+
+ if (tabstops != NULL) free(tabstops);
+
+ /* If there were decorations (underlines, overlines), generate them */
+
+ if (decorations != NULL) {
+ int i;
+ if (open_decor) {
+ addlinepoint(decorations, nvals, newpoint.x, group);
+ }
+ for (i = 0; i < nvals; i += 2) {
+ fprintf(svgf, "\n<line stroke-width=\"2\" stroke-linecap=\"square\" "
+ "x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" />",
+ decorations[i].x, decorations[i].y, decorations[i + 1].x,
+ decorations[i + 1].y);
+ }
+ free(decorations);
+ }
+ fprintf(svgf, "</g>\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* Write the SVG file output */
+/*----------------------------------------------------------------------*/
+
+#define PMARGIN 6 /* Pixel margin around drawing */
+
+void
+OutputSVG(char *filename, Boolean fullscale)
+{
+ short savesel;
+ objinstptr pinst;
+ int cstyle;
+ float outwidth, outheight, cscale;
+
+ svgf = fopen(filename, "w");
+ if (svgf == NULL) {
+ Fprintf(stderr, "Cannot open file %s for writing.\n", filename);
+ return;
+ }
+
+ /* Generate external image files, if necessary */
+ SVGCreateImages(areawin->page);
+
+ /* Save the number of selections and set it to zero while we do the */
+ /* object drawing. */
+
+ savesel = areawin->selects;
+ areawin->selects = 0;
+ pinst = xobjs.pagelist[areawin->page]->pageinst;
+
+ UPushCTM(); /* Save the top-level graphics state */
+
+ /* This is like UMakeWCTM()---it inverts the whole picture so that */
+ /* The origin is at the top left, and all data points fit in a box */
+ /* at (0, 0) to the object (width, height) */
+
+ DCTM->a = 1.0;
+ DCTM->b = 0.0;
+ DCTM->c = -pinst->bbox.lowerleft.x;
+ DCTM->d = 0.0;
+ DCTM->e = -1.0;
+ DCTM->f = pinst->bbox.lowerleft.y + pinst->bbox.height;
+
+ fprintf(svgf, "<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
+ fprintf(svgf, " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n");
+ fprintf(svgf, " version=\"1.1\"\n");
+ fprintf(svgf, " id=\"%s\" ", pinst->thisobject->name);
+
+ if (fullscale) {
+ fprintf(svgf, "width=\"100%%\" height=\"100%%\" ");
+ }
+ else {
+ cscale = getpsscale(xobjs.pagelist[areawin->page]->outscale, areawin->page);
+ cstyle = xobjs.pagelist[areawin->page]->coordstyle;
+
+ outwidth = toplevelwidth(pinst, NULL) * cscale;
+ outwidth /= (cstyle == CM) ? IN_CM_CONVERT : 72.0;
+ outheight = toplevelheight(pinst, NULL) * cscale;
+ outheight /= (cstyle == CM) ? IN_CM_CONVERT : 72.0;
+
+ /* Set display height to that specified in the output properties (in inches) */
+ fprintf(svgf, "width=\"%.3g%s\" height=\"%.3g%s\" ",
+ outwidth, (cstyle == CM) ? "cm" : "in",
+ outheight, (cstyle == CM) ? "cm" : "in");
+ }
+ fprintf(svgf, " viewBox=\"%d %d %d %d\">\n",
+ -PMARGIN, -PMARGIN, pinst->bbox.width + PMARGIN,
+ pinst->bbox.height + PMARGIN);
+
+ fprintf(svgf, "<desc>\n");
+ fprintf(svgf, "XCircuit Version %2.1f\n", PROG_VERSION);
+ fprintf(svgf, "File \"%s\" Page %d\n", xobjs.pagelist[areawin->page]->filename,
+ areawin->page + 1);
+ fprintf(svgf, "</desc>\n");
+
+ /* Set default color to black */
+ fprintf(svgf, "<g stroke=\"black\">\n");
+
+ if (areawin->hierstack) free_stack(&areawin->hierstack);
+ SVGDrawObject(areawin->topinstance, TOPLEVEL, FOREGROUND, &areawin->hierstack);
+ if (areawin->hierstack) free_stack(&areawin->hierstack);
+
+ /* restore the selection list (if any) */
+ areawin->selects = savesel;
+
+ fprintf(svgf, "</g>\n</svg>\n");
+ fclose(svgf);
+
+ UPopCTM(); /* Restore the top-level graphics state */
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* The TCL command-line for the SVG file write routine. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_svg(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char filename[128], *pptr;
+ Boolean fullscale = 0;
+ int locobjc = objc;
+ char *lastarg;
+
+ /* Argument "-full" forces full scale (not scaled per page output settings) */
+ if (objc > 1) {
+ lastarg = Tcl_GetString(objv[objc - 1]);
+ if (lastarg[0] == '-') {
+ if (!strncmp(lastarg + 1, "full", 4))
+ fullscale = 1;
+ else {
+ Tcl_SetResult(interp, "Unknown option.\n", NULL);
+ return TCL_ERROR;
+ }
+ locobjc--;
+ }
+ }
+
+
+ if (locobjc >= 2) {
+ /* If there is a non-option argument, use it for the output filename */
+ sprintf(filename, Tcl_GetString(objv[1]));
+ }
+ else if (xobjs.pagelist[areawin->page]->pageinst->thisobject->name == NULL)
+ sprintf(filename, xobjs.pagelist[areawin->page]->filename);
+ else
+ sprintf(filename, xobjs.pagelist[areawin->page]->pageinst->thisobject->name);
+
+ pptr = strrchr(filename, '.');
+ if (pptr != NULL)
+ sprintf(pptr + 1, "svg");
+ else if (strcmp(filename + strlen(filename) - 3, "svg"))
+ strcat(filename, ".svg");
+
+ OutputSVG(filename, fullscale);
+ Fprintf(stdout, "Saved page as SVG format file \"%s\"\n", filename);
+ return XcTagCallback(interp, objc, objv);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*-------------------------------------------------------------------------*/
diff --git a/symbol.map b/symbol.map
new file mode 100644
index 0000000..c05a43a
--- /dev/null
+++ b/symbol.map
@@ -0,0 +1,4 @@
+XCIRCUIT_3.8 {
+ global: Xcircuit_Init;
+ local: *;
+};
diff --git a/tclxcircuit.c b/tclxcircuit.c
new file mode 100644
index 0000000..2c192bd
--- /dev/null
+++ b/tclxcircuit.c
@@ -0,0 +1,10154 @@
+/*--------------------------------------------------------------*/
+/* tclxcircuit.c: */
+/* Tcl routines for xcircuit command-line functions */
+/* Copyright (c) 2003 Tim Edwards, Johns Hopkins University */
+/* Copyright (c) 2004 Tim Edwards, MultiGiG, Inc. */
+/*--------------------------------------------------------------*/
+
+#if defined(TCL_WRAPPER) && !defined(HAVE_PYTHON)
+
+#include <stdio.h>
+#include <stdarg.h> /* for va_copy() */
+#include <stdlib.h> /* for atoi() and others */
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <tk.h>
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+#ifdef OPENGL
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif /* OPENGL */
+
+#include "xcircuit.h"
+#include "colordefs.h"
+#include "menudep.h"
+#include "prototypes.h"
+
+Tcl_HashTable XcTagTable;
+
+extern Tcl_Interp *xcinterp;
+extern Tcl_Interp *consoleinterp;
+extern Display *dpy;
+extern Colormap cmap;
+extern Pixmap STIPPLE[STIPPLES]; /* Polygon fill-style stipple patterns */
+extern char _STR[150], _STR2[250];
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern int number_colors;
+extern int *appcolors;
+extern colorindex *colorlist;
+extern Cursor appcursors[NUM_CURSORS];
+extern ApplicationData appdata;
+extern fontinfo *fonts;
+extern short fontcount;
+extern u_char param_select[];
+extern keybinding *keylist;
+extern Boolean spice_end;
+extern short flstart;
+extern int pressmode;
+extern u_char undo_collect;
+
+#ifdef OPENGL
+GLXContext grXcontext;
+XVisualInfo *grVisualInfo;
+float gl_line_limit, gl_point_limit;
+#endif /* OPENGL */
+
+char STIPDATA[STIPPLES][4] = {
+ "\000\004\000\001",
+ "\000\005\000\012",
+ "\001\012\005\010",
+ "\005\012\005\012",
+ "\016\005\012\007",
+ "\017\012\017\005",
+ "\017\012\017\016",
+ "\000\000\000\000"
+};
+
+short flags = -1;
+
+#define LIBOVERRIDE 1
+#define LIBLOADED 2
+#define COLOROVERRIDE 4
+#define FONTOVERRIDE 8
+#define KEYOVERRIDE 16
+
+/*-----------------------*/
+/* Tcl 8.4 compatibility */
+/*-----------------------*/
+
+#ifndef CONST84
+#define CONST84
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Deal with systems which don't define va_copy(). */
+/*----------------------------------------------------------------------*/
+
+#ifndef HAVE_VA_COPY
+ #ifdef HAVE___VA_COPY
+ #define va_copy(a, b) __va_copy(a, b)
+ #else
+ #define va_copy(a, b) a = b
+ #endif
+#endif
+
+#ifdef ASG
+ extern int SetDebugLevel(int *level);
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Reimplement strdup() to use Tcl_Alloc(). */
+/* Note that "strdup" is defined as "Tcl_Strdup" in xcircuit.h. */
+/*----------------------------------------------------------------------*/
+
+char *Tcl_Strdup(const char *s)
+{
+ char *snew;
+ int slen;
+
+ slen = 1 + strlen(s);
+ snew = Tcl_Alloc(slen);
+ if (snew != NULL)
+ memcpy(snew, s, slen);
+
+ return snew;
+}
+
+/*----------------------------------------------------------------------*/
+/* Reimplement vfprintf() as a call to Tcl_Eval(). */
+/*----------------------------------------------------------------------*/
+
+void tcl_vprintf(FILE *f, const char *fmt, va_list args_in)
+{
+ va_list args;
+ static char outstr[128] = "puts -nonewline std";
+ char *outptr, *bigstr = NULL, *finalstr = NULL;
+ int i, nchars, result, escapes = 0;
+
+ /* If we are printing an error message, we want to bring attention */
+ /* to it by mapping the console window and raising it, as necessary. */
+ /* I'd rather do this internally than by Tcl_Eval(), but I can't */
+ /* find the right window ID to map! */
+
+ if ((f == stderr) && (consoleinterp != xcinterp)) {
+ Tk_Window tkwind;
+ tkwind = Tk_MainWindow(consoleinterp);
+ if ((tkwind != NULL) && (!Tk_IsMapped(tkwind)))
+ result = Tcl_Eval(consoleinterp, "wm deiconify .\n");
+ result = Tcl_Eval(consoleinterp, "raise .\n");
+ }
+
+ strcpy (outstr + 19, (f == stderr) ? "err \"" : "out \"");
+ outptr = outstr;
+
+ /* This mess circumvents problems with systems which do not have */
+ /* va_copy() defined. Some define __va_copy(); otherwise we must */
+ /* assume that args = args_in is valid. */
+
+ va_copy(args, args_in);
+ nchars = vsnprintf(outptr + 24, 102, fmt, args);
+ va_end(args);
+
+ if (nchars >= 102) {
+ va_copy(args, args_in);
+ bigstr = Tcl_Alloc(nchars + 26);
+ strncpy(bigstr, outptr, 24);
+ outptr = bigstr;
+ vsnprintf(outptr + 24, nchars + 2, fmt, args);
+ va_end(args);
+ }
+ else if (nchars == -1) nchars = 126;
+
+ for (i = 24; *(outptr + i) != '\0'; i++) {
+ if (*(outptr + i) == '\"' || *(outptr + i) == '[' ||
+ *(outptr + i) == ']' || *(outptr + i) == '\\')
+ escapes++;
+ }
+
+ if (escapes > 0) {
+ finalstr = Tcl_Alloc(nchars + escapes + 26);
+ strncpy(finalstr, outptr, 24);
+ escapes = 0;
+ for (i = 24; *(outptr + i) != '\0'; i++) {
+ if (*(outptr + i) == '\"' || *(outptr + i) == '[' ||
+ *(outptr + i) == ']' || *(outptr + i) == '\\') {
+ *(finalstr + i + escapes) = '\\';
+ escapes++;
+ }
+ *(finalstr + i + escapes) = *(outptr + i);
+ }
+ outptr = finalstr;
+ }
+
+ *(outptr + 24 + nchars + escapes) = '\"';
+ *(outptr + 25 + nchars + escapes) = '\0';
+
+ result = Tcl_Eval(consoleinterp, outptr);
+
+ if (bigstr != NULL) Tcl_Free(bigstr);
+ if (finalstr != NULL) Tcl_Free(finalstr);
+}
+
+/*------------------------------------------------------*/
+/* Console output flushing which goes along with the */
+/* routine tcl_vprintf() above. */
+/*------------------------------------------------------*/
+
+void tcl_stdflush(FILE *f)
+{
+ Tcl_SavedResult state;
+ static char stdstr[] = "::flush stdxxx";
+ char *stdptr = stdstr + 11;
+
+ if ((f != stderr) && (f != stdout)) {
+ fflush(f);
+ }
+ else {
+ Tcl_SaveResult(xcinterp, &state);
+ strcpy(stdptr, (f == stderr) ? "err" : "out");
+ Tcl_Eval(xcinterp, stdstr);
+ Tcl_RestoreResult(xcinterp, &state);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Reimplement fprintf() as a call to Tcl_Eval(). */
+/* Make sure that files (not stdout or stderr) get treated normally. */
+/*----------------------------------------------------------------------*/
+
+void tcl_printf(FILE *f, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if ((f != stderr) && (f != stdout))
+ vfprintf(f, format, ap);
+ else
+ tcl_vprintf(f, format, ap);
+ va_end(ap);
+}
+
+/*----------------------------------------------------------------------*/
+/* Fill in standard areas of a key event structure. This includes */
+/* everything necessary except type, keycode, and state (although */
+/* state defaults to zero). This is also good for button events, which */
+/* share the same structure as key events (except that keycode is */
+/* changed to button). */
+/*----------------------------------------------------------------------*/
+
+void make_new_event(XKeyEvent *event)
+{
+ XPoint newpos, wpoint;
+
+ newpos = UGetCursorPos();
+ user_to_window(newpos, &wpoint);
+ event->x = wpoint.x;
+ event->y = wpoint.y;
+
+ event->same_screen = TRUE;
+ event->send_event = TRUE;
+ event->display = dpy;
+ event->window = Tk_WindowId(areawin->area);
+
+ event->state = 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Implement tag callbacks on functions */
+/* Find any tags associated with a command and execute them. */
+/*----------------------------------------------------------------------*/
+
+int XcTagCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
+{
+ int objidx, result = TCL_OK;
+ char *postcmd, *substcmd, *newcmd, *sptr, *sres;
+ char *croot = Tcl_GetString(objv[0]);
+ Tcl_HashEntry *entry;
+ Tcl_SavedResult state;
+ int reset = FALSE;
+ int i, llen;
+
+ /* Skip over technology qualifier, if any */
+
+ if (!strncmp(croot, "::", 2)) croot += 2;
+ if (!strncmp(croot, "xcircuit::", 10)) croot += 10;
+
+ entry = Tcl_FindHashEntry(&XcTagTable, croot);
+ postcmd = (entry) ? (char *)Tcl_GetHashValue(entry) : NULL;
+
+ if (postcmd)
+ {
+ substcmd = (char *)Tcl_Alloc(strlen(postcmd) + 1);
+ strcpy(substcmd, postcmd);
+ sptr = substcmd;
+
+ /*--------------------------------------------------------------*/
+ /* Parse "postcmd" for Tk-substitution escapes */
+ /* Allowed escapes are: */
+ /* %W substitute the tk path of the calling window */
+ /* %r substitute the previous Tcl result string */
+ /* %R substitute the previous Tcl result string and */
+ /* reset the Tcl result. */
+ /* %[0-5] substitute the argument to the original command */
+ /* %N substitute all arguments as a list */
+ /* %% substitute a single percent character */
+ /* %# substitute the number of arguments passed */
+ /* %* (all others) no action: print as-is. */
+ /*--------------------------------------------------------------*/
+
+ while ((sptr = strchr(sptr, '%')) != NULL)
+ {
+ switch (*(sptr + 1))
+ {
+ case 'W': {
+ char *tkpath = NULL;
+ Tk_Window tkwind = Tk_MainWindow(interp);
+ if (tkwind != NULL) tkpath = Tk_PathName(tkwind);
+ if (tkpath == NULL)
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd));
+ else
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd) + strlen(tkpath));
+
+ strcpy(newcmd, substcmd);
+
+ if (tkpath == NULL)
+ strcpy(newcmd + (int)(sptr - substcmd), sptr + 2);
+ else
+ {
+ strcpy(newcmd + (int)(sptr - substcmd), tkpath);
+ strcat(newcmd, sptr + 2);
+ }
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ } break;
+
+ case 'R':
+ reset = TRUE;
+ case 'r':
+ sres = (char *)Tcl_GetStringResult(interp);
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd)
+ + strlen(sres) + 1);
+ strcpy(newcmd, substcmd);
+ sprintf(newcmd + (int)(sptr - substcmd), "\"%s\"", sres);
+ strcat(newcmd, sptr + 2);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ break;
+
+ case '#':
+ if (objc < 100) {
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd) + 3);
+ strcpy(newcmd, substcmd);
+ sprintf(newcmd + (int)(sptr - substcmd), "%d", objc);
+ strcat(newcmd, sptr + 2);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ objidx = (int)(*(sptr + 1) - '0');
+ if ((objidx >= 0) && (objidx < objc))
+ {
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd)
+ + strlen(Tcl_GetString(objv[objidx])) + 1);
+ strcpy(newcmd, substcmd);
+ strcpy(newcmd + (int)(sptr - substcmd),
+ Tcl_GetString(objv[objidx]));
+ strcat(newcmd, sptr + 2);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ }
+ else if (objidx >= objc)
+ {
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd) + 1);
+ strcpy(newcmd, substcmd);
+ strcpy(newcmd + (int)(sptr - substcmd), sptr + 2);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ }
+ else sptr++;
+ break;
+
+ case 'N':
+ llen = 1;
+ for (i = 1; i < objc; i++)
+ llen += (1 + strlen(Tcl_GetString(objv[i])));
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd) + llen);
+ strcpy(newcmd, substcmd);
+ strcpy(newcmd + (int)(sptr - substcmd), "{");
+ for (i = 1; i < objc; i++) {
+ strcat(newcmd, Tcl_GetString(objv[i]));
+ if (i < (objc - 1))
+ strcat(newcmd, " ");
+ }
+ strcat(newcmd, "}");
+ strcat(newcmd, sptr + 2);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ break;
+
+ case '%':
+ newcmd = (char *)Tcl_Alloc(strlen(substcmd) + 1);
+ strcpy(newcmd, substcmd);
+ strcpy(newcmd + (int)(sptr - substcmd), sptr + 1);
+ Tcl_Free(substcmd);
+ substcmd = newcmd;
+ sptr = substcmd;
+ break;
+
+ default:
+ sptr++;
+ break;
+ }
+ }
+
+ /* Fprintf(stderr, "Substituted tag callback is \"%s\"\n", substcmd); */
+ /* Flush(stderr); */
+
+ Tcl_SaveResult(interp, &state);
+ result = Tcl_Eval(interp, substcmd);
+ if ((result == TCL_OK) && (reset == FALSE))
+ Tcl_RestoreResult(interp, &state);
+ else
+ Tcl_DiscardResult(&state);
+
+ Tcl_Free(substcmd);
+ }
+ return result;
+}
+
+/*--------------------------------------------------------------*/
+/* XcInternalTagCall --- */
+/* */
+/* Execute the tag callback for a command without actually */
+/* evaluating the command itself. The command and arguments */
+/* are passed as a variable number or char * arguments, since */
+/* usually this routine will called with constant arguments */
+/* (e.g., XcInternalTagCall(interp, 2, "set", "color");) */
+/* */
+/* objv declared static because this routine is used a lot */
+/* (e.g., during select/unselect operations). */
+/*--------------------------------------------------------------*/
+
+int XcInternalTagCall(Tcl_Interp *interp, int argc, ...)
+{
+ int i;
+ static Tcl_Obj **objv = NULL;
+ char *aptr;
+ va_list ap;
+
+
+ if (objv == (Tcl_Obj **)NULL)
+ objv = (Tcl_Obj **)malloc(argc * sizeof(Tcl_Obj *));
+ else
+ objv = (Tcl_Obj **)realloc(objv, argc * sizeof(Tcl_Obj *));
+
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++) {
+ aptr = va_arg(ap, char *);
+ /* We are depending on Tcl's heap allocation of objects */
+ /* so that we do not have to manage memory for these */
+ /* string representations. . . */
+
+ objv[i] = Tcl_NewStringObj(aptr, -1);
+ }
+ va_end(ap);
+
+ return XcTagCallback(interp, argc, objv);
+}
+
+/*--------------------------------------------------------------*/
+/* Return the event mode */
+/* Event mode can be set in specific cases. */
+/*--------------------------------------------------------------*/
+
+int xctcl_eventmode(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
+{
+ static char *modeNames[] = {
+ "normal", "undo", "move", "copy", "pan", "selarea",
+ "pending", "rescale", "catalog", "cattext",
+ "fontcat", "efontcat", "text", "wire", "box",
+ "arc", "spline", "etext", "epoly", "earc",
+ "espline", "epath", "einst", "assoc", "catmove",
+ NULL
+ };
+
+ /* This routine is diagnostic only */
+
+ if (objc != 1) return TCL_ERROR;
+
+ Tcl_SetResult(interp, modeNames[eventmode], NULL);
+ return TCL_OK;
+}
+
+/*--------------------------------------------------------------*/
+/* Add a command tag callback */
+/*--------------------------------------------------------------*/
+
+int xctcl_tag(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_HashEntry *entry;
+ char *hstring;
+ int new;
+
+ if (objc != 2 && objc != 3)
+ return TCL_ERROR;
+
+ entry = Tcl_CreateHashEntry(&XcTagTable, Tcl_GetString(objv[1]), &new);
+ if (entry == NULL) return TCL_ERROR;
+
+ hstring = (char *)Tcl_GetHashValue(entry);
+ if (objc == 2)
+ {
+ Tcl_SetResult(interp, hstring, NULL);
+ return TCL_OK;
+ }
+
+ if (strlen(Tcl_GetString(objv[2])) == 0)
+ {
+ Tcl_DeleteHashEntry(entry);
+ }
+ else
+ {
+ hstring = strdup(Tcl_GetString(objv[2]));
+ Tcl_SetHashValue(entry, hstring);
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* Turn a selection list into a Tcl List object (may be empty list) */
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *SelectToTclList(Tcl_Interp *interp, short *slist, int snum)
+{
+ int i;
+ Tcl_Obj *objPtr, *listPtr;
+
+ if (snum == 1) {
+ objPtr = Tcl_NewHandleObj(SELTOGENERIC(slist));
+ return objPtr;
+ }
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < snum; i++) {
+ objPtr = Tcl_NewHandleObj(SELTOGENERIC(slist + i));
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ return listPtr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get an x,y position (as an XPoint structure) from a list of size 2 */
+/*----------------------------------------------------------------------*/
+
+int GetPositionFromList(Tcl_Interp *interp, Tcl_Obj *list, XPoint *rpoint)
+{
+ int result, numobjs;
+ Tcl_Obj *lobj, *tobj;
+ int pos;
+
+ if (!strcmp(Tcl_GetString(list), "here")) {
+ if (rpoint) *rpoint = UGetCursorPos();
+ return TCL_OK;
+ }
+ result = Tcl_ListObjLength(interp, list, &numobjs);
+ if (result != TCL_OK) return result;
+
+ if (numobjs == 1) {
+ /* Try decomposing the object into a list */
+ result = Tcl_ListObjIndex(interp, list, 0, &tobj);
+ if (result == TCL_OK) {
+ result = Tcl_ListObjLength(interp, tobj, &numobjs);
+ if (numobjs == 2)
+ list = tobj;
+ }
+ if (result != TCL_OK) Tcl_ResetResult(interp);
+ }
+ if (numobjs != 2) {
+ Tcl_SetResult(interp, "list must contain x y positions", NULL);
+ return TCL_ERROR;
+ }
+ result = Tcl_ListObjIndex(interp, list, 0, &lobj);
+ if (result != TCL_OK) return result;
+ result = Tcl_GetIntFromObj(interp, lobj, &pos);
+ if (result != TCL_OK) return result;
+ if (rpoint) rpoint->x = pos;
+
+ result = Tcl_ListObjIndex(interp, list, 1, &lobj);
+ if (result != TCL_OK) return result;
+ result = Tcl_GetIntFromObj(interp, lobj, &pos);
+ if (result != TCL_OK) return result;
+ if (rpoint) rpoint->y = pos;
+
+ return TCL_OK;
+}
+
+/*--------------------------------------------------------------*/
+/* Convert color index to a list of 3 elements */
+/* We assume that this color exists in the color table. */
+/*--------------------------------------------------------------*/
+
+Tcl_Obj *TclIndexToRGB(int cidx)
+{
+ Tcl_Obj *RGBTuple;
+
+ if (cidx < 0) { /* Handle "default color" */
+ return Tcl_NewStringObj("Default", 7);
+ }
+ else if (cidx >= number_colors) {
+ Tcl_SetResult(xcinterp, "Bad color index", NULL);
+ return NULL;
+ }
+
+ RGBTuple = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, RGBTuple,
+ Tcl_NewIntObj((int)(colorlist[cidx].color.red / 256)));
+ Tcl_ListObjAppendElement(xcinterp, RGBTuple,
+ Tcl_NewIntObj((int)(colorlist[cidx].color.green / 256)));
+ Tcl_ListObjAppendElement(xcinterp, RGBTuple,
+ Tcl_NewIntObj((int)(colorlist[cidx].color.blue / 256)));
+ return RGBTuple;
+}
+
+
+/*--------------------------------------------------------------*/
+/* Convert a stringpart* to a Tcl list object */
+/*--------------------------------------------------------------*/
+
+Tcl_Obj *TclGetStringParts(stringpart *thisstring)
+{
+ Tcl_Obj *lstr, *sdict, *stup;
+ int i;
+ stringpart *strptr;
+
+ lstr = Tcl_NewListObj(0, NULL);
+ for (strptr = thisstring, i = 0; strptr != NULL;
+ strptr = strptr->nextpart, i++) {
+ switch(strptr->type) {
+ case TEXT_STRING:
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict, Tcl_NewStringObj("Text", 4));
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj(strptr->data.string,
+ strlen(strptr->data.string)));
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case PARAM_START:
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict, Tcl_NewStringObj("Parameter", 9));
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj(strptr->data.string,
+ strlen(strptr->data.string)));
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case PARAM_END:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("End Parameter", 13));
+ break;
+ case FONT_NAME:
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict, Tcl_NewStringObj("Font", 4));
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj(fonts[strptr->data.font].psname,
+ strlen(fonts[strptr->data.font].psname)));
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case FONT_SCALE:
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj("Font Scale", 10));
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewDoubleObj((double)strptr->data.scale));
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case KERN:
+ sdict = Tcl_NewListObj(0, NULL);
+ stup = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, stup,
+ Tcl_NewIntObj((int)strptr->data.kern[0]));
+ Tcl_ListObjAppendElement(xcinterp, stup,
+ Tcl_NewIntObj((int)strptr->data.kern[1]));
+
+ Tcl_ListObjAppendElement(xcinterp, sdict, Tcl_NewStringObj("Kern", 4));
+ Tcl_ListObjAppendElement(xcinterp, sdict, stup);
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case FONT_COLOR:
+ stup = TclIndexToRGB(strptr->data.color);
+ if (stup != NULL) {
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj("Color", 5));
+ Tcl_ListObjAppendElement(xcinterp, sdict, stup);
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ }
+ break;
+ case MARGINSTOP:
+ sdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewStringObj("Margin Stop", 11));
+ Tcl_ListObjAppendElement(xcinterp, sdict,
+ Tcl_NewIntObj((int)strptr->data.width));
+ Tcl_ListObjAppendElement(xcinterp, lstr, sdict);
+ break;
+ case TABSTOP:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Tab Stop", 8));
+ break;
+ case TABFORWARD:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Tab Forward", 11));
+ break;
+ case TABBACKWARD:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Tab Backward", 12));
+ break;
+ case RETURN:
+ // Don't show automatically interted line breaks
+ if (strptr->data.flags == 0)
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Return", 6));
+ break;
+ case SUBSCRIPT:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Subscript", 9));
+ break;
+ case SUPERSCRIPT:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Superscript", 11));
+ break;
+ case NORMALSCRIPT:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Normalscript", 12));
+ break;
+ case UNDERLINE:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Underline", 9));
+ break;
+ case OVERLINE:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Overline", 8));
+ break;
+ case NOLINE:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("No Line", 7));
+ break;
+ case HALFSPACE:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Half Space", 10));
+ break;
+ case QTRSPACE:
+ Tcl_ListObjAppendElement(xcinterp, lstr,
+ Tcl_NewStringObj("Quarter Space", 13));
+ break;
+ }
+ }
+ return lstr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get a stringpart linked list from a Tcl list */
+/*----------------------------------------------------------------------*/
+
+int GetXCStringFromList(Tcl_Interp *interp, Tcl_Obj *list, stringpart **rstring)
+{
+ int result, j, k, numobjs, idx, numparts, ptype, ival;
+ Tcl_Obj *lobj, *pobj, *tobj, *t2obj;
+ stringpart *newpart;
+ char *fname;
+ double fscale;
+
+ static char *partTypes[] = {"Text", "Subscript", "Superscript",
+ "Normalscript", "Underline", "Overline", "No Line", "Tab Stop",
+ "Tab Forward", "Tab Backward", "Half Space", "Quarter Space",
+ "Return", "Font", "Font Scale", "Color", "Margin Stop", "Kern",
+ "Parameter", "End Parameter", "Special", NULL};
+
+ static int partTypesIdx[] = {TEXT_STRING, SUBSCRIPT, SUPERSCRIPT,
+ NORMALSCRIPT, UNDERLINE, OVERLINE, NOLINE, TABSTOP, TABFORWARD,
+ TABBACKWARD, HALFSPACE, QTRSPACE, RETURN, FONT_NAME, FONT_SCALE,
+ FONT_COLOR, MARGINSTOP, KERN, PARAM_START, PARAM_END, SPECIAL};
+
+ /* No place to put result! */
+ if (rstring == NULL) return TCL_ERROR;
+
+ result = Tcl_ListObjLength(interp, list, &numobjs);
+ if (result != TCL_OK) return result;
+
+ newpart = NULL;
+ for (j = 0; j < numobjs; j++) {
+ result = Tcl_ListObjIndex(interp, list, j, &lobj);
+ if (result != TCL_OK) return result;
+
+ result = Tcl_ListObjLength(interp, lobj, &numparts);
+ if (result != TCL_OK) return result;
+
+ result = Tcl_ListObjIndex(interp, lobj, 0, &pobj);
+ if (result != TCL_OK) return result;
+
+ /* Must define TCL_EXACT in flags, or else, for instance, "u" gets */
+ /* interpreted as "underline", which is usually not intended. */
+
+ if (pobj == NULL)
+ return TCL_ERROR;
+ else if (Tcl_GetIndexFromObj(interp, pobj, (CONST84 char **)partTypes,
+ "string part types", TCL_EXACT, &idx) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ idx = -1;
+ result = Tcl_ListObjIndex(interp, lobj, 0, &tobj);
+ }
+ else {
+ result = Tcl_ListObjIndex(interp, lobj, (numparts > 1) ? 1 : 0, &tobj);
+ }
+ if (result != TCL_OK) return result;
+
+ if (idx < 0) {
+ if ((newpart == NULL) || (newpart->type != TEXT_STRING))
+ idx = 0;
+ else {
+ /* We have an implicit text string which should be appended */
+ /* to the previous text string with a space character. */
+ newpart->data.string = (char *)realloc(newpart->data.string,
+ strlen(newpart->data.string) + strlen(Tcl_GetString(tobj))
+ + 2);
+ strcat(newpart->data.string, " ");
+ strcat(newpart->data.string, Tcl_GetString(tobj));
+ continue;
+ }
+ }
+ ptype = partTypesIdx[idx];
+
+ newpart = makesegment(rstring, NULL);
+ newpart->nextpart = NULL;
+ newpart->type = ptype;
+
+ switch(ptype) {
+ case TEXT_STRING:
+ case PARAM_START:
+ newpart->data.string = strdup(Tcl_GetString(tobj));
+ break;
+ case FONT_NAME:
+ fname = Tcl_GetString(tobj);
+ for (k = 0; k < fontcount; k++) {
+ if (!strcmp(fonts[k].psname, fname)) {
+ newpart->data.font = k;
+ break;
+ }
+ }
+ if (k == fontcount) {
+ Tcl_SetResult(interp, "Bad font name", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case FONT_SCALE:
+ result = Tcl_GetDoubleFromObj(interp, tobj, &fscale);
+ if (result != TCL_OK) return result;
+ newpart->data.scale = (float)fscale;
+ break;
+ case MARGINSTOP:
+ result = Tcl_GetIntFromObj(interp, tobj, &ival);
+ if (result != TCL_OK) return result;
+ newpart->data.width = ival;
+ break;
+ case KERN:
+ result = Tcl_ListObjLength(interp, tobj, &numparts);
+ if (result != TCL_OK) return result;
+ if (numparts != 2) {
+ Tcl_SetResult(interp, "Bad kern list: need 2 values", NULL);
+ return TCL_ERROR;
+ }
+ result = Tcl_ListObjIndex(interp, tobj, 0, &t2obj);
+ if (result != TCL_OK) return result;
+ result = Tcl_GetIntFromObj(interp, t2obj, &ival);
+ if (result != TCL_OK) return result;
+ newpart->data.kern[0] = (short)ival;
+
+ result = Tcl_ListObjIndex(interp, tobj, 1, &t2obj);
+ if (result != TCL_OK) return result;
+ result = Tcl_GetIntFromObj(interp, t2obj, &ival);
+ if (result != TCL_OK) return result;
+ newpart->data.kern[1] = (short)ival;
+
+ break;
+ case FONT_COLOR:
+ /* Not implemented: Need TclRGBToIndex() function */
+ break;
+
+ /* All other types have no arguments */
+ }
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* Handle (integer representation of internal xcircuit object) checking */
+/* if "checkobject" is NULL, then */
+/*----------------------------------------------------------------------*/
+
+genericptr *CheckHandle(pointertype eaddr, objectptr checkobject)
+{
+ genericptr *gelem;
+ int i, j;
+ objectptr thisobj;
+ Library *thislib;
+
+ if (checkobject != NULL) {
+ for (gelem = checkobject->plist; gelem < checkobject->plist +
+ checkobject->parts; gelem++)
+ if ((pointertype)(*gelem) == eaddr) goto exists;
+ return NULL;
+ }
+
+ /* Look through all the pages. */
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst == NULL) continue;
+ thisobj = xobjs.pagelist[i]->pageinst->thisobject;
+ for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts; gelem++)
+ if ((pointertype)(*gelem) == eaddr) goto exists;
+ }
+
+ /* Not found? Maybe in a library */
+
+ for (i = 0; i < xobjs.numlibs; i++) {
+ thislib = xobjs.userlibs + i;
+ for (j = 0; j < thislib->number; j++) {
+ thisobj = thislib->library[j];
+ for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts; gelem++)
+ if ((pointertype)(*gelem) == eaddr) goto exists;
+ }
+ }
+
+ /* Either in the delete list (where we don't want to go) or */
+ /* is an invalid number. */
+ return NULL;
+
+exists:
+ return gelem;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the index into the "plist" list of elements */
+/* Part number must be of a type in "mask" or no selection occurs. */
+/* return values: -1 = no object found, -2 = found, but wrong type */
+/*----------------------------------------------------------------------*/
+
+short GetPartNumber(genericptr egen, objectptr checkobject, int mask)
+{
+ genericptr *gelem;
+ objectptr thisobject = checkobject;
+ int i;
+
+ if (checkobject == NULL) thisobject = topobject;
+
+ for (i = 0, gelem = thisobject->plist; gelem < thisobject->plist +
+ thisobject->parts; gelem++, i++) {
+ if ((*gelem) == egen) {
+ if ((*gelem)->type & mask)
+ return i;
+ else
+ return -2;
+ }
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* This routine is used by a number of menu functions. It looks for */
+/* the arguments "selected" or an integer (object handle). If the */
+/* argument is a valid object handle, it is added to the select list. */
+/* The argument can be a list of handles, of which each is checked and */
+/* added to the select list. */
+/* "extra" indicates the number of required arguments beyond 2. */
+/* "next" returns the integer of the argument after the handle, or the */
+/* argument after the command, if there is no handle. If the handle is */
+/* specified as a hierarchical list of element handles then */
+/* areawin->hierstack contains the hierarchy of object instances. */
+/*----------------------------------------------------------------------*/
+
+int ParseElementArguments(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int *next, int mask) {
+
+ short *newselect;
+ char *argstr;
+ int i, j, result, numobjs;
+ pointertype ehandle;
+ Tcl_Obj *lobj;
+ int extra = 0, goodobjs = 0;
+
+ if (next != NULL) {
+ extra = *next;
+ *next = 1;
+ }
+
+ if ((objc > (2 + extra)) || (objc == 1)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "[selected | <element_handle>] <option>");
+ return TCL_ERROR;
+ }
+ else if (objc == 1) {
+ *next = 0;
+ return TCL_OK;
+ }
+ else {
+ argstr = Tcl_GetString(objv[1]);
+
+ if (strcmp(argstr, "selected")) {
+
+ /* check for object handle (special type) */
+
+ result = Tcl_ListObjLength(interp, objv[1], &numobjs);
+ if (result != TCL_OK) return result;
+ goodobjs = 0;
+
+ /* Non-integer, non-list types: assume operation is to be applied */
+ /* to currently selected elements, and return to caller. */
+
+ if (numobjs == 1) {
+ result = Tcl_GetHandleFromObj(interp, objv[1], (void *)&ehandle);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+ }
+ if (numobjs == 0) {
+ Tcl_SetResult(interp, "No elements.", NULL);
+ return TCL_ERROR;
+ }
+ else
+ newselect = (short *)malloc(numobjs * sizeof(short));
+
+ /* Prepare a new selection, in case the new selection is */
+ /* smaller than the original selection, but don't blanket */
+ /* delete an existing selection, which will destroy cycle */
+ /* information. */
+
+ for (j = 0; j < numobjs; j++) {
+ result = Tcl_ListObjIndex(interp, objv[1], j, &lobj);
+ if (result != TCL_OK) {
+ free(newselect);
+ return result;
+ }
+ result = Tcl_GetHandleFromObj(interp, lobj, (void *)&ehandle);
+ if (result != TCL_OK) {
+ free(newselect);
+ return result;
+ }
+ if (areawin->hierstack != NULL)
+ i = GetPartNumber((genericptr)ehandle,
+ areawin->hierstack->thisinst->thisobject, mask);
+ else
+ i = GetPartNumber((genericptr)ehandle, topobject, mask);
+
+ if (i == -1) {
+ free_stack(&areawin->hierstack);
+ Tcl_SetResult(interp, "No such element exists.", NULL);
+ free(newselect);
+ return TCL_ERROR;
+ }
+ else if (i >= 0) {
+ *(newselect + goodobjs) = i;
+ if (next != NULL) *next = 2;
+ goodobjs++;
+ }
+ }
+ if (goodobjs == 0) {
+ Tcl_SetResult(interp, "No element matches required type.", NULL);
+ unselect_all();
+ free(newselect);
+ return TCL_ERROR;
+ }
+ else {
+ selection aselect, bselect;
+
+ /* To avoid unnecessarily blasting the existing selection */
+ /* and its cycles, we compare the two selection lists. */
+ /* This is not an excuse for not fixing the selection list */
+ /* mess in general! */
+
+ aselect.selectlist = newselect;
+ aselect.selects = goodobjs;
+ bselect.selectlist = areawin->selectlist;
+ bselect.selects = areawin->selects;
+ if (compareselection(&aselect, &bselect)) {
+ free(newselect);
+ }
+ else {
+ unselect_all();
+ areawin->selects = goodobjs;
+ areawin->selectlist = newselect;
+ }
+ }
+
+ draw_normal_selected(topobject, areawin->topinstance);
+ }
+ else if (next != NULL) *next = 2;
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate a transformation matrix according to the object instance */
+/* hierarchy left on the hierstack. */
+/*----------------------------------------------------------------------*/
+
+void MakeHierCTM(Matrix *hierCTM)
+{
+ objinstptr thisinst;
+ pushlistptr cs;
+
+ UResetCTM(hierCTM);
+ for (cs = areawin->hierstack; cs != NULL; cs = cs->next) {
+ thisinst = cs->thisinst;
+ UMultCTM(hierCTM, thisinst->position, thisinst->scale, thisinst->rotation);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* This routine is similar to ParseElementArguments. It looks for a */
+/* page number or page name in the second argument position. If it */
+/* finds one, it sets the page number in the return value. Otherwise, */
+/* it sets the return value to the value of areawin->page. */
+/*----------------------------------------------------------------------*/
+
+int ParsePageArguments(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int *next, int *pageret) {
+
+ char *pagename;
+ int i, page, result;
+ Tcl_Obj *objPtr;
+
+ if (next != NULL) *next = 1;
+ if (pageret != NULL) *pageret = areawin->page; /* default */
+
+ if ((objc == 1) || ((objc == 2) && !strcmp(Tcl_GetString(objv[1]), ""))) {
+ objPtr = Tcl_NewIntObj(areawin->page + 1);
+ Tcl_SetObjResult(interp, objPtr);
+ if (next) *next = -1;
+ return TCL_OK;
+ }
+ else {
+ pagename = Tcl_GetString(objv[1]);
+ if (strcmp(pagename, "directory")) {
+
+ /* check for page number (integer) */
+
+ result = Tcl_GetIntFromObj(interp, objv[1], &page);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+
+ /* check for page name (string) */
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst == NULL) continue;
+ if (!strcmp(pagename, xobjs.pagelist[i]->pageinst->thisobject->name)) {
+ if (pageret) *pageret = i;
+ break;
+ }
+ }
+ if (i == xobjs.pages) {
+ if (next != NULL) *next = 0;
+ }
+ }
+ else {
+ if (page < 1) {
+ Tcl_SetResult(interp, "Illegal page number: zero or negative", NULL);
+ return TCL_ERROR;
+ }
+ else if (page > xobjs.pages) {
+ Tcl_SetResult(interp, "Illegal page number: page does not exist", NULL);
+ if (pageret) *pageret = (page - 1);
+ return TCL_ERROR;
+ }
+ else if (pageret) *pageret = (page - 1);
+ }
+ }
+ else {
+ *next = 0;
+ }
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* This routine is similar to ParsePageArguments. It looks for a */
+/* library number or library name in the second argument position. If */
+/* it finds one, it sets the page number in the return value. */
+/* Otherwise, if a library page is currently being viewed, it sets the */
+/* return value to that library. Otherwise, it sets the return value */
+/* to the User Library. */
+/*----------------------------------------------------------------------*/
+
+int ParseLibArguments(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int *next, int *libret) {
+
+ char *libname;
+ int library, result;
+ Tcl_Obj *objPtr;
+
+ if (next != NULL) *next = 1;
+
+ if (objc == 1) {
+ library = is_library(topobject);
+ if (library < 0) {
+ Tcl_SetResult(interp, "No current library.", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewIntObj(library + 1);
+ Tcl_SetObjResult(interp, objPtr);
+ if (next) *next = -1;
+ return TCL_OK;
+ }
+ else {
+ libname = Tcl_GetString(objv[1]);
+ if (strcmp(libname, "directory")) {
+
+ /* check for library number (integer) or name */
+
+ result = Tcl_GetIntFromObj(interp, objv[1], &library);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(xcinterp);
+ *libret = NameToLibrary(libname);
+ if (*libret < 0) {
+ *libret = -1;
+ if (next != NULL) *next = 0;
+ }
+ }
+ else {
+ if (library < 1) {
+ Tcl_SetResult(interp, "Illegal library number: zero or negative", NULL);
+ return TCL_ERROR;
+ }
+ else if (library > xobjs.numlibs) {
+ Tcl_SetResult(interp, "Illegal library number: library "
+ "does not exist", NULL);
+ return TCL_ERROR;
+ }
+ else *libret = (library - 1);
+ }
+ }
+ else *next = 0;
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* Schematic and symbol creation and association */
+/*----------------------------------------------------------------------*/
+
+int xctcl_symschem(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, idx, result, stype;
+ objectptr otherobj = NULL;
+ char *objname;
+
+ static char *subCmds[] = {
+ "associate", "disassociate", "make", "goto", "get", "type", NULL
+ };
+ enum SubIdx {
+ AssocIdx, DisAssocIdx, MakeIdx, GoToIdx, NameIdx, TypeIdx
+ };
+
+ /* The order of these must match the definitions in xcircuit.h */
+ static char *schemTypes[] = {
+ "primary", "secondary", "trivial", "symbol", "fundamental",
+ "nonetwork", NULL /* (jdk) */
+ };
+
+ if (objc == 1 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else if ((result = Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK) {
+ return result;
+ }
+
+ switch(idx) {
+ case AssocIdx:
+ if (objc == 3) {
+
+ /* To do: accept name for association */
+ objname = Tcl_GetString(objv[2]);
+
+ if (topobject->schemtype == PRIMARY) {
+
+ /* Name has to be that of a library object */
+
+ otherobj = NameToObject(Tcl_GetString(objv[2]), NULL, FALSE);
+ if (otherobj == NULL) {
+ Tcl_SetResult(interp, "Name is not a known object", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+
+ /* Name has to be that of a page label */
+
+ objectptr pageobj;
+ for (i = 0; i < xobjs.pages; i++) {
+ pageobj = xobjs.pagelist[i]->pageinst->thisobject;
+ if (!strcmp(objname, pageobj->name)) {
+ otherobj = pageobj;
+ break;
+ }
+ }
+ if (otherobj == NULL)
+ {
+ Tcl_SetResult(interp, "Name is not a known page label", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (schemassoc(topobject, otherobj) == False)
+ return TCL_ERROR;
+ }
+ else
+ startschemassoc(NULL, 0, NULL);
+ break;
+ case DisAssocIdx:
+ schemdisassoc();
+ break;
+ case MakeIdx:
+ if (topobject->symschem != NULL)
+ Wprintf("Error: Schematic already has an associated symbol.");
+ else if (topobject->schemtype != PRIMARY)
+ Wprintf("Error: Current page is not a primary schematic.");
+ else if (!strncmp(topobject->name, "Page ", 5))
+ Wprintf("Error: Schematic page must have a valid name.");
+ else {
+ int libnum = -1;
+ if (objc >= 3) {
+
+ objname = Tcl_GetString(objv[2]);
+
+ if (objc == 4) {
+ ParseLibArguments(xcinterp, 2, &objv[2], NULL, &libnum);
+ if (libnum < 0) {
+ Tcl_SetResult(interp, "Invalid library name.", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ else {
+ /* Use this error condition to generate the popup prompt */
+ Tcl_SetResult(interp, "Must supply a name for the page", NULL);
+ return TCL_ERROR;
+ }
+ swapschem(1, libnum, objname);
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+ break;
+ case GoToIdx:
+ /* This is supposed to specifically go to the specified type, */
+ /* so don't call swapschem to change views if we're already */
+ /* on the right view. */
+
+ if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY) {
+ if (!strncmp(Tcl_GetString(objv[0]), "sym", 3)) {
+ swapschem(0, -1, NULL);
+ }
+ }
+ else {
+ if (!strncmp(Tcl_GetString(objv[0]), "sch", 3)) {
+ swapschem(0, -1, NULL);
+ }
+ }
+ break;
+ case NameIdx:
+ if (topobject->symschem != NULL)
+ Tcl_AppendElement(interp, topobject->symschem->name);
+ break;
+ case TypeIdx:
+ if (objc == 3) {
+ if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY) {
+ Tcl_SetResult(interp, "Make object to change from schematic to symbol",
+ NULL);
+ return TCL_ERROR;
+ }
+ if ((result = Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)schemTypes, "schematic types",
+ 0, &stype)) != TCL_OK)
+ return result;
+ if (stype == PRIMARY || stype == SECONDARY) {
+ Tcl_SetResult(interp, "Cannot change symbol into a schematic", NULL);
+ return TCL_ERROR;
+ }
+ topobject->schemtype = stype;
+ if (topobject->symschem) schemdisassoc();
+ }
+ else
+ Tcl_AppendElement(interp, schemTypes[topobject->schemtype]);
+
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Generate netlist into a Tcl hierarchical list */
+/* (plus other netlist functions) */
+/*----------------------------------------------------------------------*/
+
+int xctcl_netlist(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_Obj *rdict;
+ int idx, result, mpage, spage, bvar, j;
+ Boolean valid, quiet;
+ char *option, *extension, *mode = NULL;
+ pushlistptr stack;
+ objectptr master, slave;
+ objinstptr schemtopinst;
+
+ static char *subCmds[] = {
+ "write", "highlight", "unhighlight", "goto", "get", "select", "parse",
+ "position", "make", "connect", "unconnect", "autonumber", "ratsnest",
+ "update", NULL
+ };
+ enum SubIdx {
+ WriteIdx, HighLightIdx, UnHighLightIdx, GoToIdx, GetIdx, SelectIdx,
+ ParseIdx, PositionIdx, MakeIdx, ConnectIdx, UnConnectIdx,
+ AutoNumberIdx, RatsNestIdx, UpdateIdx
+ };
+
+ if (objc == 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else if ((result = Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK) {
+ return result;
+ }
+
+ /* Look for the "-quiet" option (more options processed by "netlist get") */
+
+ j = 1;
+ quiet = FALSE;
+ while (option = Tcl_GetString(objv[objc - (j++)]), option[0] == '-') {
+ if (!strncmp(option + 1, "quiet", 5))
+ quiet = TRUE;
+ }
+
+ /* Make sure a valid netlist exists for the current schematic */
+ /* for those commands which require a valid netlist (non-ASG */
+ /* functions). Some functions (e.g., "parse") require that */
+ /* the next object up in the hierarchy have a valid netlist, */
+ /* if we have descended to the current symbol from there. */
+
+ valid = False;
+ switch(idx) {
+ case RatsNestIdx:
+ /* Specifically avoid calling updatenets() */
+ if ((topobject->labels != NULL) || (topobject->polygons != NULL))
+ valid = True;
+ break;
+ }
+
+ if (!valid) {
+ objinstptr tinst;
+
+ /* Ignore libraries */
+ if (is_library(topobject) >= 0 || (eventmode == CATALOG_MODE))
+ return TCL_ERROR;
+
+ if ((topobject->schemtype) != PRIMARY && (areawin->stack != NULL))
+ tinst = areawin->stack->thisinst;
+ else
+ tinst = areawin->topinstance;
+
+ if ((result = updatenets(tinst, quiet)) < 0) {
+ Tcl_SetResult(interp, "Check circuit for infinite recursion.", NULL);
+ return TCL_ERROR;
+ }
+ else if (result == 0) {
+ Tcl_SetResult(interp, "No netlist.", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ switch(idx) {
+ case WriteIdx: /* write netlist formats */
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "write format [extension] "
+ "[spice_end] [-option]");
+ return TCL_ERROR;
+ }
+
+ /* Check for forcing option */
+
+ option = Tcl_GetString(objv[objc - 1]);
+ if (option[0] == '-')
+ {
+ option++;
+ if (!strncmp(option, "flat", 4) || !strncmp(option, "pseu", 4))
+ {
+ mode = (char *)malloc(5 + strlen(Tcl_GetString(objv[2])));
+ option[4] = '\0';
+ sprintf(mode, "%s%s", option, Tcl_GetString(objv[2]));
+ }
+ else if (strncmp(option, "hier", 4))
+ {
+ Tcl_SetResult(interp, "Unknown netlist option.", NULL);
+ return TCL_ERROR;
+ }
+ objc--;
+ }
+
+ if ((result = Tcl_GetBooleanFromObj(interp, objv[objc - 1], &bvar))
+ != TCL_OK) {
+ spice_end = True;
+ Tcl_ResetResult(interp);
+ }
+ else {
+ spice_end = (Boolean)bvar;
+ objc--;
+ }
+
+ /* If no extension is specified, the extension is the same as */
+ /* the format name. */
+
+ if (objc == 3)
+ extension = Tcl_GetString(objv[2]);
+ else
+ extension = Tcl_GetString(objv[3]);
+ writenet(topobject, (mode == NULL) ? Tcl_GetString(objv[2]) : mode,
+ extension);
+ if (mode != NULL) free(mode);
+ break;
+
+ case GoToIdx: /* go to top-level page having specified name */
+ if (objc != 2 && objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "goto [hierarchical-network-name]");
+ return TCL_ERROR;
+ }
+
+ /* Find the top of the schematic hierarchy, regardless of */
+ /* where the current page is in it. */
+
+ if (areawin->stack == NULL)
+ schemtopinst = areawin->topinstance;
+ else {
+ pushlistptr sstack = areawin->stack;
+ while (sstack->next != NULL) sstack = sstack->next;
+ schemtopinst = sstack->thisinst;
+ }
+
+ stack = NULL;
+ push_stack(&stack, schemtopinst, NULL);
+ valid = TRUE;
+ if (objc == 3)
+ valid = HierNameToObject(schemtopinst, Tcl_GetString(objv[2]), &stack);
+
+ if (valid) {
+ /* Add the current edit object to the push stack, then append */
+ /* the new push stack */
+ free_stack(&areawin->stack);
+ topobject->viewscale = areawin->vscale;
+ topobject->pcorner = areawin->pcorner;
+ areawin->topinstance = stack->thisinst;
+ pop_stack(&stack);
+ areawin->stack = stack;
+ setpage(TRUE);
+ transferselects();
+ refresh(NULL, NULL, NULL);
+ setsymschem();
+
+ /* If the current object is a symbol that has a schematic, */
+ /* go to the schematic. */
+
+ if (topobject->schemtype != PRIMARY && topobject->symschem != NULL)
+ swapschem(0, -1, NULL);
+ }
+ else {
+ Tcl_SetResult(interp, "Not a valid network.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case GetIdx: { /* return hierarchical name of selected network */
+ int stype, netid, lbus;
+ Boolean uplevel, hier, canon;
+ char *prefix = NULL;
+ Matrix locctm;
+ short *newselect;
+ Genericlist *netlist;
+ CalllistPtr calls;
+ objinstptr refinstance;
+ objectptr refobject;
+ XPoint refpoint, *refptptr;
+ stringpart *ppin;
+ char *snew;
+ buslist *sbus;
+ Tcl_Obj *tlist;
+
+ option = Tcl_GetString(objv[objc - 1]);
+ uplevel = FALSE;
+ hier = FALSE;
+ canon = FALSE;
+ quiet = FALSE;
+ while (option[0] == '-') {
+ if (!strncmp(option + 1, "up", 2)) {
+ uplevel = TRUE;
+ }
+ else if (!strncmp(option + 1, "hier", 4)) {
+ hier = TRUE;
+ }
+ else if (!strncmp(option + 1, "canon", 5)) {
+ canon = TRUE;
+ }
+ else if (!strncmp(option + 1, "quiet", 5)) {
+ quiet = TRUE;
+ }
+ else if (sscanf(option, "%hd", &refpoint.x) == 1) {
+ break; /* This is probably a negative point position! */
+ }
+ objc--;
+ option = Tcl_GetString(objv[objc - 1]);
+ }
+
+ refinstance = (areawin->hierstack) ? areawin->hierstack->thisinst
+ : areawin->topinstance;
+
+ if (uplevel) {
+ if (areawin->hierstack == NULL) {
+ if (areawin->stack == NULL) {
+ if (quiet) return TCL_OK;
+ Fprintf(stderr, "Option \"up\" used, but current page is the"
+ " top of the schematic\n");
+ return TCL_ERROR;
+ }
+ else {
+ UResetCTM(&locctm);
+ UPreMultCTM(&locctm, refinstance->position, refinstance->scale,
+ refinstance->rotation);
+ refinstance = areawin->stack->thisinst;
+ refobject = refinstance->thisobject;
+ }
+ }
+ else {
+ if (areawin->hierstack->next == NULL) {
+ if (quiet) return TCL_OK;
+ Fprintf(stderr, "Option \"up\" used, but current page is the"
+ " top of the drawing stack\n");
+ return TCL_ERROR;
+ }
+ else {
+ UResetCTM(&locctm);
+ UPreMultCTM(&locctm, refinstance->position, refinstance->scale,
+ refinstance->rotation);
+ refinstance = areawin->hierstack->next->thisinst;
+ refobject = refinstance->thisobject;
+ }
+ }
+ }
+ else {
+ refobject = topobject;
+ }
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "get [selected|here|<name>] [-up][-hier][-canon][-quiet]");
+ return TCL_ERROR;
+ }
+ if ((objc == 3) && !strcmp(Tcl_GetString(objv[2]), "here")) {
+ /* If "here", make a selection. */
+ areawin->save = UGetCursorPos();
+ newselect = select_element(POLYGON | LABEL | OBJINST);
+ objc--;
+ }
+ if ((objc == 2) || (!strcmp(Tcl_GetString(objv[2]), "selected"))) {
+ /* If no argument, or "selected", use the selected element */
+ newselect = areawin->selectlist;
+ if (areawin->selects == 0) {
+ if (hier) {
+ Tcl_SetResult(interp, GetHierarchy(&areawin->stack, canon),
+ TCL_DYNAMIC);
+ break;
+ }
+ else {
+ Fprintf(stderr, "Either select an element or use \"-hier\"\n");
+ return TCL_ERROR;
+ }
+ }
+ if (areawin->selects != 1) {
+ Fprintf(stderr, "Choose only one network element\n");
+ return TCL_ERROR;
+ }
+ else {
+ stype = SELECTTYPE(newselect);
+ if (stype == LABEL) {
+ labelptr nlabel = SELTOLABEL(newselect);
+ refptptr = &(nlabel->position);
+ if ((nlabel->pin != LOCAL) && (nlabel->pin != GLOBAL)) {
+ Fprintf(stderr, "Selected label is not a pin\n");
+ return TCL_ERROR;
+ }
+ }
+ else if (stype == POLYGON) {
+ polyptr npoly = SELTOPOLY(newselect);
+ refptptr = npoly->points;
+ if (nonnetwork(npoly)) {
+ Fprintf(stderr, "Selected polygon is not a wire\n");
+ return TCL_ERROR;
+ }
+ }
+ else if (stype == OBJINST) {
+ objinstptr ninst = SELTOOBJINST(newselect);
+ char *devptr;
+
+ for (calls = topobject->calls; calls != NULL; calls = calls->next)
+ if (calls->callinst == ninst)
+ break;
+ if (calls == NULL) {
+ Fprintf(stderr, "Selected instance is not a circuit component\n");
+ return TCL_ERROR;
+ }
+ else if (calls->devindex == -1) {
+ cleartraversed(topobject);
+ resolve_indices(topobject, FALSE);
+ }
+ push_stack(&areawin->stack, ninst, NULL);
+ prefix = GetHierarchy(&areawin->stack, canon);
+ pop_stack(&areawin->stack);
+ if (prefix == NULL) break;
+ devptr = prefix;
+ if (!hier) {
+ devptr = strrchr(prefix, '/');
+ if (devptr == NULL)
+ devptr = prefix;
+ else
+ devptr++;
+ }
+ Tcl_SetResult(interp, devptr, TCL_VOLATILE);
+ free(prefix);
+ break;
+ }
+ }
+ }
+ else if ((objc == 3) && (result = GetPositionFromList(interp, objv[2],
+ &refpoint)) == TCL_OK) {
+ /* Find net at indicated position in reference object. */
+ /* This allows us to query points without generating a pin */
+ /* at the position, which can alter the netlist under */
+ /* observation. */
+ refptptr = &refpoint;
+ }
+ else {
+ /* If a name, find the pin label element matching the name */
+ int x, y;
+ objinstptr instofname = (areawin->hierstack) ?
+ areawin->hierstack->thisinst :
+ areawin->topinstance;
+
+ Tcl_ResetResult(interp);
+
+ if (NameToPinLocation(instofname, Tcl_GetString(objv[2]),
+ &x, &y) == 0) {
+ refpoint.x = x; /* conversion from int to short */
+ refpoint.y = y;
+ refptptr = &refpoint;
+ }
+ else {
+ /* This is not necessarily an error. Use "-quiet" to shut it up */
+ if (quiet) return TCL_OK;
+ Tcl_SetResult(interp, "Cannot find position for pin ", NULL);
+ Tcl_AppendElement(interp, Tcl_GetString(objv[2]));
+ return TCL_ERROR;
+ }
+ }
+
+ /* Now that we have a reference point, convert it to a netlist */
+ if (uplevel) {
+ UTransformbyCTM(&locctm, refptptr, &refpoint, 1);
+ refptptr = &refpoint;
+ }
+ netlist = pointtonet(refobject, refinstance, refptptr);
+ if (netlist == NULL) {
+ if (quiet) return TCL_OK;
+ Fprintf(stderr, "Error: No network found!\n");
+ return TCL_ERROR;
+ }
+
+ /* If refobject is a secondary schematic, we need to find the */
+ /* corresponding primary page to call nettopin(). */
+ master = (refobject->schemtype == SECONDARY) ?
+ refobject->symschem : refobject;
+
+ /* Now that we have a netlist, convert it to a name */
+ /* Need to get prefix from the current call stack so we */
+ /* can represent flat names as well as hierarchical names. */
+
+ if (hier) {
+ int plen;
+ prefix = GetHierarchy(&areawin->stack, canon);
+ if (prefix) {
+ plen = strlen(prefix);
+ if (*(prefix + plen - 1) != '/') {
+ prefix = realloc(prefix, plen + 2);
+ strcat(prefix, "/");
+ }
+ }
+ }
+
+ if (netlist->subnets == 0) {
+ netid = netlist->net.id;
+ ppin = nettopin(netid, master, (prefix == NULL) ? "" : prefix);
+ snew = textprint(ppin, refinstance);
+ Tcl_SetResult(interp, snew, TCL_DYNAMIC);
+ }
+ else if (netlist->subnets == 1) {
+
+ /* Need to get prefix from the current call stack! */
+ sbus = netlist->net.list;
+ netid = sbus->netid;
+ ppin = nettopin(netid, master, (prefix == NULL) ? "" : prefix);
+ snew = textprintsubnet(ppin, refinstance, sbus->subnetid);
+ Tcl_SetResult(interp, snew, TCL_DYNAMIC);
+ }
+ else {
+ tlist = Tcl_NewListObj(0, NULL);
+ for (lbus = 0; lbus < netlist->subnets; lbus++) {
+ sbus = netlist->net.list + lbus;
+ netid = sbus->netid;
+ ppin = nettopin(netid, master, (prefix == NULL) ? "" : prefix);
+ snew = textprintsubnet(ppin, refinstance, sbus->subnetid);
+ Tcl_ListObjAppendElement(interp, tlist, Tcl_NewStringObj(snew, -1));
+ Tcl_SetObjResult(interp, tlist);
+ free(snew);
+ }
+ }
+ if (prefix != NULL) free(prefix);
+ } break;
+
+ case ParseIdx: { /* generate output from info labels */
+ char *mode, *snew;
+ objectptr cfrom;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "parse <mode>");
+ return TCL_ERROR;
+ }
+ mode = Tcl_GetString(objv[2]);
+ master = topobject;
+ if ((master->schemtype == SECONDARY) && (master->symschem != NULL))
+ master = master->symschem;
+
+ if (master->schemtype != PRIMARY && areawin->stack != NULL) {
+ cfrom = areawin->stack->thisinst->thisobject;
+ snew = parseinfo(cfrom, master, cfrom->calls, NULL, mode, FALSE, TRUE);
+ }
+ else {
+ Calllist loccalls;
+
+ loccalls.cschem = NULL;
+ loccalls.callobj = master;
+ loccalls.callinst = areawin->topinstance;
+ loccalls.devindex = -1;
+ loccalls.ports = NULL;
+ loccalls.next = NULL;
+
+ snew = parseinfo(NULL, master, &loccalls, NULL, mode, FALSE, TRUE);
+ }
+ Tcl_SetResult(interp, snew, TCL_DYNAMIC);
+
+ } break;
+
+ case UnConnectIdx: /* disassociate the page with another one */
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "unconnect [<secondary>]");
+ return TCL_ERROR;
+ }
+ else if (objc == 3) {
+ result = Tcl_GetIntFromObj(interp, objv[2], &spage);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ slave = NameToPageObject(Tcl_GetString(objv[2]), NULL, &spage);
+ }
+ else {
+ if (spage >= xobjs.pages) {
+ Tcl_SetResult(interp, "Bad page number for secondary schematic", NULL);
+ return TCL_ERROR;
+ }
+ slave = xobjs.pagelist[spage]->pageinst->thisobject;
+ }
+ if ((slave == NULL) || (is_page(slave) < 0)) {
+ Tcl_SetResult(interp, "Error determining secondary schematic", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ slave = topobject;
+ spage = areawin->page;
+ }
+ if (slave->symschem == NULL || slave->symschem->schemtype !=
+ PRIMARY) {
+ Tcl_SetResult(interp, "Page is not a secondary schematic", NULL);
+ return TCL_ERROR;
+ }
+
+ destroynets(slave->symschem);
+ slave->schemtype = PRIMARY;
+ slave->symschem = NULL;
+ break;
+
+ case ConnectIdx: /* associate the page with another one */
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "connect <primary> [<secondary>]");
+ return TCL_ERROR;
+ }
+ else if (objc == 4) {
+ result = Tcl_GetIntFromObj(interp, objv[3], &spage);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ slave = NameToPageObject(Tcl_GetString(objv[3]), NULL, &spage);
+ }
+ else {
+ if (spage >= xobjs.pages) {
+ Tcl_SetResult(interp, "Bad page number for secondary schematic", NULL);
+ return TCL_ERROR;
+ }
+ slave = xobjs.pagelist[spage]->pageinst->thisobject;
+ }
+ if ((slave == NULL) || (is_page(slave) < 0)) {
+ Tcl_SetResult(interp, "Error determining secondary schematic", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ slave = topobject;
+ spage = areawin->page;
+ destroynets(slave);
+ }
+
+ result = Tcl_GetIntFromObj(interp, objv[2], &mpage);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ master = NameToPageObject(Tcl_GetString(objv[2]), NULL, &mpage);
+ }
+ else
+ mpage--;
+
+ if ((mpage >= xobjs.pages) || (xobjs.pagelist[mpage]->pageinst == NULL)) {
+ Tcl_SetResult(interp, "Bad page number for master schematic", NULL);
+ return TCL_ERROR;
+ }
+ else if (mpage == areawin->page) {
+ Tcl_SetResult(interp, "Attempt to specify schematic "
+ "as its own master", NULL);
+ return TCL_ERROR;
+ }
+ if (xobjs.pagelist[mpage]->pageinst->thisobject->symschem == slave) {
+ Tcl_SetResult(interp, "Attempt to create recursive "
+ "primary/secondary schematic relationship", NULL);
+ return TCL_ERROR;
+ }
+ master = xobjs.pagelist[mpage]->pageinst->thisobject;
+ destroynets(master);
+
+ if ((master == NULL) || (is_page(master) < 0)) {
+ Tcl_SetResult(interp, "Error determining master schematic", NULL);
+ return TCL_ERROR;
+ }
+
+ slave->schemtype = SECONDARY;
+ slave->symschem = master;
+ break;
+
+ case UnHighLightIdx: /* remove network connectivity highlight */
+ if (objc == 2) {
+ highlightnetlist(topobject, areawin->topinstance, 0);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no options)");
+ return TCL_ERROR;
+ }
+ break;
+
+ case HighLightIdx: /* highlight network connectivity */
+ if (objc == 2) {
+ startconnect(NULL, NULL, NULL);
+ break;
+ }
+ /* drop through */
+ case PositionIdx:
+ case SelectIdx: /* select the first element in the indicated net */
+ {
+ int netid, lbus, i;
+ XPoint newpos, *netpos;
+ char *tname;
+ Genericlist *lnets, *netlist;
+ buslist *sbus;
+ LabellistPtr llist;
+ PolylistPtr plist;
+ short *newselect;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "network");
+ return TCL_ERROR;
+ }
+
+ result = GetPositionFromList(interp, objv[2], &newpos);
+ if (result == TCL_OK) { /* find net at indicated position */
+ areawin->save = newpos;
+ connectivity(NULL, NULL, NULL);
+ /* should there be any result here? */
+ break;
+ }
+ else { /* assume objv[2] is net name */
+ Tcl_ResetResult(interp);
+ tname = Tcl_GetString(objv[2]);
+ lnets = nametonet(topobject, areawin->topinstance, tname);
+ if (lnets == NULL) {
+ Tcl_SetResult(interp, "No such network ", NULL);
+ Tcl_AppendElement(interp, tname);
+ break;
+ }
+ switch (idx) {
+ case HighLightIdx:
+ netlist = (Genericlist *)malloc(sizeof(Genericlist));
+
+ /* Erase any existing highlights first */
+ highlightnetlist(topobject, areawin->topinstance, 0);
+ netlist->subnets = 0;
+ copy_bus(netlist, lnets);
+ topobject->highlight.netlist = netlist;
+ topobject->highlight.thisinst = areawin->topinstance;
+ highlightnetlist(topobject, areawin->topinstance, 1);
+ if (netlist->subnets == 0) {
+ netid = netlist->net.id;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(netlist->net.id));
+ }
+ else {
+ rdict = Tcl_NewListObj(0, NULL);
+ for (lbus = 0; lbus < netlist->subnets; lbus++) {
+ sbus = netlist->net.list + lbus;
+ netid = sbus->netid;
+ Tcl_ListObjAppendElement(interp, rdict, Tcl_NewIntObj(netid));
+ }
+ Tcl_SetObjResult(interp, rdict);
+ }
+ break;
+
+ /* Return a position belonging to the net. If this is a bus, */
+ /* we return the position of the 1st subnet. At some point, */
+ /* this should be expanded to return a point per subnet. */
+
+ case PositionIdx:
+ if (lnets->subnets == 0)
+ netid = lnets->net.id;
+ else
+ netid = (lnets->net.list)->netid;
+
+ netpos = NetToPosition(lnets->net.id, topobject);
+ rdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, rdict, Tcl_NewIntObj(netpos->x));
+ Tcl_ListObjAppendElement(interp, rdict, Tcl_NewIntObj(netpos->y));
+ Tcl_SetObjResult(interp, rdict);
+ break;
+
+ /* Select everything in the network. To-do: allow specific */
+ /* selection of labels, wires, or a single element in the net */
+
+ case SelectIdx:
+ unselect_all();
+ rdict = Tcl_NewListObj(0, NULL);
+ for (llist = topobject->labels; llist != NULL;
+ llist = llist->next) {
+ if (match_buses((Genericlist *)llist, (Genericlist *)lnets, 0)) {
+ i = GetPartNumber((genericptr)llist->label, topobject, LABEL);
+ if (i >= 0) {
+ newselect = allocselect();
+ *newselect = i;
+ Tcl_ListObjAppendElement(interp, rdict,
+ Tcl_NewHandleObj((genericptr)llist->label));
+ }
+ }
+ }
+ for (plist = topobject->polygons; plist != NULL;
+ plist = plist->next) {
+ if (match_buses((Genericlist *)plist, (Genericlist *)lnets, 0)) {
+ i = GetPartNumber((genericptr)plist->poly, topobject, POLYGON);
+ if (i >= 0) {
+ newselect = allocselect();
+ *newselect = i;
+ Tcl_ListObjAppendElement(interp, rdict,
+ Tcl_NewHandleObj((genericptr)plist->poly));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, rdict);
+ refresh(NULL, NULL, NULL);
+ break;
+ }
+ }
+ } break;
+
+ case UpdateIdx: /* destroy and regenerate the current netlist */
+ destroynets(areawin->topinstance->thisobject);
+ if ((result = updatenets(areawin->topinstance, quiet)) < 0) {
+ Tcl_SetResult(interp, "Check circuit for infinite recursion.", NULL);
+ return TCL_ERROR;
+ }
+ else if (result == 0) {
+ Tcl_SetResult(interp, "Failure to generate a network.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case MakeIdx: /* generate Tcl-list netlist */
+ rdict = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, rdict, Tcl_NewStringObj("globals", 7));
+ Tcl_ListObjAppendElement(interp, rdict, tclglobals(areawin->topinstance));
+ Tcl_ListObjAppendElement(interp, rdict, Tcl_NewStringObj("circuit", 7));
+ Tcl_ListObjAppendElement(interp, rdict, tcltoplevel(areawin->topinstance));
+
+ Tcl_SetObjResult(interp, rdict);
+ break;
+
+ case AutoNumberIdx: /* auto-number circuit components */
+ if (checkvalid(topobject) == -1) {
+ destroynets(topobject);
+ createnets(areawin->topinstance, FALSE);
+ }
+ else {
+ cleartraversed(topobject);
+ clear_indices(topobject);
+ }
+ if ((objc == 3) && !strcmp(Tcl_GetString(objv[2]), "-forget")) {
+ cleartraversed(topobject);
+ unnumber(topobject);
+ }
+ else {
+ cleartraversed(topobject);
+ resolve_indices(topobject, FALSE); /* Do fixed assignments first */
+ cleartraversed(topobject);
+ resolve_indices(topobject, TRUE); /* Now do the auto-numbering */
+ }
+ break;
+
+ case RatsNestIdx:
+ /* Experimental netlist stuff! */
+ ratsnest(areawin->topinstance);
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Return current position */
+/*----------------------------------------------------------------------*/
+
+int xctcl_here(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_Obj *listPtr, *objPtr;
+ XPoint newpos;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 0, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ newpos = UGetCursorPos();
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewIntObj((int)newpos.x);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+
+ objPtr = Tcl_NewIntObj((int)newpos.y);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+
+ Tcl_SetObjResult(interp, listPtr);
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* Argument-converting wrappers from Tcl command callback to xcircuit */
+/*----------------------------------------------------------------------*/
+
+int xctcl_pan(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, idx;
+ double frac = 0.0;
+ XPoint newpos, wpoint;
+ static char *directions[] = {"here", "left", "right", "up", "down",
+ "center", "follow", NULL};
+ enum DirIdx {
+ DirHere, DirLeft, DirRight, DirUp, DirDown, DirCenter, DirFollow
+ };
+
+ if (objc != 2 && objc != 3) {
+ Tcl_WrongNumArgs(interp, 0, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ /* Check against keywords */
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)directions,
+ "option", 0, &idx) != TCL_OK) {
+ result = GetPositionFromList(interp, objv[1], &newpos);
+ if (result != TCL_OK) return result;
+ idx = 5;
+ }
+ else
+ newpos = UGetCursorPos();
+
+ user_to_window(newpos, &wpoint);
+
+ switch(idx) {
+ case DirHere:
+ case DirCenter:
+ case DirFollow:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 0, objv, "(no arguments)");
+ }
+ break;
+ default:
+ if (objc == 2) frac = 0.3;
+ else
+ Tcl_GetDoubleFromObj(interp, objv[2], &frac);
+ }
+
+ panbutton((u_int)idx, wpoint.x, wpoint.y, (float)frac);
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_zoom(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, idx;
+ float save;
+ double factor;
+ XPoint newpos, wpoint;
+
+ static char *subCmds[] = {"in", "out", "view", "factor", NULL};
+ enum SubIdx {
+ InIdx, OutIdx, ViewIdx, FactorIdx
+ };
+
+ newpos = UGetCursorPos();
+ user_to_window(newpos, &wpoint);
+
+ if (objc == 1)
+ zoomview(NULL, NULL, NULL);
+ else if ((result = Tcl_GetDoubleFromObj(interp, objv[1], &factor)) != TCL_OK)
+ {
+ Tcl_ResetResult(interp);
+ if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)subCmds,
+ "option", 0, &idx) != TCL_OK) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ switch(idx) {
+ case InIdx:
+ zoominrefresh(wpoint.x, wpoint.y);
+ break;
+ case OutIdx:
+ zoomoutrefresh(wpoint.x, wpoint.y);
+ break;
+ case ViewIdx:
+ zoomview(NULL, NULL, NULL);
+ break;
+ case FactorIdx:
+ if (objc == 2) {
+ Tcl_Obj *objPtr = Tcl_NewDoubleObj((double)areawin->zoomfactor);
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ }
+ else if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (!strcmp(Tcl_GetString(objv[2]), "default"))
+ factor = SCALEFAC;
+ else {
+ result = Tcl_GetDoubleFromObj(interp, objv[2], &factor);
+ if (result != TCL_OK) return result;
+ if (factor <= 0) {
+ Tcl_SetResult(interp, "Negative/Zero zoom factors not allowed.",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (factor < 1.0) factor = 1.0 / factor;
+ }
+ if ((float)factor == areawin->zoomfactor) break;
+ Wprintf("Zoom factor changed from %2.1f to %2.1f",
+ areawin->zoomfactor, (float)factor);
+ areawin->zoomfactor = (float) factor;
+ break;
+ }
+ }
+ else {
+ save = areawin->zoomfactor;
+
+ if (factor < 1.0) {
+ areawin->zoomfactor = (float)(1.0 / factor);
+ zoomout(wpoint.x, wpoint.y);
+ }
+ else {
+ areawin->zoomfactor = (float)factor;
+ zoomin(wpoint.x, wpoint.y);
+ }
+ refresh(NULL, NULL, NULL);
+ areawin->zoomfactor = save;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Get a color, either by name or by integer index. */
+/* If "append" is TRUE, then if the color is not in the existing list */
+/* of colors, it will be added to the list. */
+/*----------------------------------------------------------------------*/
+
+int GetColorFromObj(Tcl_Interp *interp, Tcl_Obj *obj, int *cindex, Boolean append)
+{
+ char *cname;
+ int result;
+
+ if (cindex == NULL) return TCL_ERROR;
+
+ cname = Tcl_GetString(obj);
+ if (!strcmp(cname, "inherit")) {
+ *cindex = DEFAULTCOLOR;
+ }
+ else {
+ result = Tcl_GetIntFromObj(interp, obj, cindex);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ *cindex = query_named_color(cname);
+ if (*cindex == BADCOLOR) {
+ *cindex = ERRORCOLOR;
+ Tcl_SetResult(interp, "Unknown color name ", NULL);
+ Tcl_AppendElement(interp, cname);
+ return TCL_ERROR;
+ }
+ else if (*cindex == ERRORCOLOR) {
+ if (append)
+ *cindex = addnewcolorentry(xc_alloccolor(cname));
+ else {
+ Tcl_SetResult(interp, "Color ", NULL);
+ Tcl_AppendElement(interp, cname);
+ Tcl_AppendElement(interp, "is not in the color table.");
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+ }
+
+ if ((*cindex >= number_colors) || (*cindex < DEFAULTCOLOR)) {
+ Tcl_SetResult(interp, "Color index out of range", NULL);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_color(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, nidx, cindex, ccol, idx, i;
+ char *colorname, *option;
+
+ static char *subCmds[] = {"set", "index", "value", "get", "add",
+ "override", NULL};
+ enum SubIdx { SetIdx, IndexIdx, ValueIdx, GetIdx, AddIdx, OverrideIdx };
+
+ nidx = 2;
+ result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds, "option", 0,
+ &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case SetIdx:
+ if ((objc - nidx) == 2) {
+ result = GetColorFromObj(interp, objv[nidx + 1], &cindex, TRUE);
+ if (result != TCL_OK) return result;
+ setcolor((Tk_Window)clientData, cindex);
+ /* Tag callback performed by setcolormarks() via setcolor() */
+ return TCL_OK;
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "set <color> | inherit");
+ return TCL_ERROR;
+ }
+ break;
+
+ case IndexIdx:
+ /* Return the index of the color */
+ if ((objc - nidx) == 2) {
+ result = GetColorFromObj(interp, objv[nidx + 1], &cindex, TRUE);
+ if (result != TCL_OK) return result;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(cindex));
+ return TCL_OK;
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "index <color> | inherit");
+ return TCL_ERROR;
+ }
+ break;
+
+ case ValueIdx:
+ /* Return the value of the color. For use with parameterized color */
+ if ((objc - nidx) == 2) {
+ result = GetColorFromObj(interp, objv[nidx + 1], &cindex, TRUE);
+ if (result != TCL_OK) return result;
+ else if (cindex < 0 || cindex >= number_colors) {
+ Tcl_SetResult(interp, "Color index out of range", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(colorlist[cindex].color.pixel));
+ return TCL_OK;
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "value <color>");
+ return TCL_ERROR;
+ }
+ break;
+
+ case GetIdx:
+ /* Check for "-all" switch */
+ if ((objc - nidx) == 2) {
+ option = Tcl_GetString(objv[nidx + 1]);
+ if (!strncmp(option, "-all", 4)) {
+ for (i = 0; i < number_colors; i++) {
+ char colorstr[14];
+ sprintf(colorstr, "#%04x%04x%04x",
+ colorlist[i].color.red,
+ colorlist[i].color.green,
+ colorlist[i].color.blue);
+ Tcl_AppendElement(interp, colorstr);
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "get [-all]");
+ return TCL_ERROR;
+ }
+ break;
+ }
+
+ if (areawin->selects > 0) { /* operation on element */
+ genericptr genobj = SELTOGENERIC(areawin->selectlist);
+ ccol = (int)genobj->color;
+ }
+ else /* global setting */
+ ccol = areawin->color;
+
+ /* Find and return the index of the color */
+ if (ccol == DEFAULTCOLOR)
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("inherit", 7));
+ else {
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == ccol)
+ break;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+ }
+ break;
+
+ case AddIdx:
+ if ((objc - nidx) == 2) {
+ colorname = Tcl_GetString(objv[nidx + 1]);
+ if (strlen(colorname) == 0) return TCL_ERROR;
+ cindex = addnewcolorentry(xc_alloccolor(colorname));
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(cindex));
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "add <color_name>");
+ return TCL_ERROR;
+ }
+ break;
+
+ case OverrideIdx:
+ flags |= COLOROVERRIDE;
+ return TCL_OK; /* no tag callback */
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_delete(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result = ParseElementArguments(interp, objc, objv, NULL, ALL_TYPES);
+
+ if (result != TCL_OK) return result;
+
+ /* delete element (call library delete if in catalog) */
+ if (areawin->selects > 0) {
+ if (eventmode == CATALOG_MODE)
+ catdelete();
+ else
+ deletebutton(0, 0); /* Note: arguments are not used */
+ }
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Note that when using "undo series", it is the responsibility of the */
+/* caller to make sure that every "start" is matched by an "end". */
+/*----------------------------------------------------------------------*/
+
+int xctcl_undo(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ if ((objc == 3) && !strcmp(Tcl_GetString(objv[1]), "series")) {
+
+ if (!strcmp(Tcl_GetString(objv[2]), "start")) {
+ if (undo_collect < 255) undo_collect++;
+ }
+ else if (!strcmp(Tcl_GetString(objv[2]), "end")) {
+ if (undo_collect > 0) undo_collect--;
+ undo_finish_series();
+ }
+ else if (!strcmp(Tcl_GetString(objv[2]), "cancel")) {
+ undo_collect = (u_char)0;
+ undo_finish_series();
+ }
+ else {
+ Tcl_SetResult(interp, "Usage: undo series <start|end|cancel>", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else if (objc == 1) {
+ undo_action();
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "[series <start|end>");
+ return TCL_ERROR;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_redo(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ redo_action();
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_move(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ XPoint position;
+ int nidx = 3;
+ int result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+
+ if (result != TCL_OK) return result;
+
+ if (areawin->selects == 0) {
+ Tcl_SetResult(interp, "Error in move setup: nothing selected.", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((objc - nidx) == 0) {
+ eventmode = MOVE_MODE;
+ u2u_snap(&areawin->save);
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask,
+ (Tk_EventProc *)xctk_drag, NULL);
+ }
+ else if ((objc - nidx) >= 1) {
+ if ((objc - nidx) == 2) {
+ if (!strcmp(Tcl_GetString(objv[nidx]), "relative")) {
+ if ((result = GetPositionFromList(interp, objv[nidx + 1],
+ &position)) != TCL_OK) {
+ Tcl_SetResult(interp, "Position must be {x y} list", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "relative {x y}");
+ return TCL_ERROR;
+ }
+ }
+ else {
+ if ((result = GetPositionFromList(interp, objv[nidx],
+ &position)) != TCL_OK) {
+ Tcl_SetResult(interp, "Position must be {x y} list", NULL);
+ return TCL_ERROR;
+ }
+ position.x -= areawin->save.x;
+ position.y -= areawin->save.y;
+ }
+ placeselects(position.x, position.y, NULL);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "[relative] {x y}");
+ return TCL_ERROR;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_copy(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ XPoint position;
+ Tcl_Obj *listPtr;
+ int nidx = 3;
+ int result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+
+ if (result != TCL_OK) return result;
+
+ if ((objc - nidx) == 0) {
+ if (areawin->selects > 0) {
+ createcopies();
+ copydrag();
+ }
+ }
+ else if ((objc - nidx) >= 1) {
+ if (areawin->selects == 0) {
+ Tcl_SetResult(interp, "Error in copy: nothing selected.", NULL);
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ if (!strcmp(Tcl_GetString(objv[nidx]), "relative")) {
+ if ((result = GetPositionFromList(interp, objv[nidx + 1],
+ &position)) != TCL_OK) {
+ Tcl_SetResult(interp, "Position must be {x y} list", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "relative {x y}");
+ return TCL_ERROR;
+ }
+ }
+ else {
+ if ((result = GetPositionFromList(interp, objv[nidx],
+ &position)) != TCL_OK) {
+ Tcl_SetResult(interp, "Position must be {x y} list", NULL);
+ return TCL_ERROR;
+ }
+ position.x -= areawin->save.x;
+ position.y -= areawin->save.y;
+ }
+ createcopies();
+
+ listPtr = SelectToTclList(interp, areawin->selectlist, areawin->selects);
+ Tcl_SetObjResult(interp, listPtr);
+
+ placeselects(position.x, position.y, NULL);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "[relative] {x y}");
+ return TCL_ERROR;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_flip(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char *teststr;
+ int nidx = 2;
+ int result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ XPoint position;
+
+ if (result != TCL_OK) return result;
+
+ if ((objc - nidx) == 2) {
+ if ((result = GetPositionFromList(interp, objv[nidx + 1],
+ &position)) != TCL_OK)
+ return result;
+ }
+ else if ((objc - nidx) == 1) {
+ if (areawin->selects > 1)
+ position = UGetCursorPos();
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "horizontal|vertical [<center>]");
+ return TCL_ERROR;
+ }
+
+ teststr = Tcl_GetString(objv[nidx]);
+
+ switch(teststr[0]) {
+ case 'h': case 'H':
+ elementflip(&position);
+ break;
+ case 'v': case 'V':
+ elementvflip(&position);
+ break;
+ default:
+ Tcl_SetResult(interp, "Error: options are horizontal or vertical", NULL);
+ return TCL_ERROR;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_rotate(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int rval, nidx = 2;
+ int result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ XPoint position;
+
+ if (result != TCL_OK) return result;
+
+ /* No options --- return the rotation value(s) */
+ if ((objc - nidx) == 0) {
+ int i, numfound = 0;
+ Tcl_Obj *listPtr, *objPtr;
+ for (i = 0; i < areawin->selects; i++) {
+ objPtr = NULL;
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ objinstptr pinst = SELTOOBJINST(areawin->selectlist + i);
+ objPtr = Tcl_NewIntObj(pinst->rotation);
+ }
+ else if (SELECTTYPE(areawin->selectlist + i) == LABEL) {
+ labelptr plab = SELTOLABEL(areawin->selectlist + i);
+ objPtr = Tcl_NewIntObj(plab->rotation);
+ }
+ else if (SELECTTYPE(areawin->selectlist + i) == GRAPHIC) {
+ graphicptr gp = SELTOGRAPHIC(areawin->selectlist + i);
+ objPtr = Tcl_NewIntObj(gp->rotation);
+ }
+ if (objPtr != NULL) {
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances, graphic "
+ "images, or labels selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ result = Tcl_GetIntFromObj(interp, objv[nidx], &rval);
+ if (result != TCL_OK) return result;
+
+ if ((objc - nidx) == 2) {
+ if ((result = GetPositionFromList(interp, objv[nidx + 1],
+ &position)) != TCL_OK)
+ return result;
+ else {
+ elementrotate(rval, &position);
+ return XcTagCallback(interp, objc, objv);
+ }
+ }
+ else if ((objc - nidx) == 1) {
+ position = UGetCursorPos();
+ elementrotate(rval, &position);
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ Tcl_WrongNumArgs(interp, 1, objv, "<angle> [<center>]");
+ return TCL_ERROR;
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_edit(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result = ParseElementArguments(interp, objc, objv, NULL, ALL_TYPES);
+
+ if (result != TCL_OK) return result;
+
+ /* To be done---edit element */
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Support procedure for xctcl_param: Given a pointer to a parameter, */
+/* return the value of the parameter as a pointer to a Tcl object. */
+/* This takes care of the fact that the parameter value can be a */
+/* string, integer, or float, depending on the parameter type. */
+/* */
+/* If "verbatim" is true, then expression parameters return the string */
+/* representation of the expression, not the result, and indirect */
+/* parameters return the parameter name referenced, not the value. */
+/* */
+/* refinst, if non-NULL, is the instance containing ops, used when */
+/* "verbatim" is true and the parameter is indirectly referenced. */
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *GetParameterValue(objectptr refobj, oparamptr ops, Boolean verbatim,
+ objinstptr refinst)
+{
+ Tcl_Obj *robj;
+ char *refkey;
+
+ if (verbatim && (refinst != NULL) &&
+ ((refkey = find_indirect_param(refinst, ops->key)) != NULL)) {
+ robj = Tcl_NewStringObj(refkey, strlen(refkey));
+ return robj;
+ }
+
+ switch (ops->type) {
+ case XC_STRING:
+ robj = TclGetStringParts(ops->parameter.string);
+ break;
+ case XC_EXPR:
+ if (verbatim)
+ robj = Tcl_NewStringObj(ops->parameter.expr,
+ strlen(ops->parameter.expr));
+ else
+ robj = evaluate_raw(refobj, ops, refinst, NULL);
+ break;
+ case XC_INT:
+ robj = Tcl_NewIntObj(ops->parameter.ivalue);
+ break;
+ case XC_FLOAT:
+ robj = Tcl_NewDoubleObj((double)ops->parameter.fvalue);
+ break;
+ }
+ return robj;
+}
+
+/*----------------------------------------------------------------------*/
+/* Given a pointer to a parameter and a Tcl object, set the parameter */
+/* to the value of the object. Return the standard Tcl return type */
+/* */
+/* If searchinst is non-NULL, then it refers to the level above in the */
+/* hierarchy, and we are supposed to set an indirect reference. */
+/*----------------------------------------------------------------------*/
+
+int SetParameterValue(Tcl_Interp *interp, oparamptr ops, Tcl_Obj *objv)
+{
+ int result, ivalue;
+ double dvalue;
+ stringpart *strptr = NULL, *newpart;
+
+ if (ops == NULL) {
+ Tcl_SetResult(interp, "Cannot set parameter value", NULL);
+ return TCL_ERROR;
+ }
+ switch (ops->type) {
+ case XC_FLOAT:
+ result = Tcl_GetDoubleFromObj(interp, objv, &dvalue);
+ if (result != TCL_OK) return result;
+ ops->parameter.fvalue = (float)dvalue;
+ break;
+ case XC_INT:
+ result = Tcl_GetIntFromObj(interp, objv, &ivalue);
+ if (result != TCL_OK) return result;
+ ops->parameter.ivalue = ivalue;
+ break;
+ case XC_EXPR:
+ ops->parameter.expr = strdup(Tcl_GetString(objv));
+ break;
+ case XC_STRING:
+ result = GetXCStringFromList(interp, objv, &strptr);
+ if (result != TCL_OK) return result;
+ freelabel(ops->parameter.string);
+ /* Must add a "param end" */
+ newpart = makesegment(&strptr, NULL);
+ newpart->nextpart = NULL;
+ newpart->type = PARAM_END;
+ newpart->data.string = (u_char *)NULL;
+ ops->parameter.string = strptr;
+ break;
+ }
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate the numeric parameter types to a string that the Tcl */
+/* "parameter" routine will recognize from the command line. */
+/*----------------------------------------------------------------------*/
+
+char *
+translateparamtype(int type)
+{
+ const char *param_types[] = {"numeric", "substring", "x position",
+ "y position", "style", "justification", "start angle", "end angle",
+ "radius", "minor axis", "rotation", "scale", "linewidth", "color",
+ "expression", "position", NULL};
+
+ if (type < 0) return NULL;
+ return (char *)param_types[type];
+}
+
+/*----------------------------------------------------------------------*/
+/* Parameter command: */
+/* */
+/* Normally, a selected element will produce a list of backwards- */
+/* referenced parameters (eparam). However, it is useful to pick up */
+/* the forwards-referenced parameters of an object instance, so that */
+/* parameters can be modified from the level above (e.g., to change */
+/* circuit component values, component indices, etc.). The optional */
+/* final argument "-forward" can be used to access this mode. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_param(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, j, value, idx, nidx = 4;
+ int result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ oparamptr ops, instops;
+ oparam temps;
+ eparamptr epp;
+ genericptr thiselem = NULL;
+ Tcl_Obj *plist, *kpair, *exprres;
+ objinstptr refinst;
+ objectptr refobj;
+ char *dash_opt;
+ Boolean verbatim = FALSE, indirection = FALSE, forwarding = FALSE;
+
+ static char *subCmds[] = {"allowed", "get", "type", "default", "set", "make",
+ "replace", "forget", "delete", NULL};
+ enum SubIdx {
+ AllowedIdx, GetIdx, TypeIdx, DefaultIdx, SetIdx, MakeIdx, ReplaceIdx,
+ ForgetIdx, DeleteIdx
+ };
+
+ /* The order of these type names must match the enumeration in xcircuit.h */
+
+ static char *param_types[] = {"numeric", "substring", "x position",
+ "y position", "style", "justification", "start angle", "end angle",
+ "radius", "minor axis", "rotation", "scale", "linewidth", "color",
+ "expression", "position", NULL}; /* (jdk) */
+
+ /* The first object instance in the select list becomes "thiselem", */
+ /* if such exists. Otherwise, it remains null. */
+
+ for (j = 0; j < areawin->selects; j++) {
+ if (SELECTTYPE(areawin->selectlist + j) == OBJINST) {
+ thiselem = SELTOGENERIC(areawin->selectlist + j);
+ break;
+ }
+ }
+
+ if (objc - nidx < 1)
+ idx = GetIdx;
+ else {
+ dash_opt = Tcl_GetString(objv[nidx]);
+ if (*dash_opt == '-')
+ idx = GetIdx;
+ else {
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK)
+ return result;
+ }
+ }
+
+ /* Use the topobject by default */
+ refinst = areawin->topinstance;
+ refobj = topobject;
+
+ /* command-line switches */
+
+ dash_opt = Tcl_GetString(objv[objc - 1]);
+ while (*dash_opt == '-') {
+
+ /* If an object instance is selected, we list backwards-referenced */
+ /* (eparam) parameters, unless the command ends in "-forward". */
+
+ if (!strncmp(dash_opt + 1, "forw", 4)) {
+ switch (idx) {
+ case SetIdx:
+ case GetIdx:
+ case TypeIdx:
+ case MakeIdx:
+ case DeleteIdx:
+ case ForgetIdx:
+ case DefaultIdx:
+ if (thiselem && IS_OBJINST(thiselem)) {
+ refinst = (objinstptr)thiselem;
+ refobj = refinst->thisobject;
+ thiselem = NULL;
+ forwarding = TRUE;
+ }
+ break;
+ }
+ }
+ else if (!strncmp(dash_opt + 1, "verb", 4)) {
+ verbatim = TRUE;
+ }
+ else if (!strncmp(dash_opt + 1, "ind", 3)) {
+ indirection = TRUE;
+ }
+
+ objc--;
+ if (objc == 0) {
+ Tcl_SetResult(interp, "Must have a valid option", NULL);
+ return TCL_ERROR;
+ }
+ dash_opt = Tcl_GetString(objv[objc - 1]);
+ }
+
+
+ switch (idx) {
+ case AllowedIdx:
+ for (i = 0; i < (sizeof(param_types) / sizeof(char *)); i++)
+ if ((thiselem == NULL) || (param_select[i] & thiselem->type))
+ Tcl_AppendElement(interp, param_types[i]);
+
+ break;
+
+ case GetIdx:
+ case TypeIdx:
+
+ if (objc == nidx + 2) {
+
+ /* Check argument against all parameter keys */
+ ops = find_param(refinst, Tcl_GetString(objv[nidx + 1]));
+ if (ops == NULL) {
+ /* Otherwise, the argument must be a parameter type. */
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)param_types, "parameter type",
+ 0, &value)) != TCL_OK) {
+ Tcl_SetResult(interp, "Must have a valid key or parameter type",
+ NULL);
+ return result;
+ }
+ }
+
+ /* Return the value of the indicated parameter */
+
+ plist = Tcl_NewListObj(0, NULL);
+ if (thiselem == NULL) {
+ if (ops != NULL) {
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ else
+ Tcl_ListObjAppendElement(interp, plist,
+ Tcl_NewStringObj(param_types[ops->which],
+ strlen(param_types[ops->which])));
+ }
+ else {
+ for (ops = refobj->params; ops != NULL; ops = ops->next) {
+ instops = find_param(refinst, ops->key);
+ if (instops->which == value) {
+ kpair = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(instops->key, strlen(instops->key)));
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, instops, verbatim,
+ refinst));
+ else
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(param_types[instops->which],
+ strlen(param_types[instops->which])));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+ }
+ }
+ }
+ else {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ instops = find_param(refinst, epp->key);
+ if (instops->which == value) {
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, instops, verbatim, refinst));
+ else
+ Tcl_ListObjAppendElement(interp, plist,
+ Tcl_NewStringObj(param_types[instops->which],
+ strlen(param_types[instops->which])));
+ }
+ }
+
+ /* Search label for parameterized substrings. These are */
+ /* backwards-referenced parameters, although they are */
+ /* not stored in the eparam record of the label. */
+
+ if ((value == P_SUBSTRING) && IS_LABEL(thiselem)) {
+ stringpart *cstr;
+ labelptr clab = (labelptr)thiselem;
+ for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart) {
+ if (cstr->type == PARAM_START) {
+ kpair = Tcl_NewListObj(0, NULL);
+ ops = find_param(refinst, cstr->data.string);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(ops->key, strlen(ops->key)));
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, ops, verbatim,
+ refinst));
+ else
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(param_types[ops->which],
+ strlen(param_types[ops->which])));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, plist);
+ }
+ else {
+ plist = Tcl_NewListObj(0, NULL);
+ if (thiselem == NULL) {
+ for (ops = refobj->params; ops != NULL; ops = ops->next) {
+ kpair = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(ops->key, strlen(ops->key)));
+ if (idx == GetIdx) {
+ instops = find_param(refinst, ops->key);
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, instops, verbatim, refinst));
+ }
+ else
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(param_types[ops->which],
+ strlen(param_types[ops->which])));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+ }
+ else {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ kpair = Tcl_NewListObj(0, NULL);
+ ops = find_param(refinst, epp->key);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(ops->key, strlen(ops->key)));
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ else
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(param_types[ops->which],
+ strlen(param_types[ops->which])));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+
+ /* Search label for parameterized substrings. These are */
+ /* backwards-referenced parameters, although they are */
+ /* not stored in the eparam record of the label. */
+
+ if (IS_LABEL(thiselem)) {
+ stringpart *cstr;
+ labelptr clab = (labelptr)thiselem;
+ for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart) {
+ if (cstr->type == PARAM_START) {
+ kpair = Tcl_NewListObj(0, NULL);
+ ops = find_param(refinst, cstr->data.string);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(ops->key, strlen(ops->key)));
+ if (idx == GetIdx)
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, ops, verbatim,
+ refinst));
+ else
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(param_types[ops->which],
+ strlen(param_types[ops->which])));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, plist);
+ }
+ break;
+
+ case DefaultIdx:
+ if (objc == nidx + 2) {
+ /* Check against keys */
+ ops = match_param(refobj, Tcl_GetString(objv[nidx + 1]));
+ if (ops == NULL) {
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)param_types, "parameter type",
+ 0, &value)) != TCL_OK) {
+ Tcl_SetResult(interp, "Must have a valid key or parameter type",
+ NULL);
+ return result;
+ }
+ }
+ else { /* get default value(s) */
+ plist = Tcl_NewListObj(0, NULL);
+ if (thiselem == NULL) {
+ if (ops != NULL) {
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ }
+ else {
+ for (ops = refobj->params; ops != NULL; ops = ops->next) {
+ if (ops->which == value) {
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ }
+ }
+ }
+ }
+ else {
+ for (epp = thiselem->passed; epp != NULL; epp = epp->next) {
+ ops = match_param(refobj, epp->key);
+ if (ops->which == value) {
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ }
+ }
+
+ /* search label for parameterized substrings */
+
+ if ((value == P_SUBSTRING) && IS_LABEL(thiselem)) {
+ stringpart *cstr;
+ labelptr clab = (labelptr)thiselem;
+ for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart) {
+ if (cstr->type == PARAM_START) {
+ ops = match_param(refobj, cstr->data.string);
+ if (ops != NULL)
+ Tcl_ListObjAppendElement(interp, plist,
+ GetParameterValue(refobj, ops, verbatim,
+ refinst));
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, plist);
+ }
+ }
+ else if (objc == nidx + 1) { /* list all parameters and their defaults */
+ plist = Tcl_NewListObj(0, NULL);
+ for (ops = refobj->params; ops != NULL; ops = ops->next) {
+ kpair = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, kpair,
+ Tcl_NewStringObj(ops->key, strlen(ops->key)));
+ Tcl_ListObjAppendElement(interp, kpair,
+ GetParameterValue(refobj, ops, verbatim, refinst));
+ Tcl_ListObjAppendElement(interp, plist, kpair);
+ }
+ Tcl_SetObjResult(interp, plist);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "default <type|key> [<value>]");
+ return TCL_ERROR;
+ }
+ break;
+
+ case SetIdx: /* currently, instances only. . .*/
+ if (objc == nidx + 3) { /* possibly to be expanded. . . */
+ char *key = Tcl_GetString(objv[nidx + 1]);
+ objinstptr searchinst = NULL;
+
+ /* Allow option "set" to act on more than one selection */
+
+ if (areawin->selects == 0) goto keycheck;
+
+ while (j < areawin->selects) {
+
+ refinst = SELTOOBJINST(areawin->selectlist + j);
+ refobj = refinst->thisobject;
+
+ /* Check against keys */
+keycheck:
+ instops = match_instance_param(refinst, key);
+ ops = match_param(refobj, key);
+ if (instops == NULL) {
+ if (ops == NULL) {
+ if (!forwarding || (areawin->selects <= 1)) {
+ Tcl_SetResult(interp, "Invalid key ", NULL);
+ Tcl_AppendElement(interp, key);
+ return TCL_ERROR;
+ }
+ else
+ goto next_param;
+ }
+ copyparams(refinst, refinst);
+ instops = match_instance_param(refinst, key);
+ }
+ else if (ops->type == XC_EXPR) {
+ /* If the expression is currently the default expression */
+ /* but the instance value is holding the last evaluated */
+ /* result, then we have to delete and regenerate the */
+ /* existing instance parameter ("verbatim" assumed even */
+ /* if not declared because you can't change the result */
+ /* of the expression). */
+
+ free_instance_param(refinst, instops);
+ instops = copyparameter(ops);
+ instops->next = refinst->params;
+ refinst->params = instops;
+ }
+ if (indirection) {
+ char *refkey = Tcl_GetString(objv[nidx + 2]);
+
+ if (refinst != areawin->topinstance)
+ searchinst = areawin->topinstance;
+ else if (areawin->stack) {
+ searchinst = areawin->stack->thisinst;
+ }
+ else {
+ resolveparams(refinst);
+ Tcl_SetResult(interp, "On top-level page: "
+ "no indirection possible!", NULL);
+ return TCL_ERROR;
+ }
+ if (match_param(searchinst->thisobject, refkey) == NULL) {
+ resolveparams(refinst);
+ Tcl_SetResult(interp, "Invalid indirect reference key", NULL);
+ return TCL_ERROR;
+ }
+ /* Create an eparam record in the instance */
+ epp = make_new_eparam(refkey);
+ epp->flags |= P_INDIRECT;
+ epp->pdata.refkey = strdup(key);
+ epp->next = refinst->passed;
+ refinst->passed = epp;
+ }
+ else
+ SetParameterValue(interp, instops, objv[nidx + 2]);
+ resolveparams(refinst);
+
+ /* Check if there are more selections to modify */
+
+next_param:
+ if (!forwarding) break;
+ while (++j != areawin->selects)
+ if (SELECTTYPE(areawin->selectlist + j) == OBJINST)
+ break;
+ }
+
+ /* Redraw everything (this could be finessed. . .) */
+ drawarea(areawin->area, (caddr_t)NULL, (caddr_t)NULL);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "set <key>");
+ return TCL_ERROR;
+ }
+ break;
+
+ case MakeIdx:
+ if (objc >= (nidx + 2) && objc <= (nidx + 4)) {
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)param_types, "parameter type",
+ 0, &value)) != TCL_OK)
+ return result;
+
+ if ((value == P_SUBSTRING) && (objc == (nidx + 4))) {
+ stringpart *strptr = NULL, *newpart;
+ result = GetXCStringFromList(interp, objv[nidx + 3], &strptr);
+ if (result != TCL_ERROR) {
+ if (makestringparam(refobj, Tcl_GetString(objv[nidx + 2]),
+ strptr) == -1)
+ return TCL_ERROR;
+ /* Add the "parameter end" marker to this string */
+ newpart = makesegment(&strptr, NULL);
+ newpart->nextpart = NULL;
+ newpart->type = PARAM_END;
+ newpart->data.string = (u_char *)NULL;
+ }
+ }
+ else if (value == P_SUBSTRING) {
+ /* Get parameter value from selection */
+ startparam((Tk_Window)clientData, (pointertype)value,
+ (caddr_t)Tcl_GetString(objv[nidx + 2]));
+ }
+ else if ((value == P_EXPRESSION) && (objc == (nidx + 4))) {
+ temps.type = XC_EXPR;
+ temps.parameter.expr = Tcl_GetString(objv[nidx + 3]);
+ exprres = evaluate_raw(refobj, &temps, refinst, &result);
+
+ if (result != TCL_OK) {
+ Tcl_SetResult(xcinterp, "Bad result from expression!", NULL);
+ /* Not fatal to have a bad expression result. . . */
+ /* return result; */
+ }
+ if (makeexprparam(refobj, Tcl_GetString(objv[nidx + 2]),
+ temps.parameter.expr, P_EXPRESSION) == NULL)
+ return TCL_ERROR;
+ }
+
+ /* All other types are parsed as either a numeric value */
+ /* (integer or float), or an expression that evaluates */
+ /* to a numeric value. */
+
+ else if (((value == P_NUMERIC) && (objc == (nidx + 4))) ||
+ objc == (nidx + 3)) {
+ double tmpdbl;
+
+ i = (value == P_NUMERIC) ? 3 : 2;
+
+ result = Tcl_GetDoubleFromObj(interp, objv[nidx + i], &tmpdbl);
+ if (result != TCL_ERROR) {
+ if (makefloatparam(refobj, Tcl_GetString(objv[nidx + i - 1]),
+ (float)tmpdbl) == -1)
+ return TCL_ERROR;
+ }
+ else {
+ char *newkey;
+
+ /* This may be an expression. Do a quick check to */
+ /* see if the string can be evaluated as a Tcl */
+ /* expression. If it returns a valid numeric result, */
+ /* then accept the expression. */
+
+ Tcl_ResetResult(interp);
+ temps.type = XC_EXPR;
+ temps.parameter.expr = Tcl_GetString(objv[nidx + i]);
+
+ exprres = evaluate_raw(refobj, &temps, refinst, &result);
+ if (result != TCL_OK) {
+ Tcl_SetResult(xcinterp, "Bad result from expression!", NULL);
+ return result;
+ }
+ result = Tcl_GetDoubleFromObj(interp, exprres, &tmpdbl);
+ if (result != TCL_ERROR) {
+ if ((newkey = makeexprparam(refobj, (value == P_NUMERIC) ?
+ Tcl_GetString(objv[nidx + i - 1]) : NULL,
+ temps.parameter.expr, value)) == NULL)
+ return TCL_ERROR;
+ else if (value != P_NUMERIC) {
+ /* Link the expression parameter to the element */
+ /* To-do: Handle cycles (one extra argument) */
+ genericptr pgen;
+ for (i = 0; i < areawin->selects; i++) {
+ pgen = SELTOGENERIC(areawin->selectlist + i);
+ makenumericalp(&pgen, value, newkey, 0);
+ }
+ }
+ }
+ else {
+ Tcl_SetResult(xcinterp, "Expression evaluates to "
+ "non-numeric type!", NULL);
+ return result;
+ }
+ }
+ }
+ else if (((value != P_NUMERIC) && (objc == (nidx + 4))) ||
+ objc == (nidx + 3)) {
+ int cycle;
+ i = objc - 1;
+ if (value == P_POSITION || value == P_POSITION_X ||
+ value == P_POSITION_Y) {
+ if (objc == nidx + 4) {
+ result = Tcl_GetIntFromObj(interp, objv[i - 1], &cycle);
+ if (result == TCL_ERROR) {
+ Tcl_ResetResult(interp);
+ startparam((Tk_Window)clientData, (pointertype)value,
+ Tcl_GetString(objv[i]));
+ }
+ else {
+ parameterize(value, NULL, (short)cycle);
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "make position cycle <value>");
+ return TCL_ERROR;
+ }
+ }
+ else {
+ if (objc == nidx + 3)
+ startparam((Tk_Window)clientData, (pointertype)value,
+ Tcl_GetString(objv[i]));
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "make <numeric_type> <value>");
+ return TCL_ERROR;
+ }
+ }
+ }
+ else {
+ if ((value == P_SUBSTRING) || (value == P_NUMERIC) ||
+ (value == P_EXPRESSION)) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "make substring|numeric|expression <key>");
+ return TCL_ERROR;
+ }
+ else
+ startparam((Tk_Window)clientData, (pointertype)value, NULL);
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "make <type> [<key>]");
+ return TCL_ERROR;
+ }
+ break;
+
+ case ReplaceIdx:
+ /* Calls unparameterize---replaces text with the instance value, */
+ /* or replaces a numeric parameter with the instance values by */
+ /* unparameterizing the element. Don't use with parameter keys. */
+
+ if (objc == nidx + 2) {
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)param_types, "parameter type",
+ 0, &value)) != TCL_OK)
+ return result;
+ unparameterize(value);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "replace <type>");
+ return TCL_ERROR;
+ }
+ break;
+
+ case DeleteIdx:
+ case ForgetIdx:
+
+ if (objc == nidx + 2) {
+ /* Check against keys */
+ ops = match_param(refobj, Tcl_GetString(objv[nidx + 1]));
+ if (ops == NULL) {
+ Tcl_SetResult(interp, "Invalid parameter key", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ free_object_param(refobj, ops);
+ /* Redraw everything */
+ drawarea(areawin->area, (caddr_t)NULL, (caddr_t)NULL);
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "forget <key>");
+ return TCL_ERROR;
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_select(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char *argstr;
+ short *newselect;
+ int selected_prior, selected_new, nidx, result;
+ Tcl_Obj *listPtr;
+ XPoint newpos;
+
+ if (objc == 1) {
+ /* Special case: "select" by itself returns the number of */
+ /* selected objects. */
+ Tcl_SetObjResult(interp, Tcl_NewIntObj((int)areawin->selects));
+ return XcTagCallback(interp, objc, objv);
+ }
+ else {
+ nidx = 1;
+ result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ if (result != TCL_OK) return result;
+ }
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "here | get | <element_handle>");
+ return TCL_ERROR;
+ }
+
+ if (nidx == 1) {
+ argstr = Tcl_GetString(objv[1]);
+ if (!strcmp(argstr, "here")) {
+ newpos = UGetCursorPos();
+ areawin->save = newpos;
+ selected_prior = areawin->selects;
+ newselect = select_element(ALL_TYPES);
+ selected_new = areawin->selects - selected_prior;
+ }
+ else if (!strcmp(argstr, "get")) {
+ newselect = areawin->selectlist;
+ selected_new = areawin->selects;
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "here | get | <object_handle>");
+ return TCL_ERROR;
+ }
+
+ listPtr = SelectToTclList(interp, newselect, selected_new);
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_deselect(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, j, k, result, numobjs;
+ pointertype ehandle;
+ char *argstr;
+ Tcl_Obj *lobj;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "[element_handle]");
+ return TCL_ERROR;
+ }
+ else if (objc == 3 || (objc == 2 && !strcmp(Tcl_GetString(objv[0]), "deselect"))) {
+
+ argstr = Tcl_GetString(objv[1]);
+ if (strcmp(argstr, "selected")) {
+
+ /* check for object handles (integer list) */
+
+ result = Tcl_ListObjLength(interp, objv[1], &numobjs);
+ if (result != TCL_OK) return result;
+
+ for (j = 0; j < numobjs; j++) {
+ result = Tcl_ListObjIndex(interp, objv[1], j, &lobj);
+ if (result != TCL_OK) return result;
+ result = Tcl_GetHandleFromObj(interp, lobj, (void *)&ehandle);
+ if (result != TCL_OK) return result;
+ i = GetPartNumber((genericptr)ehandle, topobject, ALL_TYPES);
+ if (i == -1) {
+ Tcl_SetResult(interp, "No such element exists.", NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < areawin->selects; i++) {
+ short *newselect = areawin->selectlist + i;
+ if ((genericptr)ehandle == SELTOGENERIC(newselect)) {
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(SELTOCOLOR(newselect));
+ geneasydraw(*newselect, DEFAULTCOLOR, topobject,
+ areawin->topinstance);
+
+ areawin->selects--;
+ for (k = i; k < areawin->selects; k++)
+ *(areawin->selectlist + k) = *(areawin->selectlist + k + 1);
+ if (areawin->selects == 0) {
+ free(areawin->selectlist);
+ freeselects(); /* specifically, free hierstack */
+ }
+ }
+ }
+ }
+ }
+ else
+ unselect_all();
+ }
+ else
+ startdesel((Tk_Window)clientData, NULL, NULL);
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_push(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result = ParseElementArguments(interp, objc, objv, NULL, OBJINST);
+
+ if (result != TCL_OK) return result;
+
+ pushobject(NULL);
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_pop(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ popobject((Tk_Window)clientData, 0, NULL);
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Object queries */
+/*----------------------------------------------------------------------*/
+
+int xctcl_object(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, j, idx, result, nidx, libno;
+ genericptr egen;
+ Tcl_Obj **newobjv, *ilist, *plist, *hobj;
+ pointertype ehandle;
+ objinstptr thisinst;
+ Boolean forceempty = FALSE;
+
+ static char *subCmds[] = {"make", "name", "parts", "library",
+ "handle", "hide", "unhide", "bbox", NULL};
+ enum SubIdx {
+ MakeIdx, NameIdx, PartsIdx, LibraryIdx, HandleIdx, HideIdx,
+ UnhideIdx, BBoxIdx
+ };
+
+ /* Check for option "-force" (create an object even if it has no contents) */
+ if (!strncmp(Tcl_GetString(objv[objc - 1]), "-forc", 5)) {
+ forceempty = TRUE;
+ objc--;
+ }
+
+ /* (revision) "object handle <name>" returns a handle (or null), so */
+ /* all commands can unambiguously operate on a handle (or nothing) */
+ /* in the second position. */
+
+ nidx = 0;
+
+ /* 2nd argument may be a handle, object name, or nothing. */
+ /* If nothing, the instance of the top-level page is assumed. */
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 0, objv, "object [handle] <option> ...");
+ return TCL_ERROR;
+ }
+
+ result = Tcl_GetHandleFromObj(interp, objv[1], (void *)&ehandle);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(interp);
+ ehandle = (pointertype)(areawin->topinstance);
+ }
+ else {
+ nidx = 1;
+ objc--;
+ }
+ egen = (genericptr)ehandle;
+
+ if (ELEMENTTYPE(egen) != OBJINST) {
+ Tcl_SetResult(interp, "handle does not point to an object instance!", NULL);
+ return TCL_ERROR;
+ }
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 0, objv, "object <handle> <option> ...");
+ return TCL_ERROR;
+ }
+ thisinst = (objinstptr)egen;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[1 + nidx],
+ (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case LibraryIdx:
+ case HideIdx:
+ case UnhideIdx:
+
+ if ((libno = libfindobject(thisinst->thisobject, &j)) < 0) {
+ Tcl_SetResult(interp, "No such object.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ }
+
+ switch (idx) {
+ case BBoxIdx:
+ ilist = Tcl_NewListObj(0, NULL);
+ hobj = Tcl_NewIntObj((int)thisinst->thisobject->bbox.lowerleft.x);
+ Tcl_ListObjAppendElement(interp, ilist, hobj);
+ hobj = Tcl_NewIntObj((int)thisinst->thisobject->bbox.lowerleft.y);
+ Tcl_ListObjAppendElement(interp, ilist, hobj);
+ hobj = Tcl_NewIntObj((int)(thisinst->thisobject->bbox.lowerleft.x +
+ thisinst->thisobject->bbox.width));
+ Tcl_ListObjAppendElement(interp, ilist, hobj);
+ hobj = Tcl_NewIntObj((int)(thisinst->thisobject->bbox.lowerleft.y +
+ thisinst->thisobject->bbox.height));
+ Tcl_ListObjAppendElement(interp, ilist, hobj);
+ Tcl_SetObjResult(interp, ilist);
+ break;
+
+ case HandleIdx:
+ if ((objc == 3) && (!NameToObject(Tcl_GetString(objv[nidx + 2]),
+ (objinstptr *)&ehandle, TRUE))) {
+ Tcl_SetResult(interp, "Object is not loaded.", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetObjResult(interp, Tcl_NewHandleObj((genericptr)ehandle));
+ }
+ break;
+
+ case LibraryIdx:
+ if (objc == 3) {
+ int libtarget;
+ if (ParseLibArguments(xcinterp, 2, &objv[objc - 2 + nidx], NULL,
+ &libtarget) == TCL_ERROR)
+ return TCL_ERROR;
+ else if (libno != libtarget) {
+ libmoveobject(thisinst->thisobject, libtarget);
+ /* Regenerate the source and target library pages */
+ composelib(libno + LIBRARY);
+ composelib(libtarget + LIBRARY);
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(libno + 1));
+ break;
+
+ case HideIdx:
+ thisinst->thisobject->hidden = True;
+ composelib(libno + LIBRARY);
+ break;
+
+ case UnhideIdx:
+ thisinst->thisobject->hidden = False;
+ composelib(libno + LIBRARY);
+ break;
+
+ case MakeIdx:
+
+ if ((areawin->selects == 0) && (nidx == 0)) {
+ /* h = object make "name" [{element_list}] [library]*/
+ newobjv = (Tcl_Obj **)(&objv[2]);
+ result = ParseElementArguments(interp, objc - 2, newobjv, NULL, ALL_TYPES);
+ if (forceempty && result != TCL_OK) Tcl_ResetResult(interp);
+ else if (!forceempty && result == TCL_OK && areawin->selects == 0)
+ {
+ Tcl_SetResult(interp, "Cannot create empty object. Use "
+ "\"-force\" option.", NULL);
+ return TCL_ERROR;
+ }
+ else if (result != TCL_OK) return result;
+ }
+ else if (nidx == 1) {
+ Tcl_SetResult(interp, "\"object <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "make <name> [element_list] [<library>]");
+ return TCL_ERROR;
+ }
+ if (objc >= 4)
+ ParseLibArguments(xcinterp, 2, &objv[objc - 2], NULL, &libno);
+ else
+ libno = -1;
+ thisinst = domakeobject(libno, Tcl_GetString(objv[nidx + 2]), forceempty);
+ Tcl_SetObjResult(interp, Tcl_NewHandleObj(thisinst));
+ break;
+
+ case NameIdx:
+ if (nidx == 1 || areawin->selects == 0) {
+ if (objc == 3) {
+ sprintf(thisinst->thisobject->name, Tcl_GetString(objv[nidx + 2]));
+ checkname(thisinst->thisobject);
+ }
+ Tcl_AppendElement(interp, thisinst->thisobject->name);
+ }
+ else {
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ thisinst = SELTOOBJINST(areawin->selectlist + i);
+ Tcl_AppendElement(interp, thisinst->thisobject->name);
+ }
+ }
+ }
+ break;
+ case PartsIdx:
+ /* Make a list of the handles of all parts in the object */
+ if (nidx == 1 || areawin->selects == 0) {
+ plist = Tcl_NewListObj(0, NULL);
+ for (j = 0; j < thisinst->thisobject->parts; j++) {
+ hobj = Tcl_NewHandleObj(*(thisinst->thisobject->plist + j));
+ Tcl_ListObjAppendElement(interp, plist, hobj);
+ }
+ Tcl_SetObjResult(interp, plist);
+ }
+ else {
+ ilist = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ objinstptr thisinst = SELTOOBJINST(areawin->selectlist + i);
+ Tcl_ListObjAppendElement(interp, ilist,
+ Tcl_NewStringObj(thisinst->thisobject->name,
+ strlen(thisinst->thisobject->name)));
+ plist = Tcl_NewListObj(0, NULL);
+ for (j = 0; j < thisinst->thisobject->parts; j++) {
+ hobj = Tcl_NewHandleObj(*(thisinst->thisobject->plist + j));
+ Tcl_ListObjAppendElement(interp, plist, hobj);
+ }
+ Tcl_ListObjAppendElement(interp, ilist, plist);
+ }
+ }
+ Tcl_SetObjResult(interp, ilist);
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Get justification (or associated fields) global setting, or apply */
+/* to selected labels. */
+/*----------------------------------------------------------------------*/
+
+int
+getjustification(Tcl_Interp *interp, short bitfield)
+{
+ int i, rval;
+ labelptr tlab;
+
+ if (areawin->selects == 0) {
+ if (bitfield & RIGHT) {
+ Tcl_AppendElement(interp, (areawin->justify & RIGHT) ?
+ "right" : (areawin->justify & NOTLEFT) ? "center" : "left");
+ }
+ else if (bitfield & TOP) {
+ Tcl_AppendElement(interp, (areawin->justify & TOP) ?
+ "top" : (areawin->justify & NOTBOTTOM) ? "middle" : "bottom");
+ }
+ else {
+ Tcl_AppendElement(interp, (areawin->justify & bitfield) ?
+ "true" : "false");
+ }
+ return (areawin->justify & bitfield);
+ }
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ if (bitfield == PINVISIBLE && tlab->pin == NORMAL) continue;
+ if (bitfield & RIGHT) {
+ Tcl_AppendElement(interp, (tlab->justify & RIGHT) ?
+ "right" : (tlab->justify & NOTLEFT) ? "center" : "left");
+ }
+ else if (bitfield & TOP) {
+ Tcl_AppendElement(interp, (tlab->justify & TOP) ?
+ "top" : (tlab->justify & NOTBOTTOM) ? "middle" : "bottom");
+ }
+ else {
+ Tcl_AppendElement(interp, (tlab->justify & bitfield) ? "true" : "false");
+ }
+ rval = tlab->justify;
+ }
+ return (rval & bitfield);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* Set justification (and associated fields) global setting, or apply */
+/* to selected labels. */
+/*----------------------------------------------------------------------*/
+
+void
+setjustification(short bitfield, short value)
+{
+ int i;
+ labelptr tlab;
+
+ if (areawin->selects == 0) {
+ areawin->justify &= (~bitfield);
+ if (value > 0) areawin->justify |= value;
+ return;
+ }
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ if (bitfield == PINVISIBLE && tlab->pin == NORMAL) continue;
+ tlab->justify &= (~bitfield);
+ if (value > 0) tlab->justify |= value;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate the label encoding bits to a string that the Tcl routine */
+/* will recognize from the command line. */
+/* */
+/* (note to self---is there a good way to not have to declare these */
+/* constant character arrays twice in two different routines?) */
+/*----------------------------------------------------------------------*/
+
+char *
+translateencoding(int psfont)
+{
+ const char *encValues[] = {"Standard", "special", "ISOLatin1",
+ "ISOLatin2", "ISOLatin3", "ISOLatin4", "ISOLatin5",
+ "ISOLatin6", NULL};
+ int i;
+
+ i = (fonts[psfont].flags & 0xf80) >> 7;
+ if (i < 0) return NULL;
+ return (char *)encValues[i];
+}
+
+/*----------------------------------------------------------------------*/
+/* Translate the label style bits to a string that the Tcl routine */
+/* will recognize from the command line. */
+/*----------------------------------------------------------------------*/
+
+char *
+translatestyle(int psfont)
+{
+ const char *styValues[] = {"normal", "bold", "italic", "bolditalic", NULL};
+ int i;
+
+ i = fonts[psfont].flags & 0x3;
+ if (i < 0) return NULL;
+ return (char *)styValues[i];
+}
+
+/*----------------------------------------------------------------------*/
+/* Individual element handling. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_label(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, idx, idx2, nidx, result, value, jval, jval2;
+ double tmpdbl;
+ char *tmpstr;
+ Tcl_Obj *objPtr, *listPtr;
+ labelptr tlab;
+
+ static char *subCmds[] = {"make", "type", "insert", "justify", "flipinvariant",
+ "visible", "font", "scale", "encoding", "style", "family", "substring",
+ "text", "latex", "list", "replace", "position", NULL};
+ enum SubIdx {
+ MakeIdx, TypeIdx, InsertIdx, JustIdx, FlipIdx, VisibleIdx,
+ FontIdx, ScaleIdx, EncodingIdx, StyleIdx, FamilyIdx, SubstringIdx,
+ TextIdx, LaTeXIdx, ListIdx, ReplaceIdx, PositionIdx
+ };
+
+ /* These must match the order of string part types defined in xcircuit.h */
+ static char *subsubCmds[] = {"text", "subscript", "superscript",
+ "normalscript", "underline", "overline", "noline", "stop",
+ "forward", "backward", "halfspace", "quarterspace", "return",
+ "name", "scale", "color", "margin", "kern", "parameter",
+ "special", NULL};
+
+ static char *pinTypeNames[] = {"normal", "text", "local", "pin", "global",
+ "info", "netlist", NULL};
+
+ static int pinTypes[] = {NORMAL, NORMAL, LOCAL, LOCAL, GLOBAL, INFO, INFO};
+
+ static char *justValues[] = {"left", "center", "right", "top", "middle",
+ "bottom", NULL};
+
+ const char *styValues[] = {"normal", "bold", "italic", "bolditalic", NULL};
+
+ const char *encValues[] = {"Standard", "special", "ISOLatin1",
+ "ISOLatin2", "ISOLatin3", "ISOLatin4", "ISOLatin5",
+ "ISOLatin6", NULL};
+
+ /* Tk "label" has been renamed to "tcl_label", but we want to */
+ /* consider the "label" command to be overloaded, such that the */
+ /* command "label" may be used without reference to technology. */
+
+ Tcl_Obj **newobjv = (Tcl_Obj **)Tcl_Alloc(objc * sizeof(Tcl_Obj *));
+
+ newobjv[0] = Tcl_NewStringObj("tcl_label", 9);
+ Tcl_IncrRefCount(newobjv[0]);
+ for (i = 1; i < objc; i++) {
+ if (Tcl_IsShared(objv[i]))
+ newobjv[i] = Tcl_DuplicateObj(objv[i]);
+ else
+ newobjv[i] = objv[i];
+ Tcl_IncrRefCount(newobjv[i]);
+ }
+
+ result = Tcl_EvalObjv(interp, objc, newobjv, 0);
+
+ for (i = 0; i < objc; i++)
+ Tcl_DecrRefCount(newobjv[i]);
+ Tcl_Free((char *)newobjv);
+
+ if (result == TCL_OK) return result;
+ Tcl_ResetResult(interp);
+
+ /* Now, assuming that Tcl didn't like the syntax, we continue on with */
+ /* our own version. */
+
+ nidx = 4;
+ result = ParseElementArguments(interp, objc, objv, &nidx, LABEL);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ /* If there are no selections at this point, check if the command is */
+ /* appropriate for setting a default value. */
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if (objc != 2) {
+ result = Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)pinTypeNames, "pin type", 0, &idx2);
+ if (result != TCL_OK) {
+ if (objc == 3) return result;
+ else {
+ Tcl_ResetResult(interp);
+ idx2 = 0;
+ }
+ }
+ else {
+ nidx++;
+ idx2 = pinTypes[idx2]; /* idx2 now matches defs in xcircuit.h */
+ }
+ }
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else {
+ labelptr newlab;
+ stringpart *strptr = NULL;
+ XPoint position;
+
+ if ((result = GetXCStringFromList(interp, objv[nidx + 1],
+ &strptr)) != TCL_OK)
+ return result;
+
+ /* Should probably have some mechanism to create an empty */
+ /* string from a script, even though empty strings are */
+ /* disallowed from the GUI. */
+
+ if (strptr == NULL) {
+ Tcl_SetResult(interp, "Empty string. No element created.", NULL);
+ break;
+ }
+ if ((objc - nidx) <= 2) {
+ Tcl_WrongNumArgs(interp, 3, objv, "<text> {position}");
+ return TCL_ERROR;
+ }
+
+ if ((result = GetPositionFromList(interp, objv[nidx + 2],
+ &position)) != TCL_OK)
+ return result;
+
+ newlab = new_label(NULL, strptr, idx2, position.x, position.y);
+ singlebbox((genericptr *)&newlab);
+ objPtr = Tcl_NewHandleObj(newlab);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"label <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case ScaleIdx:
+ if (objc == 2) {
+ if ((areawin->selects == 0) && (nidx == 1) &&
+ eventmode != TEXT_MODE && eventmode != ETEXT_MODE) {
+ objPtr = Tcl_NewDoubleObj((double)areawin->textscale);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else {
+ float *floatptr;
+ gettextsize(&floatptr);
+ objPtr = Tcl_NewDoubleObj((double)((float)(*floatptr)));
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ }
+ else if (objc >= 3) {
+ result = Tcl_GetDoubleFromObj(interp, objv[2], &tmpdbl);
+ if (result != TCL_OK) return result;
+ if (tmpdbl <= 0.0) {
+ Tcl_SetResult(interp, "Illegal scale value", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((areawin->selects == 0) && (nidx == 1) && (eventmode != TEXT_MODE)
+ && (eventmode != ETEXT_MODE))
+ areawin->textscale = (float)tmpdbl;
+ else
+ changetextscale((float)tmpdbl);
+ }
+ break;
+
+ case FontIdx:
+ if (objc == 2) {
+ tmpstr = fonts[areawin->psfont].psname;
+ objPtr = Tcl_NewStringObj(tmpstr, strlen(tmpstr));
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, tmpstr)) break;
+ setfont((Tk_Window)clientData, (u_int)i, NULL);
+ }
+ break;
+
+ case FamilyIdx:
+
+ /* Check for "-all" switch */
+ if ((objc - nidx) == 2) {
+ tmpstr = Tcl_GetString(objv[nidx + 1]);
+ if (!strncmp(tmpstr, "-all", 4)) {
+
+ /* Create a list of all font families. This does a simple */
+ /* check against contiguous entries, but the result is not */
+ /* guaranteed to be a list of unique entries (i.e., the */
+ /* calling script should sort the list) */
+
+ for (i = 0; i < fontcount; i++) {
+ if (i == 0 || strcmp(fonts[i].family, fonts[i-1].family))
+ Tcl_AppendElement(interp, fonts[i].family);
+ }
+ break;
+ }
+ }
+
+ if (objc == 2) {
+ tmpstr = fonts[areawin->psfont].family;
+ objPtr = Tcl_NewStringObj(tmpstr, strlen(tmpstr));
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].family, tmpstr)) break;
+ setfont((Tk_Window)clientData, (u_int)i, NULL);
+ }
+ break;
+
+ case EncodingIdx:
+ if (objc == 2) {
+ tmpstr = translateencoding(areawin->psfont);
+ objPtr = Tcl_NewStringObj(tmpstr, -1);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)encValues, "encodings", 0,
+ &idx2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fontencoding((Tk_Window)clientData, idx2, NULL);
+ refresh(NULL, NULL, NULL);
+ }
+ break;
+
+ case StyleIdx:
+ if (objc == 2) {
+ tmpstr = translatestyle(areawin->psfont);
+ objPtr = Tcl_NewStringObj(tmpstr, -1);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)styValues,
+ "styles", 0, &idx2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fontstyle((Tk_Window)clientData, idx2, NULL);
+ }
+ break;
+
+ case TypeIdx: /* Change type of label */
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a label selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return pin type(s) */
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ for (idx2 = 0; idx2 < sizeof(pinTypeNames); idx2++) {
+ if (tlab->pin == pinTypes[idx2]) {
+ Tcl_AppendElement(interp, pinTypeNames[idx2]);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)pinTypeNames,
+ "pin types", 0, &idx2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ tlab->pin = pinTypes[idx2];
+ pinconvert(tlab, tlab->pin);
+ setobjecttype(topobject);
+ }
+ }
+ break;
+
+ case InsertIdx: /* Text insertion */
+ if (nidx != 1) {
+ Tcl_SetResult(interp, "Insertion into handle or selection"
+ " not supported (yet)", NULL);
+ return TCL_ERROR;
+ }
+ if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE) {
+ Tcl_SetResult(interp, "Must be in edit mode to insert into label.",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (objc <= nidx + 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "insert_type");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)subsubCmds,
+ "insertions", 0, &idx2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((idx2 > TEXT_STRING) && (idx2 < FONT_NAME) && (objc - nidx == 2)) {
+ labeltext(idx2, (char *)1);
+ }
+ else if (idx2 == MARGINSTOP) {
+ if (objc - nidx == 3) {
+ result = Tcl_GetIntFromObj(interp, objv[nidx + 2], &value);
+ if (result != TCL_OK) return result;
+ }
+ else value = 1;
+ labeltext(idx2, (char *)&value);
+ }
+ else if ((idx2 == PARAM_START) && (objc - nidx == 3)) {
+ labeltext(idx2, Tcl_GetString(objv[nidx + 2]));
+ }
+ else if ((idx2 == FONT_COLOR) && (objc - nidx == 3)) {
+ result = GetColorFromObj(interp, objv[nidx + 2], &value, TRUE);
+ if (result != TCL_OK) return result;
+ labeltext(idx2, (char *)&value);
+ }
+ else if ((idx2 == FONT_NAME) && (objc - nidx == 3)) {
+ tmpstr = Tcl_GetString(objv[nidx + 2]);
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, tmpstr)) break;
+ if (i == fontcount) {
+ Tcl_SetResult(interp, "Invalid font name.", NULL);
+ return TCL_ERROR;
+ }
+ else
+ labeltext(idx2, (char *)&i);
+ }
+ else if ((idx2 == FONT_SCALE) && (objc - nidx == 3)) {
+ float fvalue;
+ double dvalue;
+ result = Tcl_GetDoubleFromObj(interp, objv[nidx + 2], &dvalue);
+ if (result != TCL_OK) return result;
+ fvalue = (float)dvalue;
+ labeltext(idx2, (char *)&fvalue);
+ }
+ else if ((idx2 == KERN) && (objc - nidx == 3)) {
+ strcpy(_STR2, Tcl_GetString(objv[nidx + 2]));
+ setkern(NULL, NULL);
+ }
+ else if ((idx2 == TEXT_STRING) && (objc - nidx == 3)) {
+ char *substring = Tcl_GetString(objv[nidx + 2]);
+ for (i = 0; i < strlen(substring); i++) {
+ /* Special handling allows newlines from cutbuffer selections */
+ /* to be translated into embedded carriage returns. */
+ if (substring[i] == '\012')
+ labeltext(RETURN, (char *)1);
+ else
+ labeltext(substring[i], NULL);
+ }
+ }
+
+ /* PARAM_END in xcircuit.h is actually mapped to the same */
+ /* position as "special" in subsubCommands[] above; don't */
+ /* be confused. . . */
+
+ else if ((idx2 == PARAM_END) && (objc - nidx == 2)) {
+ dospecial();
+ }
+ else if ((idx2 == PARAM_END) && (objc - nidx == 3)) {
+ result = Tcl_GetIntFromObj(interp, objv[nidx + 2], &value);
+ if (result != TCL_OK) return result;
+ labeltext(value, NULL);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 2, objv, "insertion_type ?arg ...?");
+ return TCL_ERROR;
+ }
+ break;
+
+ case SubstringIdx:
+ objPtr = Tcl_NewListObj(0, NULL);
+ if (areawin != NULL && areawin->selects == 1) {
+ if (SELECTTYPE(areawin->selectlist) == LABEL) {
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(areawin->textend));
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(areawin->textpos));
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case VisibleIdx: /* Change visibility of pin */
+ if (objc == nidx + 1)
+ jval = getjustification(interp, PINVISIBLE);
+ else {
+ if ((result = Tcl_GetBooleanFromObj(interp, objv[nidx + 1],
+ &value)) != TCL_OK)
+ return result;
+ if (jval != value)
+ setjustification(PINVISIBLE, (value) ? PINVISIBLE : NORMAL);
+ }
+ break;
+
+ case FlipIdx:
+ if (objc == nidx + 1)
+ jval = getjustification(interp, FLIPINV);
+ else {
+ if ((result = Tcl_GetBooleanFromObj(interp, objv[nidx + 1],
+ &value)) != TCL_OK)
+ return result;
+ if (jval != value)
+ setjustification(FLIPINV, (value) ? FLIPINV : NORMAL);
+ }
+ break;
+
+ case LaTeXIdx:
+ if (objc == nidx + 1)
+ jval = getjustification(interp, LATEXLABEL);
+ else {
+ if ((result = Tcl_GetBooleanFromObj(interp, objv[nidx + 1],
+ &value)) != TCL_OK)
+ return result;
+ if (jval != value)
+ setjustification(LATEXLABEL, (value) ? LATEXLABEL : NORMAL);
+ }
+ break;
+
+ case JustIdx:
+ if (objc == nidx + 1) {
+ jval = getjustification(interp, RIGHT | NOTLEFT);
+ jval2 = getjustification(interp, TOP | NOTBOTTOM);
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)justValues,
+ "justification", 0, &idx2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (idx2) {
+ case 0: value = NORMAL; break;
+ case 1: value = NOTLEFT; break;
+ case 2: value = NOTLEFT | RIGHT; break;
+ case 3: value = NOTBOTTOM | TOP; break;
+ case 4: value = NOTBOTTOM; break;
+ case 5: value = NORMAL; break;
+ }
+ switch (idx2) {
+ case 0: case 1: case 2:
+ jval = getjustification(interp, RIGHT | NOTLEFT);
+ if (jval != value) {
+ setjustification(RIGHT | NOTLEFT, value);
+ refresh(NULL, NULL, NULL);
+ }
+ break;
+ case 3: case 4: case 5:
+ jval2 = getjustification(interp, TOP | NOTBOTTOM);
+ if (jval2 != value) {
+ setjustification(TOP | NOTBOTTOM, value);
+ refresh(NULL, NULL, NULL);
+ }
+ break;
+ }
+ }
+ break;
+
+ case TextIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a label selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return label as printable string */
+ char *tstr;
+ objPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ tstr = textprint(tlab->string, areawin->topinstance);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(tstr, strlen(tstr)));
+ free(tstr);
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
+
+ case ListIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a label selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return label as printable string */
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ objPtr = TclGetStringParts(tlab->string);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ break;
+
+ case ReplaceIdx: /* the opposite of "list" */
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a label selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 2) { /* Replace string from list */
+ stringpart *strptr = NULL;
+
+ if ((result = GetXCStringFromList(interp, objv[nidx + 1],
+ &strptr)) != TCL_OK)
+ return result;
+
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ register_for_undo(XCF_Edit, UNDO_MORE, areawin->topinstance, tlab);
+ freelabel(tlab->string);
+ tlab->string = stringcopy(strptr);
+ }
+ freelabel(strptr);
+ undo_finish_series();
+ refresh(NULL, NULL, NULL);
+ }
+ break;
+
+ case PositionIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a label selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return position of label */
+ Tcl_Obj *cpair;
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != LABEL) continue;
+ tlab = SELTOLABEL(areawin->selectlist + i);
+ cpair = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewIntObj((int)tlab->position.x);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ objPtr = Tcl_NewIntObj((int)tlab->position.y);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, cpair);
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ else if (objc == nidx + 2) { /* Change position of label */
+ XPoint position;
+
+ if ((areawin->selects != 1) || (SELECTTYPE(areawin->selectlist)
+ != LABEL)) {
+ Tcl_SetResult(interp, "Must have exactly one selected label", NULL);
+ return TCL_ERROR;
+ }
+ if ((result = GetPositionFromList(interp, objv[nidx + 1],
+ &position)) != TCL_OK)
+ return result;
+
+ tlab = SELTOLABEL(areawin->selectlist);
+ tlab->position.x = position.x;
+ tlab->position.y = position.y;
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Element Fill Styles */
+/*----------------------------------------------------------------------*/
+
+int xctcl_dofill(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ u_int value;
+ int i, idx, result, rval = -1;
+
+ static char *Styles[] = {"opaque", "transparent", "filled", "unfilled",
+ "solid", NULL};
+ enum StylesIdx {
+ OpaqueIdx, TransparentIdx, FilledIdx, UnfilledIdx, SolidIdx
+ };
+
+ if (objc == 1) {
+ value = areawin->style;
+ Tcl_AppendElement(interp, ((value & OPAQUE) ? "opaque" : "transparent"));
+ if (value & FILLED) {
+ Tcl_AppendElement(interp, "filled");
+ switch (value & FILLSOLID) {
+ case 0:
+ Tcl_AppendElement(interp, "12"); break;
+ case STIP0:
+ Tcl_AppendElement(interp, "25"); break;
+ case STIP1:
+ Tcl_AppendElement(interp, "37"); break;
+ case STIP1 | STIP0:
+ Tcl_AppendElement(interp, "50"); break;
+ case STIP2:
+ Tcl_AppendElement(interp, "62"); break;
+ case STIP2 | STIP0:
+ Tcl_AppendElement(interp, "75"); break;
+ case STIP2 | STIP1:
+ Tcl_AppendElement(interp, "87"); break;
+ case FILLSOLID:
+ Tcl_AppendElement(interp, "solid"); break;
+ }
+ }
+ else {
+ Tcl_AppendElement(interp, "unfilled");
+ }
+ return TCL_OK;
+ }
+
+ for (i = 1; i < objc; i++) {
+ if (Tcl_GetIndexFromObj(interp, objv[i],
+ (CONST84 char **)Styles, "fill styles",
+ 0, &idx) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ result = Tcl_GetIntFromObj(interp, objv[i], &value);
+ if (result != TCL_OK) {
+ Tcl_SetResult(interp, "Expected fill style or fillfactor 0 to 100", NULL);
+ return result;
+ }
+ else {
+ if (value >= 0 && value < 6) value = FILLSOLID;
+ else if (value >= 6 && value < 19) value = FILLED;
+ else if (value >= 19 && value < 31) value = FILLED | STIP0;
+ else if (value >= 31 && value < 44) value = FILLED | STIP1;
+ else if (value >= 44 && value < 56) value = FILLED | STIP0 | STIP1;
+ else if (value >= 56 && value < 69) value = FILLED | STIP2;
+ else if (value >= 69 && value < 81) value = FILLED | STIP2 | STIP0;
+ else if (value >= 81 && value < 94) value = FILLED | STIP2 | STIP1;
+ else if (value >= 94 && value <= 100) value = FILLED | FILLSOLID;
+ else {
+ Tcl_SetResult(interp, "Fill value should be 0 to 100", NULL);
+ return TCL_ERROR;
+ }
+ rval = setelementstyle((Tk_Window)clientData, (pointertype)value,
+ FILLED | FILLSOLID);
+ }
+ }
+ else {
+ switch(idx) {
+ case OpaqueIdx:
+ rval = setelementstyle((Tk_Window)clientData, OPAQUE, OPAQUE);
+ break;
+ case TransparentIdx:
+ rval = setelementstyle((Tk_Window)clientData, NORMAL, OPAQUE);
+ break;
+ case UnfilledIdx:
+ rval = setelementstyle((Tk_Window)clientData, FILLSOLID,
+ FILLED | FILLSOLID);
+ break;
+ case SolidIdx:
+ rval = setelementstyle((Tk_Window)clientData, FILLED | FILLSOLID,
+ FILLED | FILLSOLID);
+ break;
+ case FilledIdx:
+ break;
+ }
+ }
+ }
+ if (rval < 0)
+ return TCL_ERROR;
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Element border styles */
+/*----------------------------------------------------------------------*/
+
+int xctcl_doborder(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, i, idx, value, rval = -1;
+ u_short mask;
+ double wvalue;
+
+ static char *borderStyles[] = {"solid", "dashed", "dotted", "none",
+ "unbordered", "unclosed", "closed", "bbox", "set", "get", "square",
+ "round", "clipmask", NULL};
+ enum StyIdx {
+ SolidIdx, DashedIdx, DottedIdx, NoneIdx, UnborderedIdx,
+ UnclosedIdx, ClosedIdx, BBoxIdx, SetIdx, GetIdx, SquareIdx,
+ RoundIdx, ClipMaskIdx
+ };
+
+ if (objc == 1) {
+ Tcl_Obj *listPtr;
+ listPtr = Tcl_NewListObj(0, NULL);
+ value = areawin->style;
+ wvalue = (double)areawin->linewidth;
+ switch (value & (DASHED | DOTTED | NOBORDER | SQUARECAP)) {
+ case NORMAL:
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("solid", 5)); break;
+ case DASHED:
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("dashed", 6)); break;
+ case DOTTED:
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("dotted", 6)); break;
+ case NOBORDER:
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("unbordered", 10)); break;
+ case SQUARECAP:
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("square-endcaps", 10)); break;
+ }
+ if (value & UNCLOSED)
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj("unclosed", 8));
+ else
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj("closed", 6));
+
+ if (value & BBOX)
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("bounding box", 12));
+
+ if (value & CLIPMASK)
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("clipmask", 8));
+
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(wvalue));
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+
+ for (i = 1; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ (CONST84 char **)borderStyles,
+ "border style", 0, &idx);
+ if (result != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case GetIdx:
+ {
+ int j, numfound = 0;
+ genericptr setel;
+ Tcl_Obj *objPtr, *listPtr = NULL;
+
+ for (j = 0; j < areawin->selects; j++) {
+ setel = SELTOGENERIC(areawin->selectlist + j);
+ if (IS_ARC(setel) || IS_POLYGON(setel) ||
+ IS_SPLINE(setel) || IS_PATH(setel)) {
+ switch(ELEMENTTYPE(setel)) {
+ case ARC: wvalue = ((arcptr)setel)->width; break;
+ case POLYGON: wvalue = ((polyptr)setel)->width; break;
+ case SPLINE: wvalue = ((splineptr)setel)->width; break;
+ case PATH: wvalue = ((pathptr)setel)->width; break;
+ }
+ if ((++numfound) == 2) {
+ listPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ objPtr = Tcl_NewDoubleObj(wvalue);
+ if (numfound > 1)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ switch (numfound) {
+ case 0:
+ objPtr = Tcl_NewDoubleObj(areawin->linewidth);
+ /* fall through */
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ break;
+ case SetIdx:
+ if ((objc - i) != 2) {
+ Tcl_SetResult(interp, "Error: no linewidth given.", NULL);
+ return TCL_ERROR;
+ }
+ result = Tcl_GetDoubleFromObj(interp, objv[++i], &wvalue);
+ if (result == TCL_OK) {
+ sprintf(_STR2, "%f", wvalue);
+ setwwidth((Tk_Window)clientData, NULL);
+ }
+ else {
+ Tcl_SetResult(interp, "Error: invalid border linewidth.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case SolidIdx: value = NORMAL; mask = DASHED | DOTTED | NOBORDER; break;
+ case DashedIdx: value = DASHED; mask = DASHED | DOTTED | NOBORDER; break;
+ case DottedIdx: value = DOTTED; mask = DASHED | DOTTED | NOBORDER; break;
+ case NoneIdx: case UnborderedIdx:
+ value = NOBORDER; mask = DASHED | DOTTED | NOBORDER; break;
+ case UnclosedIdx: value = UNCLOSED; mask = UNCLOSED; break;
+ case ClosedIdx: value = NORMAL; mask = UNCLOSED; break;
+ case SquareIdx: value = SQUARECAP; mask = SQUARECAP; break;
+ case RoundIdx: value = NORMAL; mask = SQUARECAP; break;
+ case BBoxIdx:
+ mask = BBOX;
+ if ((objc - i) < 2) value = BBOX;
+ else {
+ char *yesno = Tcl_GetString(objv[++i]);
+ value = (tolower(yesno[0]) == 'y' || tolower(yesno[0]) == 't') ?
+ BBOX : NORMAL;
+ }
+ break;
+ case ClipMaskIdx:
+ mask = CLIPMASK;
+ if ((objc - i) < 2) value = CLIPMASK;
+ else {
+ char *yesno = Tcl_GetString(objv[++i]);
+ value = (tolower(yesno[0]) == 'y' || tolower(yesno[0]) == 't') ?
+ CLIPMASK : NORMAL;
+ }
+ break;
+ }
+ if (idx != SetIdx && idx != GetIdx)
+ rval = setelementstyle((Tk_Window)clientData, (u_short)value, mask);
+ }
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_polygon(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, nidx, result, npoints, j;
+ polyptr newpoly, ppoly;
+ XPoint ppt;
+ pointlist points;
+ Tcl_Obj *objPtr, *coord, *cpair, **newobjv;
+ Boolean is_box = FALSE;
+ Matrix hierCTM;
+
+ static char *subCmds[] = {"make", "border", "fill", "points", "number", NULL};
+ enum SubIdx {
+ MakeIdx, BorderIdx, FillIdx, PointsIdx, NumberIdx
+ };
+
+ nidx = 255;
+ result = ParseElementArguments(interp, objc, objv, &nidx, POLYGON);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (!strcmp(Tcl_GetString(objv[2]), "box")) {
+ npoints = objc - 3;
+ is_box = TRUE;
+ if (npoints != 4 && npoints != 2) {
+ Tcl_SetResult(interp, "Box must have 2 or 4 points", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ result = Tcl_GetIntFromObj(interp, objv[2], &npoints);
+ if (result != TCL_OK) return result;
+ }
+ if (objc != npoints + 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "N {x1 y1}...{xN yN}");
+ return TCL_ERROR;
+ }
+ points = (pointlist)malloc(npoints * sizeof(XPoint));
+ for (j = 0; j < npoints; j++) {
+ result = GetPositionFromList(interp, objv[3 + j], &ppt);
+ if (result == TCL_OK) {
+ points[j].x = ppt.x;
+ points[j].y = ppt.y;
+ }
+ }
+ if (is_box && (npoints == 2)) {
+ npoints = 4;
+ points = (pointlist)realloc(points, npoints * sizeof(XPoint));
+ points[2].x = points[1].x;
+ points[2].y = points[1].y;
+ points[1].y = points[0].y;
+ points[3].x = points[0].x;
+ points[3].y = points[2].y;
+ }
+ newpoly = new_polygon(NULL, &points, npoints);
+ if (!is_box) newpoly->style |= UNCLOSED;
+ singlebbox((genericptr *)&newpoly);
+
+ objPtr = Tcl_NewHandleObj(newpoly);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"polygon <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case BorderIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_doborder(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case FillIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_dofill(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case NumberIdx:
+ if (areawin->selects != 1) {
+ Tcl_SetResult(interp, "Must have exactly one selection to "
+ "query points", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ if (SELECTTYPE(areawin->selectlist) != POLYGON) {
+ Tcl_SetResult(interp, "Selected element is not a polygon", NULL);
+ return TCL_ERROR;
+ }
+ else
+ ppoly = SELTOPOLY(areawin->selectlist);
+
+ if ((objc - nidx) == 1) {
+ objPtr = Tcl_NewIntObj(ppoly->number);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else
+ {
+ Tcl_SetResult(interp, "Cannot change number of points.\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ break;
+
+ case PointsIdx:
+ if (areawin->selects != 1) {
+ Tcl_SetResult(interp, "Must have exactly one selection to "
+ "query or manipulate points", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ ppoly = SELTOPOLY(areawin->selectlist);
+ MakeHierCTM(&hierCTM);
+ if (ppoly->type != POLYGON) {
+ Tcl_SetResult(interp, "Selected element is not a polygon", NULL);
+ return TCL_ERROR;
+ }
+ points = ppoly->points;
+
+ if ((objc - nidx) == 1) /* Return a list of all points */
+ {
+ objPtr = Tcl_NewListObj(0, NULL);
+ for (npoints = 0; npoints < ppoly->number; npoints++) {
+ cpair = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, points + npoints, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ Tcl_ListObjAppendElement(interp, objPtr, cpair);
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if ((objc - nidx) == 2) /* Return a specific point */
+ {
+ result = Tcl_GetIntFromObj(interp, objv[2], &npoints);
+ if (result != TCL_OK) return result;
+ if (npoints >= ppoly->number) {
+ Tcl_SetResult(interp, "Point number out of range", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, points + npoints, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else
+ {
+ Tcl_SetResult(interp, "Individual point setting unimplemented\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_spline(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, nidx, result, j, npoints;
+ splineptr newspline, pspline;
+ XPoint ppt, ctrlpoints[4];
+ Tcl_Obj *objPtr, *cpair, *coord, **newobjv;
+ Matrix hierCTM;
+
+ static char *subCmds[] = {"make", "border", "fill", "points", NULL};
+ enum SubIdx {
+ MakeIdx, BorderIdx, FillIdx, PointsIdx
+ };
+
+ nidx = 5;
+ result = ParseElementArguments(interp, objc, objv, &nidx, SPLINE);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ /* h = spline make {x1 y1} ... {x4 y4} */
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ for (j = 0; j < 4; j++) {
+ result = GetPositionFromList(interp, objv[2 + j], &ppt);
+ if (result == TCL_OK) {
+ ctrlpoints[j].x = ppt.x;
+ ctrlpoints[j].y = ppt.y;
+ }
+ }
+ newspline = new_spline(NULL, ctrlpoints);
+ singlebbox((genericptr *)&newspline);
+
+ objPtr = Tcl_NewHandleObj(newspline);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (areawin->selects == 1) {
+ if (ELEMENTTYPE(*(topobject->plist + (*areawin->selectlist))) == POLYGON) {
+ converttocurve();
+ }
+ else {
+ Tcl_SetResult(interp, "\"spline make\": must have a polygon selected",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"spline <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed except single polygon", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case BorderIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_doborder(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case FillIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_dofill(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case PointsIdx:
+ if (areawin->selects != 1) {
+ Tcl_SetResult(interp, "Must have exactly one selection to "
+ "query or manipulate points", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ /* check for ESPLINE mode? */
+ if (SELECTTYPE(areawin->selectlist) != SPLINE) {
+ Tcl_SetResult(interp, "Selected element is not a spline", NULL);
+ return TCL_ERROR;
+ }
+ else
+ pspline = SELTOSPLINE(areawin->selectlist);
+
+ MakeHierCTM(&hierCTM);
+
+ if ((objc - nidx) == 1) /* Return a list of all points */
+ {
+ objPtr = Tcl_NewListObj(0, NULL);
+ for (npoints = 0; npoints < 4; npoints++) {
+ cpair = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, pspline->ctrl + npoints, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ Tcl_ListObjAppendElement(interp, objPtr, cpair);
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if ((objc - nidx) == 2) /* Return a specific point */
+ {
+ result = Tcl_GetIntFromObj(interp, objv[objc - nidx + 1], &npoints);
+ if (result != TCL_OK) return result;
+ if (npoints >= 4) {
+ Tcl_SetResult(interp, "Point number out of range", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, pspline->ctrl + npoints, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else
+ {
+ Tcl_SetResult(interp, "Individual control point setting "
+ "unimplemented\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_graphic(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, idx, nidx, result;
+ double dvalue;
+ graphicptr newgp, gp;
+ XPoint ppt;
+ Tcl_Obj *objPtr, *listPtr;
+ char *filename;
+
+ static char *subCmds[] = {"make", "scale", "position", NULL};
+ enum SubIdx {
+ MakeIdx, ScaleIdx, PositionIdx
+ };
+
+ nidx = 7;
+ result = ParseElementArguments(interp, objc, objv, &nidx, GRAPHIC);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if ((objc != 5) && (objc != 7)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ filename = Tcl_GetString(objv[2]);
+
+ result = GetPositionFromList(interp, objv[3], &ppt);
+ if (result != TCL_OK) return result;
+
+ result = Tcl_GetDoubleFromObj(interp, objv[4], &dvalue);
+ if (result != TCL_OK) return result;
+
+ if (!strcmp(filename, "gradient")) {
+ if (objc == 7) {
+ int c1, c2;
+ result = GetColorFromObj(interp, objv[5], &c1, TRUE);
+ if (result != TCL_OK) return result;
+ result = GetColorFromObj(interp, objv[6], &c2, TRUE);
+ if (result != TCL_OK) return result;
+ newgp = gradient_field(NULL, ppt.x, ppt.y, c1, c2);
+ }
+ else
+ newgp = gradient_field(NULL, ppt.x, ppt.y, 0, 1);
+ }
+ else if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else
+ newgp = new_graphic(NULL, filename, ppt.x, ppt.y);
+
+ if (newgp == NULL) return TCL_ERROR;
+
+ newgp->scale = (float)dvalue;
+ singlebbox((genericptr *)&newgp);
+
+ objPtr = Tcl_NewHandleObj(newgp);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"graphic <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case ScaleIdx:
+ case PositionIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have a graphic selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return position of graphic origin */
+ Tcl_Obj *cpair;
+ graphicptr gp;
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != GRAPHIC) continue;
+ gp = SELTOGRAPHIC(areawin->selectlist + i);
+
+ switch (idx) {
+ case ScaleIdx:
+ objPtr = Tcl_NewDoubleObj(gp->scale);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ break;
+ case PositionIdx:
+ cpair = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewIntObj((int)gp->position.x);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ objPtr = Tcl_NewIntObj((int)gp->position.y);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, cpair);
+ break;
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ else if (objc == nidx + 2) { /* Change position or scale */
+ if (idx == ScaleIdx) {
+ result = Tcl_GetDoubleFromObj(interp, objv[nidx + 1], &dvalue);
+ if (result == TCL_OK) {
+ for (i = 0; i < areawin->selects; i++) {
+ float oldscale;
+
+ if (SELECTTYPE(areawin->selectlist + i) != GRAPHIC) continue;
+ gp = SELTOGRAPHIC(areawin->selectlist + i);
+ oldscale = gp->scale;
+ gp->scale = (float)dvalue;
+ if (gp->scale != oldscale) {
+ gp->valid = False;
+ drawarea(areawin->area, (caddr_t)clientData, (caddr_t)NULL);
+ calcbboxvalues(areawin->topinstance,
+ topobject->plist + *(areawin->selectlist + i));
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ (genericptr)gp, (double)oldscale);
+ }
+ }
+ undo_finish_series();
+ }
+ }
+ else {
+ result = GetPositionFromList(interp, objv[nidx + 1], &ppt);
+ if (result == TCL_OK) {
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != GRAPHIC) continue;
+ gp = SELTOGRAPHIC(areawin->selectlist + i);
+ gp->position.x = ppt.x;
+ gp->position.y = ppt.y;
+ calcbboxvalues(areawin->topinstance,
+ topobject->plist + *(areawin->selectlist + i));
+ }
+ }
+ }
+ updatepagebounds(topobject);
+ incr_changes(topobject);
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_arc(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, nidx, result, value;
+ double angle;
+ arcptr newarc;
+ XPoint ppt;
+ Tcl_Obj *objPtr, *listPtr, **newobjv;
+
+ static char *subCmds[] = {"make", "border", "fill", "radius", "minor",
+ "angle", "position", NULL};
+ enum SubIdx {
+ MakeIdx, BorderIdx, FillIdx, RadiusIdx, MinorIdx, AngleIdx,
+ PositionIdx
+ };
+
+ nidx = 7;
+ result = ParseElementArguments(interp, objc, objv, &nidx, ARC);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if ((objc < 4) || (objc > 7)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ result = GetPositionFromList(interp, objv[2], &ppt);
+ if (result != TCL_OK) return result;
+
+ result = Tcl_GetIntFromObj(interp, objv[3], &value);
+ if (result != TCL_OK) return result;
+
+ newarc = new_arc(NULL, value, ppt.x, ppt.y);
+
+ switch (objc) {
+ case 6:
+ result = Tcl_GetDoubleFromObj(interp, objv[4], &angle);
+ if (result == TCL_OK) newarc->angle1 = (float)angle;
+ result = Tcl_GetDoubleFromObj(interp, objv[5], &angle);
+ if (result == TCL_OK) newarc->angle2 = (float)angle;
+ break;
+ case 7:
+ result = Tcl_GetDoubleFromObj(interp, objv[5], &angle);
+ if (result == TCL_OK) newarc->angle1 = (float)angle;
+ result = Tcl_GetDoubleFromObj(interp, objv[6], &angle);
+ if (result == TCL_OK) newarc->angle2 = (float)angle;
+ case 5:
+ result = Tcl_GetIntFromObj(interp, objv[4], &value);
+ if (result == TCL_OK) newarc->yaxis = value;
+ break;
+ }
+ if (objc >= 6) {
+ /* Check that angle2 > angle1. Swap if necessary. */
+ if (newarc->angle2 < newarc->angle1) {
+ int tmp = newarc->angle2;
+ newarc->angle2 = newarc->angle1;
+ newarc->angle1 = tmp;
+ }
+
+ /* Check for 0 length chords (assume full circle was intended) */
+ if (newarc->angle1 == newarc->angle2) {
+ Tcl_SetResult(interp, "Changed zero-length arc chord!\n", NULL);
+ newarc->angle2 = newarc->angle1 + 360;
+ }
+
+ /* Normalize */
+ if (newarc->angle1 >= 360) {
+ newarc->angle1 -= 360;
+ newarc->angle2 -= 360;
+ }
+ else if (newarc->angle2 <= 0) {
+ newarc->angle1 += 360;
+ newarc->angle2 += 360;
+ }
+ }
+ if (objc >= 5) {
+ calcarc(newarc);
+ singlebbox((genericptr *)&newarc);
+ }
+ objPtr = Tcl_NewHandleObj(newarc);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"arc <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case BorderIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_doborder(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case FillIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_dofill(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case RadiusIdx:
+ case MinorIdx:
+ case AngleIdx:
+ case PositionIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ Tcl_SetResult(interp, "Must have an arc selection.", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == nidx + 1) { /* Return position of arc center */
+ Tcl_Obj *cpair;
+ int i;
+ arcptr parc;
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) != ARC) continue;
+ parc = SELTOARC(areawin->selectlist + i);
+
+ switch (idx) {
+ case RadiusIdx:
+ objPtr = Tcl_NewIntObj(parc->radius);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ break;
+ case MinorIdx:
+ objPtr = Tcl_NewIntObj(parc->yaxis);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ break;
+ case AngleIdx:
+ cpair = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewDoubleObj(parc->angle1);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ objPtr = Tcl_NewDoubleObj(parc->angle2);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, cpair);
+ break;
+ case PositionIdx:
+ cpair = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewIntObj((int)parc->position.x);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ objPtr = Tcl_NewIntObj((int)parc->position.y);
+ Tcl_ListObjAppendElement(interp, cpair, objPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, cpair);
+ break;
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_path(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, nidx, result, j, i;
+ genericptr newgen, *eptr;
+ pathptr ppath;
+ Tcl_Obj *elist, *objPtr, *cpair, *coord, **newobjv;
+ XPoint ppt;
+ Matrix hierCTM;
+
+ static char *subCmds[] = {"join", "make", "border", "fill", "point", "unjoin",
+ "points", NULL};
+ enum SubIdx {
+ JoinIdx, MakeIdx, BorderIdx, FillIdx, PointIdx, UnJoinIdx, PointsIdx
+ };
+
+ nidx = 5;
+ result = ParseElementArguments(interp, objc, objv, &nidx, PATH);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case MakeIdx: case JoinIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ /* h = path make {element_list} */
+ newobjv = (Tcl_Obj **)(&objv[1]);
+ result = ParseElementArguments(interp, objc - 1, newobjv, NULL,
+ POLYGON | ARC | SPLINE | PATH);
+ if (result != TCL_OK) return result;
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"path <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ /* h = path make */
+ join();
+ newgen = *(topobject->plist + topobject->parts - 1);
+ objPtr = Tcl_NewHandleObj(newgen);
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case BorderIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_doborder(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case FillIdx:
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ result = xctcl_dofill(clientData, interp, objc - nidx, newobjv);
+ break;
+
+ case PointIdx:
+ Tcl_SetResult(interp, "Unimplemented function.", NULL);
+ return TCL_ERROR;
+ break;
+
+ case UnJoinIdx:
+ unjoin();
+ /* Would be nice to return the list of constituent elements. . . */
+ break;
+
+ case PointsIdx:
+ /* Make a list of the polygon and spline elements in the path, */
+ /* returning a nested list enumerating the points. This is */
+ /* ad-hoc, as it does not match any other method of returning */
+ /* point information about a part. This is because returning */
+ /* a handle list is useless, since the handles cannot be */
+ /* accessed directly. */
+
+ if (areawin->selects != 1) {
+ Tcl_SetResult(interp, "Must have exactly one selection to "
+ "query parts", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ if (SELECTTYPE(areawin->selectlist) != PATH) {
+ Tcl_SetResult(interp, "Selected element is not a path", NULL);
+ return TCL_ERROR;
+ }
+ else
+ ppath = SELTOPATH(areawin->selectlist);
+
+ MakeHierCTM(&hierCTM);
+
+ objPtr = Tcl_NewListObj(0, NULL);
+ for (j = 0; j < ppath->parts; j++) {
+ eptr = (genericptr *)(ppath->plist + j);
+ elist = Tcl_NewListObj(0, NULL);
+ if ((*eptr)->type == POLYGON) {
+ polyptr ppoly;
+ ppoly = (polyptr)(*eptr);
+ Tcl_ListObjAppendElement(interp, elist,
+ Tcl_NewStringObj("polygon", -1));
+ for (i = 0; i < ppoly->number; i++) {
+ cpair = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, ppoly->points + i, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ Tcl_ListObjAppendElement(interp, elist, cpair);
+ }
+ }
+ else {
+ splineptr pspline;
+ pspline = (splineptr)(*eptr);
+ Tcl_ListObjAppendElement(interp, elist,
+ Tcl_NewStringObj("spline", -1));
+ for (i = 0; i < 4; i++) {
+ cpair = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, pspline->ctrl + i, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, cpair, coord);
+ Tcl_ListObjAppendElement(interp, elist, cpair);
+ }
+ }
+ Tcl_ListObjAppendElement(interp, objPtr, elist);
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_instance(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int i, numfound, idx, nidx, result;
+ objectptr pobj;
+ objinstptr pinst, newinst;
+ short *newselect;
+ XPoint newpos, ppt;
+ Tcl_Obj *objPtr;
+ Matrix hierCTM;
+
+ static char *subCmds[] = {"make", "object", "scale", "center", "linewidth",
+ "bbox", NULL};
+ enum SubIdx {
+ MakeIdx, ObjectIdx, ScaleIdx, CenterIdx, LineWidthIdx, BBoxIdx
+ };
+
+ static char *lwsubCmds[] = {"scale_variant", "variant", "scale_invariant",
+ "invariant", NULL};
+
+ nidx = 3;
+ result = ParseElementArguments(interp, objc, objv, &nidx, OBJINST);
+ if (result != TCL_OK) return result;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx)) != TCL_OK)
+ return result;
+
+ switch (idx) {
+ case MakeIdx:
+ if ((areawin->selects == 0) && (nidx == 1)) {
+ if (objc == 3) {
+ pobj = NameToObject(Tcl_GetString(objv[2]), &pinst, False);
+ if (pobj == NULL) {
+ Tcl_SetResult(interp, "no such object", NULL);
+ return TCL_ERROR;
+ }
+ newpos = UGetCursorPos();
+ u2u_snap(&newpos);
+ newinst = new_objinst(NULL, pinst, newpos.x, newpos.y);
+ newinst->color = areawin->color;
+ newselect = allocselect();
+ *newselect = (short)(topobject->parts - 1);
+ draw_normal_selected(topobject, areawin->topinstance);
+ eventmode = COPY_MODE;
+ Tk_CreateEventHandler(areawin->area, PointerMotionMask,
+ (Tk_EventProc *)xctk_drag, NULL);
+ return XcTagCallback(interp, objc, objv);
+ }
+ else if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ pobj = NameToObject(Tcl_GetString(objv[2]), &pinst, False);
+ if (pobj == NULL) {
+ Tcl_SetResult(interp, "no such object", NULL);
+ return TCL_ERROR;
+ }
+ result = GetPositionFromList(interp, objv[3], &newpos);
+ if (result != TCL_OK) return result;
+
+ newinst = new_objinst(NULL, pinst, newpos.x, newpos.y);
+ newinst->color = areawin->color;
+ singlebbox((genericptr *)&newinst);
+ objPtr = Tcl_NewHandleObj(newinst);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (nidx == 2) {
+ Tcl_SetResult(interp, "\"instance <handle> make\" is illegal", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ Tcl_SetResult(interp, "No selections allowed.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case ObjectIdx:
+ if ((objc - nidx) == 1) {
+ Tcl_Obj *listPtr;
+ numfound = 0;
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ objPtr = Tcl_NewStringObj(pinst->thisobject->name, -1);
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ else {
+ Tcl_Obj *listPtr;
+ int listlen;
+ objectptr pobj;
+
+ /* If the number of additional arguments matches the number */
+ /* of selected items, or if there is one additional item */
+ /* that is a list with a number of items equal to the */
+ /* number of selected items, then change each element to */
+ /* the corresponding object in the list. If there is only */
+ /* one additional item, change all elements to that object. */
+
+ if ((objc - nidx) == 1 + areawin->selects) {
+ // Change each element in turn to the corresponding object
+ // taken from the command arguments
+ for (i = 0; i < areawin->selects; i++) {
+ pobj = NameToObject(Tcl_GetString(objv[2 + i]), NULL, FALSE);
+ if (pobj == NULL) {
+ Tcl_SetResult(interp, "Name is not a known object", NULL);
+ return TCL_ERROR;
+ }
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ pinst->thisobject = pobj;
+ calcbboxinst(pinst);
+ }
+ }
+ else if ((objc - nidx) == 2) {
+ result = Tcl_ListObjLength(interp, objv[2], &listlen);
+ if (result != TCL_OK) return result;
+ if (listlen == 1) {
+ // Check if the indicated object exists
+ pobj = NameToObject(Tcl_GetString(objv[2]), NULL, FALSE);
+ if (pobj == NULL) {
+ Tcl_SetResult(interp, "Name is not a known object", NULL);
+ return TCL_ERROR;
+ }
+
+ // Change all selected elements to the object specified
+ for (i = 0; i < areawin->selects; i++) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ pinst->thisobject = pobj;
+ calcbboxinst(pinst);
+ }
+ }
+ else if (listlen != areawin->selects) {
+ Tcl_SetResult(interp, "Error: list length does not match"
+ "the number of selected elements.", NULL);
+ return TCL_ERROR;
+ }
+ else {
+ // Change each element in turn to the corresponding object
+ // in the list
+ for (i = 0; i < areawin->selects; i++) {
+ result = Tcl_ListObjIndex(interp, objv[2], i, &listPtr);
+ if (result != TCL_OK) return result;
+
+ pobj = NameToObject(Tcl_GetString(listPtr), NULL, FALSE);
+ if (pobj == NULL) {
+ Tcl_SetResult(interp, "Name is not a known object", NULL);
+ return TCL_ERROR;
+ }
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ pinst->thisobject = pobj;
+ calcbboxinst(pinst);
+ }
+ }
+ }
+ drawarea(areawin->area, NULL, NULL);
+ }
+ break;
+
+ case ScaleIdx:
+ if ((objc - nidx) == 1) {
+ Tcl_Obj *listPtr;
+ numfound = 0;
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ objPtr = Tcl_NewDoubleObj(pinst->scale);
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ else {
+ strcpy(_STR2, Tcl_GetString(objv[2]));
+ setosize((Tk_Window)clientData, NULL);
+ }
+ break;
+
+ case CenterIdx:
+
+ if ((objc - nidx) == 1) {
+ Tcl_Obj *listPtr, *coord;
+ numfound = 0;
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ MakeHierCTM(&hierCTM);
+ objPtr = Tcl_NewListObj(0, NULL);
+ UTransformbyCTM(&hierCTM, &pinst->position, &ppt, 1);
+ coord = Tcl_NewIntObj((int)ppt.x);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)ppt.y);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ else if (((objc - nidx) == 2) && (areawin->selects == 1)) {
+ result = GetPositionFromList(interp, objv[objc - 1], &newpos);
+ if (result != TCL_OK) return result;
+ if (SELECTTYPE(areawin->selectlist) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist);
+ MakeHierCTM(&hierCTM);
+ UTransformbyCTM(&hierCTM, &newpos, &pinst->position, 1);
+ }
+ }
+ else {
+ Tcl_SetResult(interp, "Usage: instance center {x y}; only one"
+ "instance should be selected.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case LineWidthIdx:
+ if ((objc - nidx) == 1) {
+ Tcl_Obj *listPtr;
+ numfound = 0;
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ if (pinst->style & LINE_INVARIANT)
+ objPtr = Tcl_NewStringObj("scale_invariant", -1);
+ else
+ objPtr = Tcl_NewStringObj("scale_variant", -1);
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ else {
+ int subidx;
+ if ((result = Tcl_GetIndexFromObj(interp, objv[nidx + 1],
+ (CONST84 char **)lwsubCmds,
+ "value", 0, &subidx)) == TCL_OK) {
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist);
+ if (subidx < 2)
+ pinst->style &= ~LINE_INVARIANT;
+ else
+ pinst->style |= LINE_INVARIANT;
+ }
+ }
+ }
+ }
+ break;
+
+ case BBoxIdx:
+ if ((objc - nidx) == 1) {
+ Tcl_Obj *listPtr, *coord;
+ numfound = 0;
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ objPtr = Tcl_NewListObj(0, NULL);
+ coord = Tcl_NewIntObj((int)pinst->bbox.lowerleft.x);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)pinst->bbox.lowerleft.y);
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)(pinst->bbox.lowerleft.x +
+ pinst->bbox.width));
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ coord = Tcl_NewIntObj((int)(pinst->bbox.lowerleft.y +
+ pinst->bbox.height));
+ Tcl_ListObjAppendElement(interp, objPtr, coord);
+ if (numfound > 0)
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if ((++numfound) == 1)
+ listPtr = objPtr;
+ }
+ }
+ switch (numfound) {
+ case 0:
+ Tcl_SetResult(interp, "Error: no object instances selected", NULL);
+ return TCL_ERROR;
+ break;
+ case 1:
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ default:
+ Tcl_SetObjResult(interp, listPtr);
+ break;
+ }
+ }
+ else {
+ /* e.g., "instance bbox recompute" */
+ for (i = 0; i < areawin->selects; i++) {
+ if (SELECTTYPE(areawin->selectlist + i) == OBJINST) {
+ pinst = SELTOOBJINST(areawin->selectlist + i);
+ calcbbox(pinst);
+ }
+ }
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* "element" configures properties of elements. Note that if the */
+/* second argument is not an element handle (pointer), then operations */
+/* will be applied to all selected elements. If there is no element */
+/* handle and no objects are selected, the operation will be applied */
+/* to default settings, like the "xcircuit::set" command. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_element(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, nidx, idx, i, flags;
+ Tcl_Obj *listPtr;
+ Tcl_Obj **newobjv;
+ int newobjc;
+ genericptr egen;
+ short *newselect, *tempselect, *orderlist;
+
+ /* Commands */
+ static char *subCmds[] = {
+ "delete", "copy", "flip", "rotate", "edit", "select", "snap", "move",
+ "color", "parameters", "raise", "lower", "exchange", "hide", "show",
+ "handle", "deselect", NULL
+ };
+ enum SubIdx {
+ DeleteIdx, CopyIdx, FlipIdx, RotateIdx, EditIdx, SelectIdx, SnapIdx,
+ MoveIdx, ColorIdx, ParamIdx, RaiseIdx, LowerIdx, ExchangeIdx,
+ HideIdx, ShowIdx, HandleIdx, DeselectIdx
+ };
+
+ static char *etypes[] = {
+ "Label", "Polygon", "Bezier Curve", "Object Instance", "Path",
+ "Arc", "Graphic", NULL /* (jdk) */
+ };
+
+ /* Before doing a standard parse, we need to check for the single case */
+ /* "element X deselect"; otherwise, calling ParseElementArguements() */
+ /* is going to destroy the selection list. */
+
+ if ((objc == 3) && (!strcmp(Tcl_GetString(objv[2]), "deselect"))) {
+ result = xctcl_deselect(clientData, interp, objc, objv);
+ return result;
+ }
+
+ /* All other commands are dispatched to individual element commands */
+ /* for the indicated element or for each selected element. */
+
+ nidx = 7;
+ result = ParseElementArguments(interp, objc, objv, &nidx, ALL_TYPES);
+ if (result != TCL_OK) return result;
+
+ if ((objc - nidx) < 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (!strcmp(Tcl_GetString(objv[nidx]), "type")) {
+ /* Return a list of types of the selected elements */
+
+ if (areawin->selects > 1)
+ listPtr = Tcl_NewListObj(0, NULL);
+
+ for (i = 0; i < areawin->selects; i++) {
+ Tcl_Obj *objPtr;
+ int idx2, type = SELECTTYPE(areawin->selectlist + i);
+ switch (type) {
+ case LABEL: idx2 = 0; break;
+ case POLYGON: idx2 = 1; break;
+ case SPLINE: idx2 = 2; break;
+ case OBJINST: idx2 = 3; break;
+ case PATH: idx2 = 4; break;
+ case ARC: idx2 = 5; break;
+ case GRAPHIC: idx2 = 6; break;
+ default: return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(etypes[idx2], strlen(etypes[idx2]));
+ if (areawin->selects == 1) {
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ else {
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ return XcTagCallback(interp, objc, objv);
+ }
+ else if (!strcmp(Tcl_GetString(objv[nidx]), "handle")) {
+ /* Return a list of handles of the selected elements */
+
+ listPtr = SelectToTclList(interp, areawin->selectlist, areawin->selects);
+ Tcl_SetObjResult(interp, listPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[nidx],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx) == TCL_OK) {
+
+ newobjv = (Tcl_Obj **)(&objv[nidx]);
+ newobjc = objc - nidx;
+
+ /* Shift the argument list and call the indicated function. */
+
+ switch(idx) {
+ case DeleteIdx:
+ result = xctcl_delete(clientData, interp, newobjc, newobjv);
+ break;
+ case CopyIdx:
+ result = xctcl_copy(clientData, interp, newobjc, newobjv);
+ break;
+ case FlipIdx:
+ result = xctcl_flip(clientData, interp, newobjc, newobjv);
+ break;
+ case RotateIdx:
+ result = xctcl_rotate(clientData, interp, newobjc, newobjv);
+ break;
+ case EditIdx:
+ result = xctcl_edit(clientData, interp, newobjc, newobjv);
+ break;
+ case ParamIdx:
+ result = xctcl_param(clientData, interp, newobjc, newobjv);
+ break;
+ case HideIdx:
+ for (i = 0; i < areawin->selects; i++) {
+ newselect = areawin->selectlist + i;
+ egen = SELTOGENERIC(newselect);
+ egen->type |= DRAW_HIDE;
+ }
+ refresh(NULL, NULL, NULL);
+ break;
+ case ShowIdx:
+ if (newobjc == 2) {
+ if (!strcmp(Tcl_GetString(newobjv[1]), "all")) {
+ for (i = 0; i < topobject->parts; i++) {
+ egen = *(topobject->plist + i);
+ egen->type &= (~DRAW_HIDE);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < areawin->selects; i++) {
+ newselect = areawin->selectlist + i;
+ egen = SELTOGENERIC(newselect);
+ egen->type &= (~DRAW_HIDE);
+ }
+ }
+ refresh(NULL, NULL, NULL);
+ break;
+ case SelectIdx:
+ if (newobjc == 2) {
+ if (!strncmp(Tcl_GetString(newobjv[1]), "hide", 4)) {
+ for (i = 0; i < areawin->selects; i++) {
+ newselect = areawin->selectlist + i;
+ egen = SELTOGENERIC(newselect);
+ egen->type |= SELECT_HIDE;
+ }
+ }
+ else if (!strncmp(Tcl_GetString(newobjv[1]), "allow", 5)) {
+ for (i = 0; i < topobject->parts; i++) {
+ egen = *(topobject->plist + i);
+ egen->type &= (~SELECT_HIDE);
+ }
+ }
+ else {
+ Tcl_SetResult(interp, "Select options are \"hide\" "
+ "and \"allow\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ /* If nidx == 2, then we've already done the selection! */
+ else if (nidx == 1)
+ result = xctcl_select(clientData, interp, newobjc, newobjv);
+ else
+ result = TCL_OK;
+ break;
+ case DeselectIdx:
+ /* case nidx == 2 was already taken care of. case nidx == 1 */
+ /* implies "deselect all". */
+ unselect_all();
+ result = TCL_OK;
+ break;
+ case ColorIdx:
+ result = xctcl_color(clientData, interp, newobjc, newobjv);
+ break;
+ case SnapIdx:
+ snapelement();
+ break;
+ case ExchangeIdx:
+ exchange();
+ break;
+ case LowerIdx:
+
+ /* Improved method thanks to Dimitri Princen */
+
+ /* First move the selected parts to the bottom. This sets */
+ /* all the values pointed by (selectlist + i) to zero, and */
+ /* inverts the order between the selected elements. */
+ /* Finally *tempselect += i inverts the original numbering, */
+ /* so the second loop inverts the placing again, regaining */
+ /* the correct order (and writes it so). */
+ /* */
+ /* RaiseIdx works similar but starts from the top. */
+
+ if (newobjc == 2) {
+ if (!strcmp(Tcl_GetString(newobjv[1]), "all")) {
+ orderlist = (short *)malloc(topobject->parts * sizeof(short));
+ for (i = 0; i < topobject->parts; i++) *(orderlist + i) = i;
+
+ for (i = 0; i < areawin->selects; i++) {
+ tempselect = areawin->selectlist + i;
+ xc_bottom(tempselect, orderlist);
+ *tempselect += i;
+ }
+ for (i = 0; i < areawin->selects; i++) {
+ tempselect = areawin->selectlist + i;
+ xc_bottom(tempselect, orderlist);
+ *tempselect += (areawin->selects - 1 - i);
+ }
+ register_for_undo(XCF_Reorder, UNDO_MORE, areawin->topinstance,
+ orderlist, topobject->parts);
+ }
+ }
+ else {
+ xc_lower();
+ }
+ break;
+
+ case RaiseIdx:
+
+ /* Improved method thanks to Dimitri Princen */
+
+ if (newobjc == 2) {
+ if (!strcmp(Tcl_GetString(newobjv[1]), "all")) {
+ orderlist = (short *)malloc(topobject->parts * sizeof(short));
+ for (i = 0; i < topobject->parts; i++) *(orderlist + i) = i;
+
+ for (i = areawin->selects - 1; i >= 0 ; i--) {
+ tempselect = areawin->selectlist + i;
+ xc_top(tempselect, orderlist);
+ *tempselect -= (areawin->selects - 1 - i);
+ }
+ for (i = areawin->selects - 1; i >= 0 ; i--) {
+ tempselect = areawin->selectlist + i;
+ xc_top(tempselect, orderlist);
+ *tempselect -= i;
+ }
+ register_for_undo(XCF_Reorder, UNDO_MORE, areawin->topinstance,
+ orderlist, topobject->parts);
+ }
+ }
+ else {
+ xc_raise();
+ }
+ break;
+
+ case MoveIdx:
+ result = xctcl_move(clientData, interp, newobjc, newobjv);
+ break;
+ }
+ return result;
+ }
+
+ /* Call each individual element function. */
+ /* Each function is responsible for filtering the select list to */
+ /* choose only the appropriate elements. However, we first check */
+ /* if at least one of that type exists in the list, so the function */
+ /* won't return an error. */
+
+ Tcl_ResetResult(interp);
+
+ newobjv = (Tcl_Obj **)(&objv[nidx - 1]);
+ newobjc = objc - nidx + 1;
+
+ flags = 0;
+ for (i = 0; i < areawin->selects; i++)
+ flags |= SELECTTYPE(areawin->selectlist + i);
+
+ if (flags & LABEL) {
+ result = xctcl_label(clientData, interp, newobjc, newobjv);
+ if (result != TCL_OK) return result;
+ }
+ if (flags & POLYGON) {
+ result = xctcl_polygon(clientData, interp, newobjc, newobjv);
+ if (result != TCL_OK) return result;
+ }
+ if (flags & OBJINST) {
+ result = xctcl_instance(clientData, interp, newobjc, newobjv);
+ if (result != TCL_OK) return result;
+ }
+ if (flags & SPLINE) {
+ result = xctcl_spline(clientData, interp, newobjc, newobjv);
+ if (result != TCL_OK) return result;
+ }
+ if (flags & PATH) {
+ result = xctcl_path(clientData, interp, newobjc, newobjv);
+ if (result != TCL_OK) return result;
+ }
+ if (flags & ARC) {
+ result = xctcl_arc(clientData, interp, newobjc, newobjv);
+ }
+ if (flags & GRAPHIC) {
+ result = xctcl_graphic(clientData, interp, newobjc, newobjv);
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------*/
+/* "config" manipulates a whole bunch of option settings. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_config(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int tmpint, i;
+ int result, idx;
+ char *tmpstr, buffer[30], **sptr;
+ Pagedata *curpage;
+
+ static char *boxsubCmds[] = {"manhattan", "rhomboidx", "rhomboidy",
+ "rhomboida", "normal", NULL};
+ static char *pathsubCmds[] = {"tangents", "normal", NULL};
+ static char *coordsubCmds[] = {"decimal inches", "fractional inches",
+ "centimeters", "internal units", NULL};
+ static char *filterTypes[] = {"instances", "labels", "polygons", "arcs",
+ "splines", "paths", "graphics", NULL};
+ static char *searchOpts[] = {"files", "lib", "libs", "library", "libraries", NULL};
+
+ static char *subCmds[] = {
+ "axis", "axes", "grid", "snap", "bbox", "editinplace",
+ "pinpositions", "pinattach", "clipmasks", "boxedit", "pathedit", "linewidth",
+ "colorscheme", "coordstyle", "drawingscale", "manhattan", "centering",
+ "filter", "buschar", "backup", "search", "focus", "init",
+ "delete", "windownames", "hold", "database", "suspend",
+ "technologies", "fontnames", "debug", NULL
+ };
+ enum SubIdx {
+ AxisIdx, AxesIdx, GridIdx, SnapIdx, BBoxIdx, EditInPlaceIdx,
+ PinPosIdx, PinAttachIdx, ShowClipIdx, BoxEditIdx, PathEditIdx, LineWidthIdx,
+ ColorSchemeIdx, CoordStyleIdx, ScaleIdx, ManhattanIdx, CenteringIdx,
+ FilterIdx, BusCharIdx, BackupIdx, SearchIdx, FocusIdx,
+ InitIdx, DeleteIdx, WindowNamesIdx, HoldIdx, DatabaseIdx,
+ SuspendIdx, TechnologysIdx, FontNamesIdx, DebugIdx
+ };
+
+ if ((objc == 1) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)subCmds,
+ "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* Set curpage for those routines that need it */
+
+ switch(idx) {
+ case GridIdx:
+ case SnapIdx:
+ case LineWidthIdx:
+ case CoordStyleIdx:
+ case ScaleIdx:
+ if (areawin == NULL) {
+ Tcl_SetResult(interp, "No current window set, assuming default\n",
+ NULL);
+ curpage = xobjs.pagelist[0];
+ if (curpage == NULL) return TCL_ERROR;
+ }
+ else
+ curpage = xobjs.pagelist[areawin->page];
+ break;
+ }
+
+ /* Check number of arguments wholesale (to be done) */
+
+ switch(idx) {
+ case SuspendIdx:
+ if (objc == 2) {
+ switch (xobjs.suspend) {
+ case -1:
+ Tcl_SetResult(interp, "normal drawing", NULL);
+ break;
+ case 0:
+ Tcl_SetResult(interp, "drawing suspended", NULL);
+ break;
+ case 1:
+ Tcl_SetResult(interp, "refresh pending", NULL);
+ break;
+ case 2:
+ Tcl_SetResult(interp, "drawing locked", NULL);
+ break;
+ }
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ if (tmpint == 0) {
+
+ /* Pending drawing */
+
+ if (xobjs.suspend == 1) {
+ xobjs.suspend = -1;
+ refresh(NULL, NULL, NULL);
+ }
+ else
+ xobjs.suspend = -1;
+ }
+ else {
+ /* Calling "config suspend true" twice effectively */
+ /* locks the graphics in a state that can only be */
+ /* removed by a call to "config suspend false". */
+ if (xobjs.suspend >= 0)
+ xobjs.suspend = 2;
+ else
+ xobjs.suspend = 0;
+ }
+ }
+ break;
+
+ case DatabaseIdx:
+ /* Regenerate the database of colors, fonts, etc. from Tk options */
+ if (objc == 3) {
+ Tk_Window tkwind, tktop;
+
+ tktop = Tk_MainWindow(interp);
+ tkwind = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tktop);
+ build_app_database(tkwind);
+ setcolorscheme(!areawin->invert);
+ }
+ break;
+
+ case FontNamesIdx:
+ /* To do: Return a list of known font names. The Tk wrapper uses */
+ /* this list to regenerate the font menu for each new window. */
+ break;
+
+ case WindowNamesIdx:
+ /* Generate and return a list of existing window names */
+
+ if (objc == 2) {
+ XCWindowData *winptr;
+ for (winptr = xobjs.windowlist; winptr != NULL; winptr = winptr->next)
+ Tcl_AppendElement(interp, Tk_PathName(winptr->area));
+ }
+ break;
+
+ case DeleteIdx:
+ if (objc == 3) {
+ XCWindowData *winptr;
+ Tk_Window tkwind, tktop;
+
+ tktop = Tk_MainWindow(interp);
+ tkwind = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tktop);
+ for (winptr = xobjs.windowlist; winptr != NULL; winptr = winptr->next) {
+ if (winptr->area == tkwind) {
+ delete_window(winptr);
+ break;
+ }
+ }
+ if (winptr == NULL) {
+ Tcl_SetResult(interp, "No such window\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ break;
+
+ case DebugIdx:
+#ifdef ASG
+ if (objc == 3) {
+ result = Tcl_GetIntFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ SetDebugLevel(&tmpint);
+ }
+ else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(SetDebugLevel(NULL)));
+ }
+#endif
+ break;
+
+
+ case InitIdx:
+ /* Create a data structure for a new drawing window. */
+ /* Give it the same page number and view as the current window */
+
+ if (objc == 3) {
+ XCWindowData *newwin;
+ newwin = GUI_init(objc - 2, objv + 2);
+ if (newwin != NULL) {
+ newwin->page = areawin->page;
+ newwin->vscale = areawin->vscale;
+ newwin->pcorner = areawin->pcorner;
+ newwin->topinstance = areawin->topinstance;
+ }
+ else {
+ Tcl_SetResult(interp, "Unable to create new window structure\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ break;
+
+ case FocusIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, Tk_PathName(areawin->area), NULL);
+ }
+ else if (objc == 3) {
+ Tk_Window tkwind, tktop;
+ XCWindowData *winptr;
+ XPoint locsave;
+
+ tktop = Tk_MainWindow(interp);
+ tkwind = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tktop);
+ /* (Diagnostic) */
+ /* printf("Focusing: %s\n", Tcl_GetString(objv[2])); */
+ for (winptr = xobjs.windowlist; winptr != NULL; winptr = winptr->next) {
+ if (winptr->area == tkwind) {
+ int savemode;
+ objectptr savestack;
+
+ if (areawin == winptr) break;
+ if ((eventmode == MOVE_MODE || eventmode == COPY_MODE) &&
+ winptr->editstack->parts == 0) {
+ locsave = areawin->save;
+ delete_for_xfer(NORMAL, areawin->selectlist, areawin->selects);
+ /* Swap editstacks */
+ savestack = winptr->editstack;
+ winptr->editstack = areawin->editstack;
+ areawin->editstack = savestack;
+ savemode = eventmode;
+ eventmode = NORMAL_MODE;
+
+ /* Change event handlers */
+ xcRemoveEventHandler(areawin->area, PointerMotionMask, False,
+ (xcEventHandler)xctk_drag, NULL);
+ drawarea(areawin->area, NULL, NULL);
+ Tk_CreateEventHandler(winptr->area, PointerMotionMask,
+ (Tk_EventProc *)xctk_drag, NULL);
+
+ /* Set new window */
+ areawin = winptr;
+ eventmode = savemode;
+ areawin->save = locsave;
+ transferselects();
+ drawarea(areawin->area, NULL, NULL);
+ }
+ else
+ areawin = winptr;
+ break;
+ }
+ }
+ if (winptr == NULL) {
+ Tcl_SetResult(interp, "No such xcircuit drawing window\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 2, objv, "[window]");
+ return TCL_ERROR;
+ }
+ break;
+
+ case AxisIdx: case AxesIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->axeson) ? "true" : "false", NULL);
+ break;
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->axeson = (Boolean) tmpint;
+ }
+ break;
+
+ case GridIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->gridon) ? "true" : "false", NULL);
+ break;
+ }
+ else {
+ if (!strncmp("spac", Tcl_GetString(objv[2]), 4)) {
+ if (objc == 3) {
+ measurestr((float)curpage->gridspace, buffer);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buffer, strlen(buffer)));
+ break;
+ }
+ else {
+ strcpy(_STR2, Tcl_GetString(objv[3]));
+ setgrid(NULL, &(curpage->gridspace));
+ }
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->gridon = (Boolean) tmpint;
+ }
+ }
+ break;
+
+ case SnapIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->snapto) ? "true" : "false", NULL);
+ }
+ else {
+ if (!strncmp("spac", Tcl_GetString(objv[2]), 4)) {
+ if (objc == 3) {
+ measurestr((float)curpage->snapspace, buffer);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buffer, strlen(buffer)));
+ break;
+ }
+ else {
+ strcpy(_STR2, Tcl_GetString(objv[3]));
+ setgrid(NULL, &(curpage->snapspace));
+ }
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->snapto = (Boolean) tmpint;
+ }
+ }
+ break;
+
+ case BoxEditIdx:
+ if (objc == 2) {
+ switch (areawin->boxedit) {
+ case MANHATTAN: idx = 0; break;
+ case RHOMBOIDX: idx = 1; break;
+ case RHOMBOIDY: idx = 2; break;
+ case RHOMBOIDA: idx = 3; break;
+ case NORMAL: idx = 4; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(boxsubCmds[idx],
+ strlen(boxsubCmds[idx])));
+ }
+ else if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "boxedit ?arg ...?");
+ return TCL_ERROR;
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)boxsubCmds,
+ "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (idx) {
+ case 0: tmpint = MANHATTAN; break;
+ case 1: tmpint = RHOMBOIDX; break;
+ case 2: tmpint = RHOMBOIDY; break;
+ case 3: tmpint = RHOMBOIDA; break;
+ case 4: tmpint = NORMAL; break;
+ }
+ areawin->boxedit = tmpint;
+ }
+ break;
+
+ case PathEditIdx:
+ if (objc == 2) {
+ switch (areawin->pathedit) {
+ case TANGENTS: idx = 0; break;
+ case NORMAL: idx = 1; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(pathsubCmds[idx],
+ strlen(pathsubCmds[idx])));
+ }
+ else if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pathedit ?arg ...?");
+ return TCL_ERROR;
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)pathsubCmds,
+ "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (idx) {
+ case 0: tmpint = TANGENTS; break;
+ case 1: tmpint = NORMAL; break;
+ }
+ areawin->pathedit = tmpint;
+ }
+ break;
+
+ case LineWidthIdx:
+ if (objc == 2) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewDoubleObj((double)curpage->wirewidth / 2.0));
+ }
+ else if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, "linewidth");
+ return TCL_ERROR;
+ }
+ else {
+ strcpy(_STR2, Tcl_GetString(objv[2]));
+ setwidth(NULL, &(curpage->wirewidth));
+ }
+ break;
+
+ case BBoxIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->bboxon) ? "visible" : "invisible", NULL);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ if (strstr(tmpstr, "visible"))
+ tmpint = (tmpstr[0] == 'i') ? False : True;
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ }
+ areawin->bboxon = (Boolean) tmpint;
+ }
+ break;
+
+ case HoldIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (xobjs.hold) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ xobjs.hold = (Boolean) tmpint;
+ }
+ break;
+
+ case EditInPlaceIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->editinplace) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->editinplace = (Boolean) tmpint;
+ }
+ break;
+
+ case ShowClipIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->showclipmasks) ? "show" : "hide", NULL);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ if (!strcmp(tmpstr, "show"))
+ tmpint = True;
+ else if (!strcmp(tmpstr, "hide"))
+ tmpint = False;
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ }
+ areawin->showclipmasks = (Boolean) tmpint;
+ }
+ break;
+
+ case PinPosIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->pinpointon) ? "visible" : "invisible", NULL);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ if (strstr(tmpstr, "visible"))
+ tmpint = (tmpstr[0] == 'i') ? False : True;
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ }
+ areawin->pinpointon = (Boolean) tmpint;
+ }
+ break;
+
+ case PinAttachIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->pinattach) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->pinattach = (Boolean) tmpint;
+ }
+ break;
+
+ case ColorSchemeIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->invert) ? "inverse" : "normal", NULL);
+ }
+ else {
+ tmpstr = Tcl_GetString(objv[2]);
+ if (!strcmp(tmpstr, "normal") || !strcmp(tmpstr, "standard"))
+ tmpint = False;
+ else if (!strcmp(tmpstr, "inverse") || !strcmp(tmpstr, "alternate"))
+ tmpint = True;
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ }
+ areawin->invert = (Boolean) tmpint;
+ setcolorscheme(!areawin->invert);
+ }
+ break;
+
+ case CoordStyleIdx:
+ if (objc == 2) {
+ switch (curpage->coordstyle) {
+ case DEC_INCH: idx = 0; break;
+ case FRAC_INCH: idx = 1; break;
+ case CM: idx = 2; break;
+ case INTERNAL: idx = 3; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(coordsubCmds[idx],
+ strlen(coordsubCmds[idx])));
+ }
+ else if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "coordstyle ?arg ...?");
+ return TCL_ERROR;
+ }
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)coordsubCmds,
+ "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (idx) {
+ case 0: tmpint = DEC_INCH; break;
+ case 1: tmpint = FRAC_INCH; break;
+ case 2: tmpint = CM; break;
+ case 3: tmpint = INTERNAL; break;
+ }
+ getgridtype(NULL, tmpint, NULL);
+ }
+ break;
+
+ case ScaleIdx:
+ if (objc == 2) {
+ Tcl_Obj *objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj((int)curpage->drawingscale.x));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(":", 1));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj((int)curpage->drawingscale.y));
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ else if (objc == 3) {
+ strcpy(_STR2, Tcl_GetString(objv[2]));
+ setdscale(NULL, &(curpage->drawingscale));
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 2, objv, "drawingscale ?arg ...?");
+ return TCL_ERROR;
+ }
+ break;
+
+ case TechnologysIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (xobjs.showtech) ? "true" : "false", NULL);
+ }
+ else {
+ short libnum;
+
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ if (xobjs.showtech != (Boolean) tmpint) {
+ xobjs.showtech = (Boolean) tmpint;
+
+ /* When namespaces are included, the length of the printed */
+ /* name may cause names to overlap, so recompose each */
+ /* library when the showtech flag is changed. */
+ for (libnum = 0; libnum < xobjs.numlibs; libnum++)
+ composelib(LIBRARY + libnum);
+
+ if (eventmode == CATALOG_MODE) refresh(NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ case ManhattanIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->manhatn) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->manhatn = (Boolean) tmpint;
+ }
+ break;
+
+ case CenteringIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (areawin->center) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ areawin->center = (Boolean) tmpint;
+ }
+ break;
+
+ case FilterIdx:
+ if (objc == 2) {
+ for (i = 0; i < 6; i++) {
+ tmpint = 1 << i;
+ if (areawin->filter & tmpint) {
+ Tcl_AppendElement(interp, filterTypes[i]);
+ }
+ }
+ }
+ else if (objc >= 3) {
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)filterTypes,
+ "filter_type", 0, &tmpint) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (areawin->filter & (1 << tmpint))
+ Tcl_SetResult(interp, "true", NULL);
+ else
+ Tcl_SetResult(interp, "false", NULL);
+ }
+ else {
+ int ftype = 1 << tmpint;
+ if (!strcmp(Tcl_GetString(objv[3]), "true"))
+ areawin->filter |= ftype;
+ else
+ areawin->filter &= (~ftype);
+ }
+ }
+ break;
+
+ case BusCharIdx:
+ if (objc == 2) {
+ buffer[0] = '\\';
+ buffer[1] = areawin->buschar;
+ buffer[2] = '\0';
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
+ }
+ else if (objc == 3) {
+ tmpstr = Tcl_GetString(objv[2]);
+ areawin->buschar = (tmpstr[0] == '\\') ? tmpstr[1] : tmpstr[0];
+ }
+ break;
+
+ case BackupIdx:
+ if (objc == 2) {
+ Tcl_SetResult(interp, (xobjs.retain_backup) ? "true" : "false", NULL);
+ }
+ else {
+ result = Tcl_GetBooleanFromObj(interp, objv[2], &tmpint);
+ if (result != TCL_OK) return result;
+ xobjs.retain_backup = (Boolean) tmpint;
+ }
+ break;
+
+ case SearchIdx:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "search files|libraries ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)searchOpts, "options", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ sptr = (idx == 0) ? &xobjs.filesearchpath : &xobjs.libsearchpath;
+ if (objc == 3) {
+ if (*sptr != NULL) Tcl_SetResult(interp, *sptr, TCL_VOLATILE);
+ }
+ else {
+ if (*sptr != NULL) free(*sptr);
+ *sptr = NULL;
+ tmpstr = Tcl_GetString(objv[3]);
+ if (strlen(tmpstr) > 0)
+ *sptr = strdup(Tcl_GetString(objv[3]));
+ }
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_promptsavepage(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int page = areawin->page;
+ int result;
+ Pagedata *curpage;
+ objectptr pageobj;
+ struct stat statbuf;
+
+ /* save page popup */
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "[page_number]");
+ return TCL_ERROR;
+ }
+ else if (objc == 2) {
+ result = Tcl_GetIntFromObj(interp, objv[1], &page);
+ if (result != TCL_OK) return result;
+ }
+ else page = areawin->page;
+
+ curpage = xobjs.pagelist[page];
+ if (curpage->pageinst == NULL) {
+ Tcl_SetResult(interp, "Page does not exist. . . cannot save.", NULL);
+ return TCL_ERROR;
+ }
+ pageobj = curpage->pageinst->thisobject;
+
+ /* recompute bounding box and auto-scale, if set */
+
+ calcbbox(xobjs.pagelist[page]->pageinst);
+ if (curpage->pmode & 2) autoscale(page);
+
+ /* get file information, if filename is set */
+
+ if (curpage->filename != NULL) {
+ if (strstr(curpage->filename, ".") == NULL)
+ sprintf(_STR2, "%s.ps", curpage->filename);
+ else sprintf(_STR2, "%s", curpage->filename);
+ if (stat(_STR2, &statbuf) == 0) {
+ Wprintf(" Warning: File exists");
+ }
+ else {
+ if (errno == ENOTDIR)
+ Wprintf("Error: Incorrect pathname");
+ else if (errno == EACCES)
+ Wprintf("Error: Path not readable");
+ else
+ W3printf(" ");
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj((int)page));
+
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_quit(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ /* quit, without checks */
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ quit(areawin->area, NULL);
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_promptquit(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ /* quit, with checks */
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ if (areawin != NULL)
+ quitcheck(areawin->area, NULL, NULL);
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_refresh(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ /* refresh */
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ drawarea(areawin->area, (caddr_t)clientData, (caddr_t)NULL);
+ if (areawin->scrollbarh)
+ drawhbar(areawin->scrollbarh, NULL, NULL);
+ if (areawin->scrollbarv)
+ drawvbar(areawin->scrollbarv, NULL, NULL);
+ printname(topobject);
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Load a schematic that belongs to a symbol referenced by the current */
+/* schematic by loading the file pointed to by the "link" parameter */
+/* in the symbol. */
+/* */
+/* Return 1 on success, 0 if the link has already been loaded, and -1 */
+/* on failure to find, open, or read the link's schematic. */
+/*----------------------------------------------------------------------*/
+
+int loadlinkfile(objinstptr tinst, char *filename, int target, Boolean do_load)
+{
+ int j, savepage;
+ FILE *ps;
+ char file_return[150];
+ int result;
+
+ /* Shorthand: "%n" can be used to indicate that the link filename is */
+ /* the same as the name of the object, minus technology prefix. */
+ /* While unlikely to be used, "%N" includes the technology prefix. */
+
+ if (!strcmp(filename, "%n")) {
+ char *suffix = strstr(tinst->thisobject->name, "::");
+ if (suffix == NULL)
+ suffix = tinst->thisobject->name;
+ else
+ suffix += 2;
+ strcpy(_STR, suffix);
+ }
+ else if (!strcmp(filename, "%N"))
+ strcpy(_STR, tinst->thisobject->name);
+ else
+ strcpy(_STR, filename);
+
+ /* When loading links, we want to avoid */
+ /* loading the same file more than once, so */
+ /* compare filename against all existing */
+ /* page filenames. Also compare links; any */
+ /* page with a link to the same object is a */
+ /* duplicate. */
+
+ ps = fileopen(_STR, ".ps", file_return, 149);
+ if (ps != NULL) {
+ fclose(ps);
+ for (j = 0; j < xobjs.pages; j++) {
+ if (xobjs.pagelist[j]->filename == NULL)
+ continue;
+ else if (!strcmp(file_return, xobjs.pagelist[j]->filename))
+ break;
+ else if ((strlen(xobjs.pagelist[j]->filename) > 0) &&
+ !strcmp(file_return + strlen(file_return) - 3, ".ps")
+ && !strncmp(xobjs.pagelist[j]->filename, file_return,
+ strlen(file_return) - 3))
+ break;
+ else if ((xobjs.pagelist[j]->pageinst != NULL) && (tinst->thisobject ==
+ xobjs.pagelist[j]->pageinst->thisobject->symschem))
+ break;
+ }
+ if (j < xobjs.pages) {
+
+ /* Duplicate page. Don't load it, but make sure that an association */
+ /* exists between the symbol and schematic. */
+
+ if (tinst->thisobject->symschem == NULL) {
+ tinst->thisobject->symschem =
+ xobjs.pagelist[j]->pageinst->thisobject;
+ if (xobjs.pagelist[j]->pageinst->thisobject->symschem == NULL)
+ xobjs.pagelist[j]->pageinst->thisobject->symschem = tinst->thisobject;
+ }
+ return 0;
+ }
+ }
+ else {
+ Fprintf(stderr, "Failed to open dependency \"%s\"\n", _STR);
+ return -1;
+ }
+
+ /* Report that a pending link exists, but do not load it. */
+ if (!do_load) return 1;
+
+ savepage = areawin->page;
+ while (areawin->page < xobjs.pages &&
+ xobjs.pagelist[areawin->page]->pageinst != NULL &&
+ xobjs.pagelist[areawin->page]->pageinst->thisobject->parts > 0)
+ areawin->page++;
+
+ changepage(areawin->page);
+ result = (loadfile(0, (target >= 0) ? target + LIBRARY : -1) == TRUE) ? 1 : -1;
+
+ /* Make symschem link if not done by loadfile() */
+
+ if (tinst->thisobject->symschem == NULL) {
+ tinst->thisobject->symschem =
+ xobjs.pagelist[areawin->page]->pageinst->thisobject;
+
+ /* Many symbols may link to one schematic, but a schematic can */
+ /* only link to one symbol (the first one associated). */
+
+ if (xobjs.pagelist[areawin->page]->pageinst->thisobject->symschem == NULL)
+ xobjs.pagelist[areawin->page]->pageinst->thisobject->symschem
+ = tinst->thisobject;
+ }
+ changepage(savepage);
+ return result;
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_page(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result, idx, nidx, aval, i, locidx;
+ int cpage, multi, savepage, pageno = -1, linktype, importtype;
+ char *filename, *froot, *astr;
+ Tcl_Obj *objPtr;
+ double newheight, newwidth, newscale;
+ float oldscale;
+ int newrot, newmode;
+ objectptr pageobj;
+ oparamptr ops;
+ char *oldstr, *newstr, *key, *argv;
+ Pagedata *curpage, *lpage;
+ short *pagelist;
+ u_short changes;
+ int target = -1;
+ Boolean forcepage = FALSE;
+
+ char *subCmds[] = {
+ "load", "list", "import", "save", "saveonly", "make", "directory",
+ "reset", "links", "fit", "filename", "label", "scale", "width",
+ "height", "size", "margins", "bbox", "goto", "orientation",
+ "encapsulation", "handle", "changes", NULL
+ };
+ enum SubIdx {
+ LoadIdx, ListIdx, ImportIdx, SaveIdx, SaveOnlyIdx, MakeIdx, DirIdx,
+ ResetIdx, LinksIdx, FitIdx, FileIdx, LabelIdx, ScaleIdx,
+ WidthIdx, HeightIdx, SizeIdx, MarginsIdx, BBoxIdx, GoToIdx,
+ OrientIdx, EPSIdx, HandleIdx, ChangesIdx
+ };
+
+ char *importTypes[] = {"xcircuit", "postscript", "background", "spice", NULL};
+ enum ImportTypes {
+ XCircuitIdx, PostScriptIdx, BackGroundIdx, SPICEIdx
+ };
+
+ char *linkTypes[] = {"independent", "dependent", "total", "linked",
+ "pagedependent", "all", "pending", "sheet", "load", NULL};
+ enum LinkTypes {
+ IndepIdx, DepIdx, TotalIdx, LinkedIdx, PageDepIdx, AllIdx, PendingIdx,
+ SheetIdx, LinkLoadIdx
+ };
+ char *psTypes[] = {"eps", "full", NULL};
+
+ if (areawin == NULL) {
+ Tcl_SetResult(interp, "No database!", NULL);
+ return TCL_ERROR;
+ }
+ savepage = areawin->page;
+
+ /* Check for option "-force" (create page if it doesn't exist) */
+ if (!strncmp(Tcl_GetString(objv[objc - 1]), "-forc", 5)) {
+ forcepage = TRUE;
+ objc--;
+ }
+
+ result = ParsePageArguments(interp, objc, objv, &nidx, &pageno);
+ if ((result != TCL_OK) || (nidx < 0)) {
+ if (forcepage && (pageno == xobjs.pages)) {
+ /* For now, allow a page to be created only if the page number */
+ /* is one higher than the current last page. */
+ Tcl_ResetResult(interp);
+ idx = MakeIdx;
+ nidx = 0;
+ pageno = areawin->page; /* so we don't get a segfault */
+ }
+ else
+ return result;
+ }
+ else if (nidx == 1 && objc == 2) {
+ idx = GoToIdx;
+ }
+ else if (Tcl_GetIndexFromObj(interp, objv[1 + nidx],
+ (CONST84 char **)subCmds, "option", 0, &idx) != TCL_OK) {
+ return result;
+ }
+
+ result = TCL_OK;
+
+ curpage = xobjs.pagelist[pageno];
+
+ if (curpage->pageinst != NULL)
+ pageobj = curpage->pageinst->thisobject;
+ else {
+ if (idx != LoadIdx && idx != MakeIdx && idx != DirIdx && idx != GoToIdx) {
+ Tcl_SetResult(interp, "Cannot do function on non-initialized page.", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ switch (idx) {
+ case HandleIdx:
+ /* return handle of page instance */
+ objPtr = Tcl_NewHandleObj(curpage->pageinst);
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case ResetIdx:
+ /* clear page */
+ resetbutton(NULL, (pointertype)(pageno + 1), NULL);
+ break;
+
+ case ListIdx:
+ /* return a list of all non-empty pages */
+ objPtr = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < xobjs.pages; i++) {
+ lpage = xobjs.pagelist[i];
+ if ((lpage != NULL) && (lpage->pageinst != NULL)) {
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(i + 1));
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case LoadIdx:
+ TechReplaceSave();
+ sprintf(_STR2, Tcl_GetString(objv[2 + nidx]));
+ for (i = 3 + nidx; i < objc; i++) {
+ argv = Tcl_GetString(objv[i]);
+ if ((*argv == '-') && !strncmp(argv, "-repl", 5)) {
+ if (i < objc - 1) {
+ char *techstr = Tcl_GetString(objv[i + 1]);
+ if (!strcmp(techstr, "all") || !strcmp(techstr, "any"))
+ TechReplaceAll();
+ else if (!strcmp(techstr, "none")) TechReplaceNone();
+ else {
+ TechPtr nsptr = LookupTechnology(techstr);
+ if (nsptr != NULL) nsptr->flags |= TECH_REPLACE;
+ }
+ i++;
+ }
+ else
+ TechReplaceAll(); /* replace ALL */
+ }
+ else if ((*argv == '-') && !strncmp(argv, "-targ", 5)) {
+ if (i < objc - 1) {
+ ParseLibArguments(interp, 2, &objv[i], NULL, &target);
+ i++;
+ }
+ }
+ else {
+ strcat(_STR2, ",");
+ strcat(_STR2, argv);
+ }
+ }
+
+ if (savepage != pageno) newpage(pageno);
+ startloadfile((target >= 0) ? target + LIBRARY : -1);
+ if (savepage != pageno) newpage(savepage);
+ TechReplaceRestore();
+ break;
+
+ case ImportIdx:
+ if ((objc - nidx) < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2 + nidx],
+ (CONST84 char **)importTypes, "file type",
+ 0, &importtype) != TCL_OK)
+ return TCL_ERROR;
+
+ /* First check the number of arguments, which varies by option. */
+
+ switch (importtype) {
+
+ /* Xcircuit imports may specify any number of files > 1. */
+
+ case XCircuitIdx:
+ if ((objc - nidx) == 3) {
+ Tcl_SetResult(interp, "Must specify a filename to import!", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ /* Postscript imports may specify 1 or 0 files. 0 causes */
+ /* the function to report back what file is the background. */
+
+ case PostScriptIdx:
+ case BackGroundIdx:
+ if ((objc - nidx) != 3 && (objc - nidx) != 4) {
+ Tcl_SetResult(interp, "Can only specify one filename "
+ "for background", NULL);
+ return TCL_ERROR;
+ }
+
+ /* All other import types must specify exactly one filename. */
+
+ default:
+ if ((objc - nidx) != 4) {
+ Tcl_SetResult(interp, "Must specify one filename "
+ "for import", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ }
+
+ /* Now process the option */
+
+ switch (importtype) {
+ case XCircuitIdx:
+ sprintf(_STR2, Tcl_GetString(objv[3 + nidx]));
+ for (i = 4; i < objc; i++) {
+ strcat(_STR2, ",");
+ strcat(_STR2, Tcl_GetString(objv[i + nidx]));
+ }
+ if (savepage != pageno) newpage(pageno);
+ importfile();
+ if (savepage != pageno) newpage(savepage);
+ break;
+ case PostScriptIdx: /* replaces "background" */
+ case BackGroundIdx:
+ if (objc - nidx == 2) {
+ objPtr = Tcl_NewStringObj(curpage->background.name,
+ strlen(curpage->background.name));
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ sprintf(_STR2, Tcl_GetString(objv[3 + nidx]));
+ if (savepage != pageno) newpage(pageno);
+ loadbackground();
+ if (savepage != pageno) newpage(savepage);
+ break;
+
+ case SPICEIdx:
+#ifdef ASG
+ /* Make sure that the ASG library is present */
+
+ if (NameToLibrary(ASG_SPICE_LIB) < 0) {
+ short ilib;
+
+ strcpy(_STR, ASG_SPICE_LIB);
+ ilib = createlibrary(FALSE);
+ if (loadlibrary(ilib) == FALSE) {
+ Tcl_SetResult(interp, "Error loading library.\n", NULL);
+ return TCL_ERROR;
+ }
+
+ }
+
+ sprintf(_STR2, Tcl_GetString(objv[3 + nidx]));
+ if (savepage != pageno) newpage(pageno);
+ importspice();
+ if (savepage != pageno) newpage(savepage);
+#else
+ Tcl_SetResult(interp, "ASG not compiled in; "
+ "function is unavailable.\n", NULL);
+ return TCL_ERROR;
+#endif
+ break;
+ }
+
+ /* Redraw */
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case MakeIdx:
+ if (nidx == 1) {
+ Tcl_SetResult(interp, "syntax is: \"page make [<name>]\"", NULL);
+ return TCL_ERROR;
+ }
+ if (objc != 2 && objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "make [<name>]");
+ return TCL_ERROR;
+ }
+ newpage((short)255);
+ if (objc == 3) {
+ curpage = xobjs.pagelist[areawin->page];
+ strcpy(curpage->pageinst->thisobject->name,
+ Tcl_GetString(objv[2]));
+ }
+ updatepagelib(PAGELIB, areawin->page);
+ printname(topobject);
+ break;
+ case SaveOnlyIdx:
+ case SaveIdx:
+ if (objc - nidx > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "[filename]");
+ return TCL_ERROR;
+ }
+ else if (objc - nidx == 3) {
+ filename = Tcl_GetString(objv[nidx + 2]);
+ if (strcmp(filename, curpage->filename)) {
+ Wprintf("Warning: Filename is \"%s\" but will be "
+ "saved as \"%s\"\n", curpage->filename, filename);
+ }
+ }
+ else if (curpage->filename == NULL) {
+ Fprintf(stderr, "Warning: Filename created to match object name\n");
+ filename = curpage->pageinst->thisobject->name;
+ }
+ else
+ filename = curpage->filename;
+
+ if (savepage != pageno) newpage(pageno);
+ if (!strncmp(Tcl_GetString(objv[nidx + 1]), "saveo", 5))
+ setfile(filename, NO_SUBCIRCUITS);
+ else
+ setfile(filename, CURRENT_PAGE);
+ if (savepage != pageno) newpage(savepage);
+ break;
+
+ case LinksIdx:
+ if ((objc - nidx) < 2 && (objc - nidx) > 6) {
+ Tcl_WrongNumArgs(interp, 1, objv, "links");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2)
+ linktype = TOTAL_PAGES;
+ else {
+ if (Tcl_GetIndexFromObj(interp, objv[2 + nidx],
+ (CONST84 char **)linkTypes,
+ "link type", 0, &linktype) != TCL_OK)
+ return TCL_ERROR;
+ }
+ multi = 0;
+ pagelist = pagetotals(pageno, (linktype >= PendingIdx) ?
+ LINKED_PAGES : linktype);
+ TechReplaceSave();
+ switch (linktype) {
+
+ /* Load any pending links, that is, objects that have a */
+ /* "link" parameter containing a string indicating a file */
+ /* defining the schematic for that symbol. Allow the use */
+ /* of the same "-replace" flag used by "page load". */
+
+ case LinkLoadIdx:
+ locidx = objc - 1;
+ argv = Tcl_GetString(objv[locidx]);
+ if (*argv != '-') argv = Tcl_GetString(objv[--locidx]);
+ if ((*argv == '-') && !strncmp(argv, "-repl", 5)) {
+ if (locidx < objc - 1) {
+ char *techstr = Tcl_GetString(objv[locidx + 1]);
+ if (!strcmp(techstr, "all")) TechReplaceAll();
+ else if (!strcmp(techstr, "none")) TechReplaceNone();
+ else {
+ TechPtr nsptr = LookupTechnology(techstr);
+ if (nsptr != NULL)
+ nsptr->flags |= TECH_REPLACE;
+ }
+ objc--;
+ }
+ else
+ TechReplaceAll(); /* replace ALL */
+ objc--;
+ }
+ if ((*argv == '-') && !strncmp(argv, "-targ", 5)) {
+ if (locidx < objc - 1) {
+ ParseLibArguments(interp, 2, &objv[locidx], NULL, &target);
+ objc--;
+ }
+ objc--;
+ }
+ /* drop through */
+
+ case PendingIdx:
+ key = ((objc - nidx) == 4) ? Tcl_GetString(objv[3 + nidx]) : "link";
+ for (i = 0; i < xobjs.pages; i++) {
+ if (pagelist[i] > 0) {
+ objinstptr tinst;
+ objectptr tpage = xobjs.pagelist[i]->pageinst->thisobject;
+ genericptr *tgen;
+
+ for (tgen = tpage->plist; tgen < tpage->plist
+ + tpage->parts; tgen++) {
+ if ((*tgen)->type == OBJINST) {
+ tinst = TOOBJINST(tgen);
+ /* Corrected 8/31/07: Instance value of "link" has */
+ /* priority over any default value in the object! */
+ ops = find_param(tinst, key);
+ if ((ops != NULL) && (ops->type == XC_STRING)) {
+ filename = textprint(ops->parameter.string, tinst);
+ if (strlen(filename) > 0) {
+ if ((result = loadlinkfile(tinst, filename, target,
+ (linktype == LinkLoadIdx))) > 0) {
+ multi++;
+ setsymschem(); /* Update GUI */
+ result = TCL_OK;
+ }
+ else if (result < 0) {
+ Tcl_SetResult(interp, "Cannot load link", NULL);
+ result = TCL_ERROR;
+ }
+ else result = TCL_OK;
+ }
+ free(filename);
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ for (i = 0; i < xobjs.pages; i++) {
+ if (pagelist[i] > 0) {
+ multi++;
+ if ((linktype == SheetIdx) && (i == pageno) && (pagelist[i] > 0))
+ break;
+ }
+ }
+ break;
+ }
+ TechReplaceRestore();
+ free((char *)pagelist);
+ if (result == TCL_ERROR) return result;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(multi));
+ break;
+
+ case DirIdx:
+ startcatalog(NULL, PAGELIB, NULL);
+ break;
+
+ case GoToIdx:
+ newpage((short)pageno);
+ break;
+
+ case BBoxIdx:
+ if (((objc - nidx) == 2) || ((objc - nidx) == 3)) {
+ Tcl_Obj *tuple;
+ BBox *bbox, *sbbox;
+ int value;
+
+ bbox = &curpage->pageinst->bbox;
+ if (bbox == NULL)
+ bbox = &curpage->pageinst->thisobject->bbox;
+ sbbox = bbox;
+
+ if ((objc - nidx) == 3) {
+ sbbox = curpage->pageinst->schembbox;
+ if (sbbox == NULL) sbbox = bbox;
+ }
+
+ objPtr = Tcl_NewListObj(0, NULL);
+
+ tuple = Tcl_NewListObj(0, NULL);
+ value = min(sbbox->lowerleft.x, bbox->lowerleft.x);
+ Tcl_ListObjAppendElement(interp, tuple, Tcl_NewIntObj(value));
+ value = min(sbbox->lowerleft.y, bbox->lowerleft.y);
+ Tcl_ListObjAppendElement(interp, tuple, Tcl_NewIntObj(value));
+ Tcl_ListObjAppendElement(interp, objPtr, tuple);
+
+ tuple = Tcl_NewListObj(0, NULL);
+ value = max(sbbox->lowerleft.x + sbbox->width,
+ bbox->lowerleft.x + bbox->width);
+ Tcl_ListObjAppendElement(interp, tuple, Tcl_NewIntObj(value));
+ value = max(sbbox->lowerleft.y + sbbox->height,
+ bbox->lowerleft.y + bbox->height);
+ Tcl_ListObjAppendElement(interp, tuple, Tcl_NewIntObj(value));
+ Tcl_ListObjAppendElement(interp, objPtr, tuple);
+
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "bbox [all]");
+ return TCL_ERROR;
+ }
+ break;
+
+ case SizeIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "size ?\"width x height\"?");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ float xsize, ysize, cfact;
+
+ objPtr = Tcl_NewListObj(0, NULL);
+
+ cfact = (curpage->coordstyle == CM) ? IN_CM_CONVERT
+ : 72.0;
+ xsize = (float)curpage->pagesize.x / cfact;
+ ysize = (float)curpage->pagesize.y / cfact;
+
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewDoubleObj((double)xsize));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("x", 1));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewDoubleObj((double)ysize));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(((curpage->coordstyle == CM) ?
+ "cm" : "in"), 2));
+ Tcl_SetObjResult(interp, objPtr);
+
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ strcpy(_STR2, Tcl_GetString(objv[2 + nidx]));
+ setoutputpagesize(&curpage->pagesize);
+
+ /* Only need to recompute values and refresh if autoscaling is enabled */
+ if (curpage->pmode & 2) autoscale(pageno);
+ break;
+
+ case MarginsIdx:
+ if ((objc - nidx) < 2 && (objc - nidx) > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "margins ?x y?");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ newwidth = (double)curpage->margins.x / 72.0;
+ newheight = (double)curpage->margins.y / 72.0;
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewDoubleObj(newwidth));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewDoubleObj(newheight));
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ newwidth = (double)parseunits(Tcl_GetString(objv[2 + nidx]));
+ if ((objc - nidx) == 4)
+ newheight = (double)parseunits(Tcl_GetString(objv[3 + nidx]));
+ else
+ newheight = newwidth;
+
+ newheight *= 72.0;
+ newwidth *= 72.0;
+ curpage->margins.x = (int)newwidth;
+ curpage->margins.y = (int)newheight;
+ break;
+
+ case HeightIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "height ?output_height?");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ newheight = toplevelheight(curpage->pageinst, NULL);
+ newheight *= getpsscale(curpage->outscale, pageno);
+ newheight /= (curpage->coordstyle == CM) ? IN_CM_CONVERT : 72.0;
+ objPtr = Tcl_NewDoubleObj((double)newheight);
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ newheight = (double)parseunits(Tcl_GetString(objv[2 + nidx]));
+ if (newheight <= 0 || topobject->bbox.height == 0) {
+ Tcl_SetResult(interp, "Illegal height value", NULL);
+ return TCL_ERROR;
+ }
+ newheight = (newheight * ((curpage->coordstyle == CM) ?
+ IN_CM_CONVERT : 72.0)) / topobject->bbox.height;
+ newheight /= getpsscale(1.0, pageno);
+ curpage->outscale = (float)newheight;
+
+ if (curpage->pmode & 2) autoscale(pageno);
+ break;
+
+ case WidthIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "output_width");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ newwidth = toplevelwidth(curpage->pageinst, NULL);
+ newwidth *= getpsscale(curpage->outscale, pageno);
+ newwidth /= (curpage->coordstyle == CM) ? IN_CM_CONVERT : 72.0;
+ objPtr = Tcl_NewDoubleObj((double)newwidth);
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ newwidth = (double)parseunits(Tcl_GetString(objv[2 + nidx]));
+ if (newwidth <= 0 || topobject->bbox.width == 0) {
+ Tcl_SetResult(interp, "Illegal width value", NULL);
+ return TCL_ERROR;
+ }
+
+ newwidth = (newwidth * ((curpage->coordstyle == CM) ?
+ IN_CM_CONVERT : 72.0)) / topobject->bbox.width;
+ newwidth /= getpsscale(1.0, pageno);
+ curpage->outscale = (float)newwidth;
+
+ if (curpage->pmode & 2) autoscale(pageno);
+ break;
+
+ case ScaleIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "output_scale");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ objPtr = Tcl_NewDoubleObj((double)curpage->outscale);
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ result = Tcl_GetDoubleFromObj(interp, objv[2 + nidx], &newscale);
+ if (result != TCL_OK) return result;
+
+ oldscale = curpage->outscale;
+
+ if (oldscale == (float)newscale) return TCL_OK; /* nothing to do */
+ else curpage->outscale = (float)newscale;
+
+ if (curpage->pmode & 2) autoscale(pageno);
+ break;
+
+ case OrientIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "orientation");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ objPtr = Tcl_NewIntObj((int)curpage->orient);
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2 + nidx], &newrot);
+ if (result != TCL_OK) return result;
+ curpage->orient = (short)newrot;
+
+ /* rescale after rotation if "auto-scale" is set */
+ if (curpage->pmode & 2) autoscale(pageno);
+ break;
+
+ case EPSIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "encapsulation");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ newstr = psTypes[curpage->pmode & 1];
+ Tcl_SetResult(interp, newstr, NULL);
+ return XcTagCallback(interp, objc, objv);
+ }
+ newstr = Tcl_GetString(objv[2 + nidx]);
+ if (Tcl_GetIndexFromObj(interp, objv[2 + nidx],
+ (CONST84 char **)psTypes,
+ "encapsulation", 0, &newmode) != TCL_OK) {
+ return result;
+ }
+ curpage->pmode &= 0x2; /* preserve auto-fit flag */
+ curpage->pmode |= (short)newmode;
+ break;
+
+ case LabelIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "label ?name?");
+ return TCL_ERROR;
+ }
+ if ((objc - nidx) == 2) {
+ objPtr = Tcl_NewStringObj(pageobj->name, strlen(pageobj->name));
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ /* Whitespace and non-printing characters not allowed */
+
+ strcpy(_STR2, Tcl_GetString(objv[2 + nidx]));
+ for (i = 0; i < strlen(_STR2); i++) {
+ if ((!isprint(_STR2[i])) || (isspace(_STR2[i]))) {
+ _STR2[i] = '_';
+ Wprintf("Replaced illegal whitespace in name with underscore");
+ }
+ }
+
+ if (!strcmp(pageobj->name, _STR2)) return TCL_OK; /* no change in string */
+ if (strlen(_STR2) == 0)
+ sprintf(pageobj->name, "Page %d", areawin->page + 1);
+ else
+ sprintf(pageobj->name, "%.79s", _STR2);
+
+ /* For schematics, all pages with associations to symbols must have */
+ /* unique names. */
+ if (pageobj->symschem != NULL) checkpagename(pageobj);
+
+ if (pageobj == topobject) printname(pageobj);
+ renamepage(pageno);
+ break;
+
+ case FileIdx:
+
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "filename ?name?");
+ return TCL_ERROR;
+ }
+
+ oldstr = curpage->filename;
+
+ if ((objc - nidx) == 2) {
+ if (oldstr)
+ objPtr = Tcl_NewStringObj(oldstr, strlen(oldstr));
+ else
+ objPtr = Tcl_NewListObj(0, NULL); /* NULL list */
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ newstr = Tcl_GetString(objv[2 + nidx]);
+ if (strlen(newstr) > 0) {
+ froot = strrchr(newstr, '/');
+ if (froot == NULL) froot = newstr;
+ if (strchr(froot, '.') == NULL) {
+ astr = malloc(strlen(newstr) + 4);
+ sprintf(astr, "%s.ps", newstr);
+ newstr = astr;
+ }
+ }
+
+ if (oldstr && (!strcmp(oldstr, newstr))) { /* no change in string */
+ if (newstr == astr) free(astr);
+ return XcTagCallback(interp, objc, objv);
+ }
+
+ if (strlen(newstr) == 0) { /* empty string */
+ Tcl_SetResult(interp, "Warning: No filename!", NULL);
+ multi = 1;
+ }
+ else {
+ multi = pagelinks(pageno); /* Are there multiple pages? */
+ }
+
+ /* Make the change to the current page */
+ curpage->filename = strdup(newstr);
+ if (newstr == astr) free(astr);
+
+ /* All existing filenames which match the old string should */
+ /* also be changed unless the filename has been set to the */
+ /* null string, which unlinks the page. */
+
+ if ((strlen(curpage->filename) > 0) && (multi > 1)) {
+ for (cpage = 0; cpage < xobjs.pages; cpage++) {
+ lpage = xobjs.pagelist[cpage];
+ if ((lpage->pageinst != NULL) && (cpage != pageno)) {
+ if (lpage->filename && (!filecmp(lpage->filename, oldstr))) {
+ free(lpage->filename);
+ lpage->filename = strdup(newstr);
+ }
+ }
+ }
+ }
+ free(oldstr);
+ autoscale(pageno);
+
+ /* Run pagelinks again; this checks if a page has been attached */
+ /* to existing schematics by being renamed to match. */
+
+ if ((strlen(curpage->filename) > 0) && (multi <= 1)) {
+ for (cpage = 0; cpage < xobjs.pages; cpage++) {
+ lpage = xobjs.pagelist[cpage];
+ if ((lpage->pageinst != NULL) && (cpage != pageno)) {
+ if (lpage->filename && (!filecmp(lpage->filename,
+ curpage->filename))) {
+ free(curpage->filename);
+ curpage->filename = strdup(lpage->filename);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case FitIdx:
+ if ((objc - nidx) > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "fit ?true|false?");
+ return TCL_ERROR;
+ }
+ else if ((objc - nidx) == 3) {
+ result = Tcl_GetBooleanFromObj(interp, objv[2 + nidx], &aval);
+ if (result != TCL_OK) return result;
+ if (aval)
+ curpage->pmode |= 2;
+ else
+ curpage->pmode &= 1;
+ }
+ else
+ Tcl_SetResult(interp, ((curpage->pmode & 2) > 0) ? "true" : "false", NULL);
+
+ /* Refresh values (does autoscale if specified) */
+ autoscale(pageno);
+ break;
+
+ case ChangesIdx:
+ if ((objc - nidx) != 2 && (objc - nidx) != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "changes");
+ return TCL_ERROR;
+ }
+ /* Allow changes to be set, so that a page can be forced to be */
+ /* recognized as either modified or unmodified. */
+
+ if ((objc - nidx) == 3) {
+ int value;
+ Tcl_GetIntFromObj(interp, objv[2 + nidx], &value);
+ curpage->pageinst->thisobject->changes = (u_short)value;
+ }
+ changes = getchanges(curpage->pageinst->thisobject);
+ objPtr = Tcl_NewIntObj((double)changes);
+ Tcl_SetObjResult(interp, objPtr);
+ return XcTagCallback(interp, objc, objv);
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* The "technology" command deals with library *technologies*, where */
+/* they differ from files or pages (see the "library" command */
+/* xctcl_library, below). Specifically, "library load" loads a file */
+/* (containing object defintions in a specific technology) onto a page, */
+/* whereas "technology save" writes back the object definitions that */
+/* came from the specified file. Although one would typically have one */
+/* library page per technology, this is not necessarily the case. */
+/* */
+/* Only one technology is defined by a library file, but the library */
+/* may contain (copies of) dependent objects from another technology. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_tech(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char *technology, *filename, *libobjname;
+ short *pagelist;
+ int idx, ilib, j, pageno, nidx, result;
+ TechPtr nsptr = NULL;
+ Tcl_Obj *olist;
+ objectptr libobj;
+ Boolean usertech = FALSE;
+ FILE *chklib;
+
+ char *subCmds[] = {
+ "save", "list", "objects", "filename", "changed", "used", "writable",
+ "writeable", NULL
+ };
+ enum SubIdx {
+ SaveIdx, ListIdx, ObjectsIdx, FileNameIdx, ChangedIdx, UsedIdx,
+ WritableIdx, WriteableIdx
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)subCmds, "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* All options except "list" and "used" expect a technology argument */
+ if (idx != ListIdx && idx != UsedIdx) {
+ if (objc > 2) {
+ technology = Tcl_GetString(objv[2]);
+ nsptr = LookupTechnology(technology);
+ if (nsptr == NULL) {
+
+ /* If the command is "objects" and has one or more */
+ /* additional arguments, then a NULL nsptr is okay (new */
+ /* technology will be created and added to the list). */
+
+ if (idx != ObjectsIdx || objc <= 3) {
+
+ /* If nsptr is NULL, then the technology should be */
+ /* "none" or "user" */
+
+ if ((strstr(technology, "none") == NULL) &&
+ (strstr(technology, "user") == NULL)) {
+ Tcl_SetResult(interp, "Error: Unknown technology name!", NULL);
+ return TCL_ERROR;
+ }
+ usertech = TRUE;
+ }
+ }
+
+ /* And if the user technology has been saved to a file, the technology */
+ /* will have a NULL string. Also check for technology name "(user)", */
+ /* although that is not supposed to happen. */
+
+ else if (*nsptr->technology == '\0')
+ usertech = TRUE;
+
+ else if (!strcmp(nsptr->technology, "(user)"))
+ usertech = TRUE;
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "<option> technology ?args ...?");
+ return TCL_ERROR;
+ }
+ }
+
+ switch (idx) {
+ case ListIdx:
+ /* List all of the known technologies */
+ olist = Tcl_NewListObj(0, NULL);
+ for (nsptr = xobjs.technologies; nsptr != NULL; nsptr = nsptr->next) {
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewStringObj(nsptr->technology,
+ strlen(nsptr->technology)));
+ }
+ Tcl_SetObjResult(interp, olist);
+ break;
+
+ case UsedIdx:
+ /* List all of the technologies used by the schematic of the */
+ /* indicated (or current) page. That is, enumerate all */
+ /* in the hierarchy of the schematic, and list all unique */
+ /* technology prefixes. */
+
+ result = ParsePageArguments(interp, objc - 1, objv + 1, &nidx, &pageno);
+ if (result != TCL_OK) return result;
+ olist = Tcl_NewListObj(0, NULL);
+
+ pagelist = pagetotals(pageno, TOTAL_PAGES);
+ for (j = 0; j < xobjs.pages; j++) {
+ if (pagelist[j] > 0) {
+ objinstptr tinst;
+ objectptr tpage = xobjs.pagelist[j]->pageinst->thisobject;
+ genericptr *tgen;
+
+ for (tgen = tpage->plist; tgen < tpage->plist + tpage->parts; tgen++) {
+ if ((*tgen)->type == OBJINST) {
+ tinst = TOOBJINST(tgen);
+ nsptr = GetObjectTechnology(tinst->thisobject);
+ if (nsptr != NULL) {
+ if ((nsptr->technology == NULL) ||
+ (strlen(nsptr->technology) == 0)) continue;
+ if (!(nsptr->flags & TECH_USED)) {
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewStringObj(nsptr->technology,
+ strlen(nsptr->technology)));
+ nsptr->flags |= TECH_USED;
+ }
+ }
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, olist);
+ for (nsptr = xobjs.technologies; nsptr != NULL; nsptr = nsptr->next)
+ nsptr->flags &= ~TECH_USED;
+ free((char *)pagelist);
+ break;
+
+ case ObjectsIdx:
+
+ if (objc > 3) {
+ int numobjs, objnamelen, technamelen;
+ Tcl_Obj *tobj;
+ char *cptr;
+ TechPtr otech;
+
+ /* Check that 4th argument is a list of objects or that */
+ /* 4th and higher arguments are all names of objects, and */
+ /* that these objects are valid existing objects. */
+
+ if (objc == 4) {
+ result = Tcl_ListObjLength(interp, objv[3], &numobjs);
+ if (result != TCL_OK) return result;
+ for (j = 0; j < numobjs; j++) {
+ result = Tcl_ListObjIndex(interp, objv[3], j, &tobj);
+ if (result != TCL_OK) return result;
+ libobj = NameToObject(Tcl_GetString(tobj), NULL, FALSE);
+ if (libobj == NULL) {
+ Tcl_SetResult(interp, "No such object name", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ else {
+ for (j = 0; j < objc - 4; j++) {
+ libobj = NameToObject(Tcl_GetString(objv[3 + j]), NULL, FALSE);
+ if (libobj == NULL) {
+ Tcl_SetResult(interp, "No such object name", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ /* Create a new technology if needed */
+ technology = Tcl_GetString(objv[2]);
+ if ((nsptr == NULL) && !usertech)
+ AddNewTechnology(technology, NULL);
+
+ nsptr = LookupTechnology(technology);
+ technamelen = (usertech) ? 0 : strlen(technology);
+
+
+ /* Change the technology prefix of all the objects listed */
+
+ if (objc == 4) {
+ result = Tcl_ListObjLength(interp, objv[3], &numobjs);
+ if (result != TCL_OK) return result;
+ for (j = 0; j < numobjs; j++) {
+ result = Tcl_ListObjIndex(interp, objv[3], j, &tobj);
+ if (result != TCL_OK) return result;
+ libobj = NameToObject(Tcl_GetString(tobj), NULL, FALSE);
+ cptr = strstr(libobj->name, "::");
+ if (cptr == NULL) {
+ objnamelen = strlen(libobj->name);
+ memmove(libobj->name + technamelen + 2,
+ libobj->name, (size_t)strlen(libobj->name));
+ }
+ else {
+ otech = GetObjectTechnology(libobj);
+ otech->flags |= TECH_CHANGED;
+ objnamelen = strlen(cptr + 2);
+ memmove(libobj->name + technamelen + 2,
+ cptr + 2, (size_t)strlen(cptr + 2));
+ }
+
+ if (!usertech) strcpy(libobj->name, technology);
+ *(libobj->name + technamelen) = ':';
+ *(libobj->name + technamelen + 1) = ':';
+ *(libobj->name + technamelen + 2 + objnamelen) = '\0';
+ }
+ }
+ else {
+ for (j = 0; j < objc - 4; j++) {
+ libobj = NameToObject(Tcl_GetString(objv[3 + j]), NULL, FALSE);
+ cptr = strstr(libobj->name, "::");
+ if (cptr == NULL) {
+ objnamelen = strlen(libobj->name);
+ memmove(libobj->name + technamelen + 2,
+ libobj->name, (size_t)strlen(libobj->name));
+ }
+ else {
+ otech = GetObjectTechnology(libobj);
+ otech->flags |= TECH_CHANGED;
+ objnamelen = strlen(cptr + 2);
+ memmove(libobj->name + technamelen + 2,
+ cptr + 2, (size_t)strlen(cptr + 2));
+ }
+
+ if (!usertech) strcpy(libobj->name, technology);
+ *(libobj->name + technamelen) = ':';
+ *(libobj->name + technamelen + 1) = ':';
+ *(libobj->name + technamelen + 2 + objnamelen) = '\0';
+ }
+ }
+ if (nsptr != NULL) nsptr->flags |= TECH_CHANGED;
+ break;
+ }
+
+ /* List all objects having this technology */
+
+ olist = Tcl_NewListObj(0, NULL);
+ for (ilib = 0; ilib < xobjs.numlibs; ilib++) {
+ for (j = 0; j < xobjs.userlibs[ilib].number; j++) {
+ libobj = *(xobjs.userlibs[ilib].library + j);
+ if (GetObjectTechnology(libobj) == nsptr) {
+ libobjname = strstr(libobj->name, "::");
+ if (libobjname == NULL)
+ libobjname = libobj->name;
+ else
+ libobjname += 2;
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewStringObj(libobjname, strlen(libobjname)));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, olist);
+ break;
+
+ case FileNameIdx:
+ if (nsptr != NULL) {
+ if (objc == 3) {
+ if (nsptr->filename == NULL)
+ Tcl_SetResult(interp, "(no associated file)", NULL);
+ else
+ Tcl_SetResult(interp, nsptr->filename, NULL);
+ }
+ else {
+ if (nsptr->filename != NULL) free(nsptr->filename);
+ nsptr->filename = strdup(Tcl_GetString(objv[3]));
+ }
+ }
+ else {
+ Tcl_SetResult(interp, "Valid technology is required", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case ChangedIdx:
+ if (objc == 4) {
+ int bval;
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &bval) != TCL_OK)
+ return TCL_ERROR;
+ else if (bval == 1)
+ nsptr->flags |= TECH_CHANGED;
+ else
+ nsptr->flags &= ~TECH_CHANGED;
+ }
+ else {
+ tech_set_changes(nsptr); /* Ensure change flags are updated */
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(((nsptr->flags & TECH_CHANGED)
+ == 0) ? FALSE : TRUE));
+ }
+ break;
+
+ case WritableIdx:
+ case WriteableIdx:
+ if (nsptr) {
+ if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(((nsptr->flags & TECH_READONLY) == 0)
+ ? TRUE : FALSE));
+ }
+ else if (objc == 4) {
+ int bval;
+
+ Tcl_GetBooleanFromObj(interp, objv[3], &bval);
+ if (bval == 0)
+ nsptr->flags |= TECH_READONLY;
+ else
+ nsptr->flags &= (~TECH_READONLY);
+ }
+ }
+ else {
+ Tcl_SetResult(interp, "Valid technology is required", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case SaveIdx:
+
+ /* technology save [filename] */
+ if ((objc == 3) && ((nsptr == NULL) || (nsptr->filename == NULL))) {
+ Tcl_SetResult(interp, "Error: Filename is required.", NULL);
+ return TCL_ERROR;
+ }
+ else if ((nsptr != NULL) && (objc == 4)) {
+ /* Technology being saved under a different filename. */
+ filename = Tcl_GetString(objv[3]);
+
+ /* Re-check read-only status of the file */
+ nsptr->flags &= ~(TECH_READONLY);
+ chklib = fopen(filename, "a");
+ if (chklib == NULL)
+ nsptr->flags |= TECH_READONLY;
+ else
+ fclose(chklib);
+ }
+ else if (objc == 4) {
+ filename = Tcl_GetString(objv[3]);
+ if (!usertech) AddNewTechnology(technology, filename);
+ }
+ else
+ filename = nsptr->filename;
+
+ savetechnology((usertech) ? NULL : technology, filename);
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* The "library" command deals with library *pages* */
+/*----------------------------------------------------------------------*/
+
+int xctcl_library(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char *filename = NULL, *objname, *argv;
+ int j = 0, libnum = -1;
+ int idx, nidx, result;
+ Tcl_Obj *olist;
+ Tcl_Obj **newobjv;
+ int newobjc, hidmode;
+ objectptr libobj;
+ liblistptr spec;
+ char *subCmds[] = {
+ "load", "make", "directory", "next", "goto", "override",
+ "handle", "import", "list", "compose", NULL
+ };
+ enum SubIdx {
+ LoadIdx, MakeIdx, DirIdx, NextIdx, GoToIdx, OverrideIdx,
+ HandleIdx, ImportIdx, ListIdx, ComposeIdx
+ };
+
+ result = ParseLibArguments(interp, objc, objv, &nidx, &libnum);
+ if ((result != TCL_OK) || (nidx < 0)) return result;
+ else if ((objc - nidx) > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ else if (objc <= (1 + nidx)) { /* No subcommand */
+
+ /* return index if name given; return name if index given. */
+ /* return index if neither is given (current library) */
+
+ if (objc > 1) {
+ int lnum; /* unused; only checks if argument is integer */
+ char *lname;
+ result = Tcl_GetIntFromObj(interp, objv[1], &lnum);
+ if (result == TCL_OK) {
+ lname = xobjs.libtop[libnum + LIBRARY]->thisobject->name;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(lname, strlen(lname)));
+ }
+ else
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(libnum + 1));
+ }
+ else
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(libnum + 1));
+ idx = -1;
+ }
+ else if (Tcl_GetIndexFromObj(interp, objv[1 + nidx],
+ (CONST84 char **)subCmds, "option", 0, &idx) != TCL_OK) {
+
+ /* Backwards compatibility: "library filename [number]" is */
+ /* the same as "library [number] load filename" */
+
+ Tcl_ResetResult(interp);
+ newobjv = (Tcl_Obj **)(&objv[1]);
+ newobjc = objc - 1;
+
+ result = ParseLibArguments(interp, newobjc, newobjv, &nidx, &libnum);
+ if (result != TCL_OK) return result;
+
+ idx = LoadIdx;
+ filename = Tcl_GetString(newobjv[0]);
+ }
+
+ /* libnum = -1 is equivalent to "USER LIBRARY" */
+ if (libnum < 0) libnum = xobjs.numlibs - 1;
+
+ switch (idx) {
+ case LoadIdx:
+ TechReplaceSave();
+
+ /* library [<name>|<number>] load <filename> [-replace [library]] */
+ if (objc < (3 + nidx)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (filename == NULL) filename = Tcl_GetString(objv[2 + nidx]);
+
+ /* if loading of default libraries is not overridden, load them first */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
+ defaultscript();
+ flags |= LIBLOADED;
+ }
+
+ /* If library number is out of range, create a new library */
+ /* libnum = -1 is equivalent to the user library page. */
+
+ if (libnum > (xobjs.numlibs - 1))
+ libnum = createlibrary(FALSE);
+ else if (libnum < 0)
+ libnum = USERLIB;
+ else
+ libnum += LIBRARY;
+
+ if (objc > (3 + nidx)) {
+ argv = Tcl_GetString(objv[3 + nidx]);
+ if ((*argv == '-') && !strncmp(argv, "-repl", 5)) {
+ if (objc > (4 + nidx)) {
+ char *techstr = Tcl_GetString(objv[3 + nidx]);
+ if (!strcmp(techstr, "all")) TechReplaceAll();
+ else if (!strcmp(techstr, "none")) TechReplaceNone();
+ else {
+ TechPtr nsptr = LookupTechnology(techstr);
+ if (nsptr != NULL)
+ nsptr->flags |= TECH_REPLACE;
+ }
+ }
+ else
+ TechReplaceAll(); /* replace ALL */
+ }
+ }
+
+ strcpy(_STR, filename);
+ result = loadlibrary(libnum);
+ if (result == False) {
+ result = loadfile(2, libnum);
+ TechReplaceRestore();
+ if (result == False) {
+ Tcl_SetResult(interp, "Error loading library.\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ TechReplaceRestore();
+ break;
+
+ case ImportIdx:
+ /* library [<name>|<number>] import <filename> <objectname> */
+ if (objc != (4 + nidx)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (filename == NULL) filename = Tcl_GetString(objv[2 + nidx]);
+
+ /* if loading of default libraries is not overridden, load them first */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
+ defaultscript();
+ flags |= LIBLOADED;
+ }
+
+ if ((libnum >= xobjs.numlibs) || (libnum < 0))
+ libnum = createlibrary(FALSE);
+ else
+ libnum += LIBRARY;
+
+ objname = Tcl_GetString(objv[3 + nidx]);
+ importfromlibrary(libnum, filename, objname);
+ break;
+
+ case ListIdx:
+
+ if (!strncmp(Tcl_GetString(objv[objc - 1]), "-vis", 4))
+ hidmode = 1; /* list visible objects only */
+ else if (!strncmp(Tcl_GetString(objv[objc - 1]), "-hid", 4))
+ hidmode = 2; /* list hidden objects only */
+ else
+ hidmode = 3; /* list everything */
+
+ /* library [name|number] list [-visible|-hidden] */
+ olist = Tcl_NewListObj(0, NULL);
+ for (j = 0; j < xobjs.userlibs[libnum].number; j++) {
+ libobj = *(xobjs.userlibs[libnum].library + j);
+ if (((libobj->hidden) && (hidmode & 2)) ||
+ ((!libobj->hidden) && (hidmode & 1)))
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewStringObj(libobj->name, strlen(libobj->name)));
+ }
+ Tcl_SetObjResult(interp, olist);
+ break;
+
+ case HandleIdx:
+
+ if (objc == (3 + nidx)) {
+ /* library [name|number] handle <object name> */
+
+ olist = Tcl_NewListObj(0, NULL);
+ for (spec = xobjs.userlibs[libnum].instlist; spec != NULL;
+ spec = spec->next) {
+ libobj = spec->thisinst->thisobject;
+ if (!strcmp(libobj->name, Tcl_GetString(objv[objc - 1])))
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewHandleObj((genericptr)spec->thisinst));
+ }
+ Tcl_SetObjResult(interp, olist);
+ }
+ else if (objc == (2 + nidx)) {
+ /* library [name|number] handle */
+
+ olist = Tcl_NewListObj(0, NULL);
+ for (spec = xobjs.userlibs[libnum].instlist; spec != NULL;
+ spec = spec->next) {
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewHandleObj((genericptr)spec->thisinst));
+ }
+ Tcl_SetObjResult(interp, olist);
+ }
+ else {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ break;
+
+ case ComposeIdx:
+ composelib(libnum + LIBRARY);
+ centerview(xobjs.libtop[libnum + LIBRARY]);
+ break;
+
+ case MakeIdx:
+ /* library make [name] */
+ if (nidx == 1) {
+ Tcl_SetResult(interp, "syntax is: library make [<name>]", NULL);
+ return TCL_ERROR;
+ }
+
+ /* If the (named or numbered) library exists, don't create it. */
+ /* ParseLibArguments() returns the library number for the User */
+ /* Library. The User Library always exists and cannot be */
+ /* created or destroyed, so it's okay to use it as a check for */
+ /* "no library found". */
+
+ if (libnum == xobjs.numlibs - 1)
+ libnum = createlibrary(TRUE);
+
+ if (objc == 3) {
+ strcpy(xobjs.libtop[libnum]->thisobject->name, Tcl_GetString(objv[2]));
+ renamelib(libnum);
+ composelib(LIBLIB);
+ }
+ /* Don't go to the library page---use "library goto" instead */
+ /* startcatalog((Tk_Window)clientData, libnum, NULL); */
+ break;
+
+ case DirIdx:
+ /* library directory */
+ if ((nidx == 0) && (objc == 2)) {
+ startcatalog(NULL, LIBLIB, NULL);
+ }
+ else if ((nidx == 0) && (objc == 3) &&
+ !strcmp(Tcl_GetString(objv[2]), "list")) {
+ olist = Tcl_NewListObj(0, NULL);
+ for (j = 0; j < xobjs.numlibs; j++) {
+ libobj = xobjs.libtop[j + LIBRARY]->thisobject;
+ Tcl_ListObjAppendElement(interp, olist,
+ Tcl_NewStringObj(libobj->name, strlen(libobj->name)));
+ }
+ Tcl_SetObjResult(interp, olist);
+ }
+ else {
+ Tcl_SetResult(interp, "syntax is: library directory [list]", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case NextIdx:
+ libnum = is_library(topobject);
+ if (++libnum >= xobjs.numlibs) libnum = 0; /* fall through */
+
+ case GoToIdx:
+ /* library go */
+ startcatalog(NULL, LIBRARY + libnum, NULL);
+ break;
+ case OverrideIdx:
+ flags |= LIBOVERRIDE;
+ return TCL_OK; /* no tag callback */
+ break;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* "bindkey" command --- this is a direct implementation of the same */
+/* key binding found in the "ad-hoc" and Python interfaces; it is */
+/* preferable to make use of the Tk "bind" command directly, and work */
+/* from the event handler. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_bind(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tk_Window window = (Tk_Window)NULL;
+ XCWindowDataPtr searchwin;
+ char *keyname, *commandname, *binding;
+ int keywstate, func = -1, value = -1;
+ int result;
+ Boolean compat = FALSE;
+
+ if (objc == 2) {
+ keyname = Tcl_GetString(objv[1]);
+ if (!strcmp(keyname, "override")) {
+ flags |= KEYOVERRIDE;
+ return TCL_OK; /* no tag callback */
+ }
+ }
+
+ if (!(flags & KEYOVERRIDE)) {
+ default_keybindings();
+ flags |= KEYOVERRIDE;
+ }
+
+ if (objc == 1) {
+ Tcl_Obj *list;
+ int i;
+
+ list = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < NUM_FUNCTIONS; i++) {
+ commandname = func_to_string(i);
+ Tcl_ListObjAppendElement(interp, list,
+ Tcl_NewStringObj(commandname, strlen(commandname)));
+ }
+ Tcl_SetObjResult(interp, list);
+ return TCL_OK;
+ }
+ else if (objc > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "[<key> [<window>] [<command> [<value>|forget]]]");
+ return TCL_ERROR;
+ }
+
+ /* If 1st argument matches a window name, create a window-specific */
+ /* binding. Otherwise, create a binding for all windows. */
+
+ if (objc > 1) {
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), Tk_MainWindow(interp));
+ if (window == (Tk_Window)NULL)
+ Tcl_ResetResult(interp);
+ else {
+ for (searchwin = xobjs.windowlist; searchwin != NULL; searchwin =
+ searchwin->next)
+ if (searchwin->area == window)
+ break;
+ if (searchwin != NULL) {
+ /* Shift arguments */
+ objc--;
+ objv++;
+ }
+ else
+ window = (xcWidget)NULL;
+ }
+ }
+
+ /* 1st argument can be option "-compatible" */
+ if ((objc > 1) && !strncmp(Tcl_GetString(objv[1]), "-comp", 5)) {
+ objc--;
+ objv++;
+ compat = TRUE;
+ }
+
+ keyname = Tcl_GetString(objv[1]);
+ keywstate = string_to_key(keyname);
+
+ /* 1st arg may be a function, not a key, if we want the binding returned */
+ if ((objc == 3) && !strncmp(keyname, "-func", 5)) {
+ keywstate = -1;
+ func = string_to_func(Tcl_GetString(objv[2]), NULL);
+ objc = 2;
+ if (func == -1) {
+ Tcl_SetResult(interp, "Invalid function name\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else if ((objc == 2) && (keywstate == 0)) {
+ keywstate = -1;
+ func = string_to_func(keyname, NULL);
+ }
+
+ if ((keywstate == -1 || keywstate == 0) && func == -1) {
+ Tcl_SetResult(interp, "Invalid key name ", NULL);
+ Tcl_AppendElement(interp, keyname);
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ if (keywstate == -1)
+ binding = function_binding_to_string(window, func);
+ else if (compat)
+ binding = compat_key_to_string(window, keywstate);
+ else
+ binding = key_binding_to_string(window, keywstate);
+ Tcl_SetResult(interp, binding, TCL_VOLATILE);
+ free(binding);
+ return TCL_OK;
+ }
+
+ if (objc < 3) {
+ Tcl_SetResult(interp, "Usage: bindkey <key> [<function>]\n", NULL);
+ return TCL_ERROR;
+ }
+
+ commandname = Tcl_GetString(objv[2]);
+ if (strlen(commandname) == 0)
+ func = -1;
+ else
+ func = string_to_func(commandname, NULL);
+
+ if (objc == 4) {
+ result = Tcl_GetIntFromObj(interp, objv[3], &value);
+ if (result != TCL_OK)
+ {
+ if (strcmp(Tcl_GetString(objv[3]), "forget"))
+ return (result);
+ else {
+ /* Unbind command */
+ Tcl_ResetResult(interp);
+ result = remove_binding(window, keywstate, func);
+ if (result == 0)
+ return TCL_OK;
+ else {
+ Tcl_SetResult(interp, "Key/Function pair not found "
+ "in binding list.\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ result = add_vbinding(window, keywstate, func, value);
+ if (result == 1) {
+ Tcl_SetResult(interp, "Key is already bound to a command.\n", NULL);
+ return (result);
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_font(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ char *fontname;
+ int result;
+
+ /* font name */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "fontname");
+ return TCL_ERROR;
+ }
+ fontname = Tcl_GetString(objv[1]);
+
+ /* Allow overrides of the default font loading mechanism */
+ if (!strcmp(fontname, "override")) {
+ flags |= FONTOVERRIDE;
+ return TCL_OK;
+ }
+
+ /* If we need to load the default font "Helvetica" because no fonts */
+ /* have been loaded yet, then we call this function twice, so that */
+ /* the command tag callback gets applied both times. */
+
+ if (!(flags & FONTOVERRIDE)) {
+ flags |= FONTOVERRIDE;
+ xctcl_font(clientData, interp, objc, objv);
+ loadfontfile("Helvetica");
+ }
+ result = loadfontfile((char *)fontname);
+ if (result >= 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(fonts[fontcount - 1].family,
+ strlen(fonts[fontcount - 1].family)));
+ }
+ switch (result) {
+ case 1:
+ return XcTagCallback(interp, objc, objv);
+ case 0:
+ return TCL_OK;
+ case -1:
+ return TCL_ERROR;
+ }
+ return TCL_ERROR; /* (jdk) */
+}
+
+/*----------------------------------------------------------------------*/
+/* Set the X11 cursor to one of those defined in the XCircuit cursor */
+/* set (cursors.h) */
+/*----------------------------------------------------------------------*/
+
+int xctcl_cursor(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, result;
+
+ static char *cursNames[] = {
+ "arrow", "cross", "scissors", "copy", "rotate", "edit",
+ "text", "circle", "question", "wait", "hand", NULL
+ };
+
+ if (!areawin) return TCL_ERROR;
+
+ /* cursor name */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cursor name");
+ return TCL_ERROR;
+ }
+ if ((result = Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)cursNames,
+ "cursor name", 0, &idx)) != TCL_OK)
+ return result;
+
+ XDefineCursor(dpy, areawin->window, appcursors[idx]);
+ areawin->defaultcursor = &appcursors[idx];
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+
+int xctcl_filerecover(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
+ return TCL_ERROR;
+ }
+ crashrecover();
+ return XcTagCallback(interp, objc, objv);
+}
+
+/*----------------------------------------------------------------------*/
+/* Replace the functions of the simple rcfile.c interpreter. */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Execute a single command from a script or from the command line */
+/*----------------------------------------------------------------------*/
+
+short execcommand(short pflags, char *cmdptr)
+{
+ flags = pflags;
+ Tcl_Eval(xcinterp, cmdptr);
+ refresh(NULL, NULL, NULL);
+ return flags;
+}
+
+/*----------------------------------------------------------------------*/
+/* Load the default script (like execscript() but don't allow recursive */
+/* loading of the startup script) */
+/*----------------------------------------------------------------------*/
+
+void defaultscript()
+{
+ FILE *fd;
+ char *tmp_s = getenv((const char *)"XCIRCUIT_SRC_DIR");
+
+ flags = LIBOVERRIDE | LIBLOADED | FONTOVERRIDE;
+
+ if (!tmp_s) tmp_s = SCRIPTS_DIR;
+ sprintf(_STR2, "%s/%s", tmp_s, STARTUP_FILE);
+
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ sprintf(_STR2, "%s/%s", SCRIPTS_DIR, STARTUP_FILE);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ sprintf(_STR2, "%s/tcl/%s", SCRIPTS_DIR, STARTUP_FILE);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ Wprintf("Failed to open startup script \"%s\"\n", STARTUP_FILE);
+ return;
+ }
+ }
+ }
+ fclose(fd);
+ Tcl_EvalFile(xcinterp, _STR2);
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute a script */
+/*----------------------------------------------------------------------*/
+
+void execscript()
+{
+ FILE *fd;
+
+ flags = 0;
+
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) != NULL) {
+ fclose(fd);
+ Tcl_EvalFile(xcinterp, _STR2);
+ refresh(NULL, NULL, NULL);
+ }
+ else {
+ Wprintf("Failed to open script file \"%s\"\n", _STR2);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Evaluate an expression from a parameter and return the result as a */
+/* Tcl object. The actual return value (TCL_OK, TCL_ERROR) is stored */
+/* in pointer "eval_status", if it is non-NULL. */
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *evaluate_raw(objectptr thisobj, oparamptr ops, objinstptr pinst,
+ int *eval_status)
+{
+ Tcl_SavedResult state;
+ Tcl_Obj *robj;
+ int status;
+ char *exprptr, *pptr, *pkey, *pnext;
+
+ /* Sanity check */
+ if (ops->type != XC_EXPR) return NULL;
+ exprptr = ops->parameter.expr;
+ pnext = exprptr;
+ if (pnext == NULL) return NULL;
+
+ /* Check for "@<parameter>" notation and substitute parameter values */
+ while ((pptr = strchr(pnext, '@')) != NULL)
+ {
+ oparam temps;
+ oparamptr ips;
+ char psave, *promoted, *newexpr;
+
+ pptr++;
+ for (pkey = pptr; *pkey && !isspace(*pkey); pkey++)
+ if (*pkey == '{' || *pkey == '}' || *pkey == '[' || *pkey == ']' ||
+ *pkey == '(' || *pkey == ')' || *pkey == ',')
+ break;
+
+ if (pkey > pptr) {
+ psave = *pkey;
+ *pkey = '\0';
+ if (pinst)
+ ips = find_param(pinst, pptr);
+ else
+ ips = match_param(thisobj, pptr);
+ if (ips == ops) {
+ /* Avoid infinite recursion by treating a reference */
+ /* to oneself as plain text. */
+ ips = NULL;
+ }
+ if ((ips == NULL) && !strncmp(pptr, "p_", 2)) {
+ ips = &temps;
+ if (!strcmp(pptr + 2, "rotation")) {
+ temps.type = XC_INT;
+ temps.parameter.ivalue = pinst ? pinst->rotation : 0;
+ }
+ else if (!strcmp(pptr + 2, "xposition")) {
+ temps.type = XC_INT;
+ temps.parameter.ivalue = pinst ? pinst->position.x : 0;
+ }
+ else if (!strcmp(pptr + 2, "yposition")) {
+ temps.type = XC_INT;
+ temps.parameter.ivalue = pinst ? pinst->position.y : 0;
+ }
+ else if (!strcmp(pptr + 2, "scale")) {
+ temps.type = XC_FLOAT;
+ temps.parameter.fvalue = pinst ? pinst->scale : 1.0;
+ }
+ else if (!strcmp(pptr + 2, "color")) {
+ temps.type = XC_INT;
+ temps.parameter.ivalue = pinst ? pinst->color : DEFAULTCOLOR;
+ }
+ else if (!strcmp(pptr + 2, "top_xposition")) {
+ temps.type = XC_INT;
+ UTopDrawingOffset(&temps.parameter.ivalue, NULL);
+ }
+ else if (!strcmp(pptr + 2, "top_yposition")) {
+ temps.type = XC_INT;
+ UTopDrawingOffset(NULL, &temps.parameter.ivalue);
+ }
+ else if (!strcmp(pptr + 2, "top_rotation")) {
+ temps.type = XC_INT;
+ temps.parameter.ivalue = UTopRotation();
+ }
+ else if (!strcmp(pptr + 2, "top_scale")) {
+ temps.type = XC_FLOAT;
+ temps.parameter.fvalue = UTopDrawingScale();
+ }
+ else
+ ips = NULL;
+ }
+ *pkey = psave;
+ if (ips != NULL) {
+ switch (ips->type) {
+ case XC_INT:
+ promoted = malloc(12);
+ snprintf(promoted, 12, "%d", ips->parameter.ivalue);
+ break;
+ case XC_FLOAT:
+ promoted = malloc(12);
+ snprintf(promoted, 12, "%g", ips->parameter.fvalue);
+ break;
+ case XC_STRING:
+ promoted = textprint(ips->parameter.string, pinst);
+ break;
+ case XC_EXPR:
+ /* We really ought to prevent infinite loops here. . .*/
+ promoted = evaluate_expr(thisobj, ips, pinst);
+ break;
+ }
+ if (promoted == NULL) break;
+ newexpr = (char *)malloc(1 + strlen(exprptr) +
+ (max(strlen(promoted), strlen(pkey))));
+ *(pptr - 1) = '\0';
+ strcpy(newexpr, exprptr);
+ *(pptr - 1) = '@';
+ strcat(newexpr, promoted);
+ pnext = newexpr + strlen(newexpr); /* For next search of '@' escape */
+ strcat(newexpr, pkey);
+ free(promoted);
+ if (exprptr != ops->parameter.expr) free(exprptr);
+ exprptr = newexpr;
+ }
+ else {
+ /* Ignore the keyword and move to the end */
+ pnext = pkey;
+ }
+ }
+ }
+
+ /* Evaluate the expression in TCL */
+
+ Tcl_SaveResult(xcinterp, &state);
+ status = Tcl_Eval(xcinterp, exprptr);
+ robj = Tcl_GetObjResult(xcinterp);
+ Tcl_IncrRefCount(robj);
+ Tcl_RestoreResult(xcinterp, &state);
+ if (eval_status) *eval_status = status;
+ if (exprptr != ops->parameter.expr) free(exprptr);
+ return robj;
+}
+
+/*----------------------------------------------------------------------*/
+/* Evaluate an expression from a parameter and return the result as an */
+/* allocated string. */
+/*----------------------------------------------------------------------*/
+
+char *evaluate_expr(objectptr thisobj, oparamptr ops, objinstptr pinst)
+{
+ Tcl_Obj *robj;
+ char *rexpr = NULL;
+ int status, ip = 0;
+ float fp = 0.0;
+ stringpart *tmpptr, *promote = NULL;
+ oparamptr ips = (pinst == NULL) ? NULL : match_instance_param(pinst, ops->key);
+
+ robj = evaluate_raw(thisobj, ops, pinst, &status);
+ if (robj != NULL) {
+ rexpr = strdup(Tcl_GetString(robj));
+ Tcl_DecrRefCount(robj);
+ }
+
+ if ((status == TCL_ERROR) && (ips != NULL)) {
+ switch(ips->type) {
+ case XC_STRING:
+ rexpr = textprint(ips->parameter.string, pinst);
+ break;
+ case XC_FLOAT:
+ fp = ips->parameter.fvalue;
+ break;
+ }
+ }
+
+ /* If an instance redefines an expression, don't preserve */
+ /* the result. It is necessary in this case that the */
+ /* expression does not reference objects during redisplay, */
+ /* or else the correct result will not be written to the */
+ /* output. */
+
+ if ((ips != NULL) && (ips->type == XC_EXPR))
+ return rexpr;
+
+ /* Preserve the result in the object instance; this will be */
+ /* used when writing the output or when the result cannot */
+ /* be evaluated (see above). */
+
+ if ((rexpr != NULL) && (status == TCL_OK) && (pinst != NULL)) {
+ switch (ops->which) {
+ case P_SUBSTRING: case P_EXPRESSION:
+ if (ips == NULL) {
+ ips = make_new_parameter(ops->key);
+ ips->which = ops->which;
+ ips->type = XC_STRING;
+ ips->next = pinst->params;
+ pinst->params = ips;
+ }
+ else {
+ free(ips->parameter.string);
+ }
+ /* Promote the expression result to an XCircuit string type */
+ tmpptr = makesegment(&promote, NULL);
+ tmpptr->type = TEXT_STRING;
+ tmpptr = makesegment(&promote, NULL);
+ tmpptr->type = PARAM_END;
+ promote->data.string = strdup(rexpr);
+ ips->parameter.string = promote;
+ break;
+
+ case P_COLOR: /* must be integer, exact to 32 bits */
+ if (ips == NULL) {
+ ips = make_new_parameter(ops->key);
+ ips->which = ops->which;
+ ips->next = pinst->params;
+ pinst->params = ips;
+ }
+ /* Promote the expression result to type float */
+ if (rexpr != NULL) {
+ if (sscanf(rexpr, "%i", &ip) == 1)
+ ips->parameter.ivalue = ip;
+ else
+ ips->parameter.ivalue = 0;
+ }
+ else
+ ips->parameter.ivalue = ip;
+ ips->type = XC_INT;
+ break;
+
+ default: /* all others convert to type float */
+ if (ips == NULL) {
+ ips = make_new_parameter(ops->key);
+ ips->which = ops->which;
+ ips->next = pinst->params;
+ pinst->params = ips;
+ }
+ /* Promote the expression result to type float */
+ if (rexpr != NULL) {
+ if (sscanf(rexpr, "%g", &fp) == 1)
+ ips->parameter.fvalue = fp;
+ else
+ ips->parameter.fvalue = 0.0;
+ }
+ else
+ ips->parameter.fvalue = fp;
+ ips->type = XC_FLOAT;
+ break;
+ }
+ }
+ return rexpr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Execute the .xcircuitrc startup script */
+/*----------------------------------------------------------------------*/
+
+void loadrcfile()
+{
+ char *userdir = getenv((const char *)"HOME");
+ FILE *fd;
+ short i;
+
+ /* Initialize flags */
+
+ flags = 0;
+
+ /* Try first in current directory, then look in user's home directory */
+ /* First try looking for a file .xcircuitrc followed by a dash and */
+ /* the program version; this allows backward compatibility of the rc */
+ /* file in cases where a new version (e.g., 3 vs. 2) introduces */
+ /* incompatible syntax. Thanks to Romano Giannetti for this */
+ /* suggestion plus provided code. */
+
+ /* (names USER_RC_FILE and PROG_VERSION imported from Makefile) */
+
+ sprintf(_STR2, "%s-%g", USER_RC_FILE, PROG_VERSION);
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ /* Not found; check for the same in $HOME directory */
+ if (userdir != NULL) {
+ sprintf(_STR2, "%s/%s-%g", userdir, USER_RC_FILE, PROG_VERSION);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ /* Not found again; check for rc file w/o version # in CWD */
+ sprintf(_STR2, "%s", USER_RC_FILE);
+ xc_tilde_expand(_STR2, 249);
+ if ((fd = fopen(_STR2, "r")) == NULL) {
+ /* last try: plain USER_RC_FILE in $HOME */
+ sprintf(_STR2, "%s/%s", userdir, USER_RC_FILE);
+ fd = fopen(_STR2, "r");
+ }
+ }
+ }
+ }
+ if (fd != NULL) {
+ fclose(fd);
+ Tcl_EvalFile(xcinterp, _STR2);
+ }
+
+
+ /* Add the default font if not loaded already */
+
+ if (!(flags & FONTOVERRIDE)) {
+ loadfontfile("Helvetica");
+ if (areawin->psfont == -1)
+ for (i = 0; i < fontcount; i++)
+ if (!strcmp(fonts[i].psname, "Helvetica")) {
+ areawin->psfont = i;
+ break;
+ }
+ }
+ if (areawin->psfont == -1) areawin->psfont = 0;
+
+ setdefaultfontmarks();
+
+ /* arrange the loaded libraries */
+
+ if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
+ defaultscript();
+ }
+
+ /* Add the default colors */
+
+ if (!(flags & COLOROVERRIDE)) {
+ addnewcolorentry(xc_alloccolor("Gray40"));
+ addnewcolorentry(xc_alloccolor("Gray60"));
+ addnewcolorentry(xc_alloccolor("Gray80"));
+ addnewcolorentry(xc_alloccolor("Gray90"));
+ addnewcolorentry(xc_alloccolor("Red"));
+ addnewcolorentry(xc_alloccolor("Blue"));
+ addnewcolorentry(xc_alloccolor("Green2"));
+ addnewcolorentry(xc_alloccolor("Yellow"));
+ addnewcolorentry(xc_alloccolor("Purple"));
+ addnewcolorentry(xc_alloccolor("SteelBlue2"));
+ addnewcolorentry(xc_alloccolor("Red3"));
+ addnewcolorentry(xc_alloccolor("Tan"));
+ addnewcolorentry(xc_alloccolor("Brown"));
+ addnewcolorentry(xc_alloccolor("#d20adc"));
+ }
+
+ /* These colors must be enabled whether or not colors are overridden, */
+ /* because they are needed by the schematic capture system. */
+
+ addnewcolorentry(xc_getlayoutcolor(LOCALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(GLOBALPINCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(INFOLABELCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(RATSNESTCOLOR));
+ addnewcolorentry(xc_getlayoutcolor(BBOXCOLOR));
+
+ if (!(flags & KEYOVERRIDE))
+ default_keybindings();
+}
+
+/*----------------------------------------------------------------------*/
+/* Alternative button handler for use with Tk "bind" */
+/*----------------------------------------------------------------------*/
+
+int xctcl_standardaction(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
+{
+ int idx, result, knum, kstate;
+ XKeyEvent kevent;
+ static char *updown[] = {"up", "down", NULL};
+
+ if ((objc != 3) && (objc != 4)) goto badargs;
+
+ if ((result = Tcl_GetIntFromObj(interp, objv[1], &knum)) != TCL_OK)
+ goto badargs;
+
+ if ((result = Tcl_GetIndexFromObj(interp, objv[2],
+ (CONST84 char **)updown, "direction", 0, &idx)) != TCL_OK)
+ goto badargs;
+
+ if (objc == 4) {
+ if ((result = Tcl_GetIntFromObj(interp, objv[3], &kstate)) != TCL_OK)
+ goto badargs;
+ }
+ else
+ kstate = 0;
+
+ make_new_event(&kevent);
+ kevent.state = kstate;
+ kevent.keycode = 0;
+
+ if (idx == 0)
+ kevent.type = KeyRelease;
+ else
+ kevent.type = KeyPress;
+
+ switch (knum) {
+ case 1:
+ kevent.state |= Button1Mask;
+ break;
+ case 2:
+ kevent.state |= Button2Mask;
+ break;
+ case 3:
+ kevent.state |= Button3Mask;
+ break;
+ case 4:
+ kevent.state |= Button4Mask;
+ break;
+ case 5:
+ kevent.state |= Button5Mask;
+ break;
+ default:
+ kevent.keycode = knum;
+ break;
+ }
+#ifdef _MSC_VER
+ if (kevent.state & Mod1Mask) {
+ kevent.state &= ~Mod1Mask;
+ }
+ if (kevent.state & (AnyModifier<<2)) {
+ kevent.state &= ~(AnyModifier<<2);
+ kevent.state |= Mod1Mask;
+ }
+#endif
+ keyhandler((xcWidget)NULL, (caddr_t)NULL, &kevent);
+ return TCL_OK;
+
+badargs:
+ Tcl_SetResult(interp, "Usage: standardaction <button_num> up|down [<keystate>]\n"
+ "or standardaction <keycode> up|down [<keystate>]\n", NULL);
+ return TCL_ERROR;
+}
+
+/*----------------------------------------------------------------------*/
+/* Action handler for use with Tk "bind" */
+/* This dispatches events based on specific named actions that xcircuit */
+/* knows about, rather than by named key. This bypasses xcircuit's */
+/* key bindings. */
+/*----------------------------------------------------------------------*/
+
+int xctcl_action(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
+{
+ short value = 0;
+ int function, result, ival;
+ XPoint newpos, wpoint;
+
+ if (objc >= 2 && objc <= 4) {
+ function = string_to_func(Tcl_GetString(objv[1]), &value);
+ if (objc >= 3) {
+ result = (short)Tcl_GetIntFromObj(interp, objv[2], &ival);
+ if (result == TCL_ERROR) return TCL_ERROR;
+ value = (short)ival;
+ }
+
+ newpos = UGetCursorPos();
+ user_to_window(newpos, &wpoint);
+
+ result = compatible_function(function);
+ if (result == -1)
+ Tcl_SetResult(interp, "Action not allowed\n", NULL);
+
+ result = functiondispatch(function, value, wpoint.x, wpoint.y);
+ if (result == -1)
+ Tcl_SetResult(interp, "Action not handled\n", NULL);
+ }
+ else {
+ Tcl_SetResult(interp, "Usage: action <action_name> [<value>]\n", NULL);
+ return TCL_ERROR;
+ }
+ return XcTagCallback(interp, objc, objv);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* Argument-converting wrappers from Tk callback to Xt callback format */
+/*----------------------------------------------------------------------*/
+
+void xctk_drawarea(ClientData clientData, XEvent *eventPtr)
+{
+ Tcl_ServiceAll();
+ drawarea(areawin->area, (caddr_t)clientData, (caddr_t)NULL);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_resizearea(ClientData clientData, XEvent *eventPtr)
+{
+ resizearea(areawin->area, (caddr_t)clientData, (caddr_t)NULL);
+ /* Callback to function "arrangetoolbar" */
+ Tcl_Eval(xcinterp, "catch {xcircuit::arrangetoolbar $XCOps(focus)}");
+}
+
+/*----------------------------------------------------------------------*/
+/* Because Tk doesn't filter MotionEvent events based on context, we */
+/* have to filter the context here. */
+/*----------------------------------------------------------------------*/
+
+void xctk_panhbar(ClientData clientData, XEvent *eventPtr)
+{
+ XMotionEvent *mevent = (XMotionEvent *)eventPtr;
+ u_int state = mevent->state;
+ if (state & (Button1Mask | Button2Mask))
+ panhbar(areawin->scrollbarh, (caddr_t)clientData, (XButtonEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_panvbar(ClientData clientData, XEvent *eventPtr)
+{
+ XMotionEvent *mevent = (XMotionEvent *)eventPtr;
+ u_int state = mevent->state;
+ if (state & (Button1Mask | Button2Mask))
+ panvbar(areawin->scrollbarv, (caddr_t)clientData, (XButtonEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_drawhbar(ClientData clientData, XEvent *eventPtr)
+{
+ drawhbar(areawin->scrollbarh, (caddr_t)clientData, (caddr_t)NULL);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_drawvbar(ClientData clientData, XEvent *eventPtr)
+{
+ drawvbar(areawin->scrollbarv, (caddr_t)clientData, (caddr_t)NULL);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_endhbar(ClientData clientData, XEvent *eventPtr)
+{
+ endhbar(areawin->scrollbarh, (caddr_t)clientData, (XButtonEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_endvbar(ClientData clientData, XEvent *eventPtr)
+{
+ endvbar(areawin->scrollbarv, (caddr_t)clientData, (XButtonEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_zoomview(ClientData clientData, XEvent *eventPtr)
+{
+ zoomview((xcWidget)NULL, (caddr_t)clientData, (caddr_t)NULL);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_swapschem(ClientData clientData, XEvent *eventPtr)
+{
+ swapschem((int)((pointertype)clientData), -1, NULL);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_drag(ClientData clientData, XEvent *eventPtr)
+{
+ XButtonEvent *b_event = (XButtonEvent *)eventPtr;
+
+ drag((int)b_event->x, (int)b_event->y);
+ flusharea();
+}
+
+/*----------------------------------------------------------------------*/
+/* This really should be set up so that the "okay" button command tcl */
+/* procedure does the job of lookdirectory(). */
+/*----------------------------------------------------------------------*/
+
+void xctk_fileselect(ClientData clientData, XEvent *eventPtr)
+{
+ XButtonEvent *beventPtr = (XButtonEvent *)eventPtr;
+ popupstruct *listp = (popupstruct *)clientData;
+ char curentry[150];
+
+ if (beventPtr->button == Button2) {
+ Tcl_Eval(xcinterp, ".filelist.textent.txt get");
+ sprintf(curentry, "%.149s", (char *)Tcl_GetStringResult(xcinterp));
+
+ if (strlen(curentry) > 0) {
+ if (lookdirectory(curentry, 149))
+ newfilelist(listp->filew, listp);
+ else
+ Tcl_Eval(xcinterp, ".filelist.bbar.okay invoke");
+ }
+ }
+ else if (beventPtr->button == Button4) { /* scroll wheel binding */
+ flstart--;
+ showlscroll(listp->scroll, NULL, NULL);
+ listfiles(listp->filew, listp, NULL);
+ }
+ else if (beventPtr->button == Button5) { /* scroll wheel binding */
+ flstart++;
+ showlscroll(listp->scroll, NULL, NULL);
+ listfiles(listp->filew, listp, NULL);
+ }
+ else
+ fileselect(listp->filew, listp, beventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_listfiles(ClientData clientData, XEvent *eventPtr)
+{
+ popupstruct *listp = (popupstruct *)clientData;
+ char *filter;
+
+ Tcl_Eval(xcinterp, ".filelist.listwin.win cget -data");
+ filter = (char *)Tcl_GetStringResult(xcinterp);
+
+ if (filter != NULL) {
+ if ((listp->filter == NULL) || (strcmp(filter, listp->filter))) {
+ if (listp->filter != NULL)
+ free(listp->filter);
+ listp->filter = strdup(filter);
+ newfilelist(listp->filew, listp);
+ }
+ else
+ listfiles(listp->filew, listp, NULL);
+ }
+ else {
+ if (listp->filter != NULL) {
+ free(listp->filter);
+ listp->filter = NULL;
+ }
+ listfiles(listp->filew, listp, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_startfiletrack(ClientData clientData, XEvent *eventPtr)
+{
+ startfiletrack((Tk_Window)clientData, NULL, (XCrossingEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_endfiletrack(ClientData clientData, XEvent *eventPtr)
+{
+ endfiletrack((Tk_Window)clientData, NULL, (XCrossingEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_dragfilebox(ClientData clientData, XEvent *eventPtr)
+{
+ dragfilebox((Tk_Window)clientData, NULL, (XMotionEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_draglscroll(ClientData clientData, XEvent *eventPtr)
+{
+ popupstruct *listp = (popupstruct *)clientData;
+ XMotionEvent *mevent = (XMotionEvent *)eventPtr;
+ u_int state = mevent->state;
+
+ if (state & (Button1Mask | Button2Mask))
+ draglscroll(listp->scroll, listp, (XButtonEvent *)eventPtr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void xctk_showlscroll(ClientData clientData, XEvent *eventPtr)
+{
+ showlscroll((Tk_Window)clientData, NULL, NULL);
+}
+
+/*----------------------------------------------------------------------*/
+/* Build or rebuild the database of colors, fonts, and other settings */
+/* from the Tk option settings. */
+/*----------------------------------------------------------------------*/
+
+void build_app_database(Tk_Window tkwind)
+{
+ Tk_Uid xcuid;
+
+ /*--------------------------*/
+ /* Build the color database */
+ /*--------------------------*/
+
+ if ((xcuid = Tk_GetOption(tkwind, "globalpincolor", "Color")) == NULL)
+ xcuid = "Orange2";
+ appdata.globalcolor = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "localpincolor", "Color")) == NULL)
+ xcuid = "Red";
+ appdata.localcolor = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "infolabelcolor", "Color")) == NULL)
+ xcuid = "SeaGreen";
+ appdata.infocolor = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "ratsnestcolor", "Color")) == NULL)
+ xcuid = "tan4";
+ appdata.ratsnestcolor = xc_alloccolor((char *)xcuid);
+
+ if ((xcuid = Tk_GetOption(tkwind, "bboxcolor", "Color")) == NULL)
+ xcuid = "greenyellow";
+ appdata.bboxpix = xc_alloccolor((char *)xcuid);
+
+ if ((xcuid = Tk_GetOption(tkwind, "clipcolor", "Color")) == NULL)
+ xcuid = "powderblue";
+ appdata.clipcolor = xc_alloccolor((char *)xcuid);
+
+ if ((xcuid = Tk_GetOption(tkwind, "paramcolor", "Color")) == NULL)
+ xcuid = "Plum3";
+ appdata.parampix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "auxiliarycolor", "Color")) == NULL)
+ xcuid = "Green3";
+ appdata.auxpix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "axescolor", "Color")) == NULL)
+ xcuid = "Antique White";
+ appdata.axespix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "filtercolor", "Color")) == NULL)
+ xcuid = "SteelBlue3";
+ appdata.filterpix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "selectcolor", "Color")) == NULL)
+ xcuid = "Gold3";
+ appdata.selectpix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "snapcolor", "Color")) == NULL)
+ xcuid = "Red";
+ appdata.snappix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "gridcolor", "Color")) == NULL)
+ xcuid = "Gray95";
+ appdata.gridpix = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "pagebackground", "Color")) == NULL)
+ xcuid = "White";
+ appdata.bg = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "pageforeground", "Color")) == NULL)
+ xcuid = "Black";
+ appdata.fg = xc_alloccolor((char *)xcuid);
+
+ if ((xcuid = Tk_GetOption(tkwind, "paramcolor2", "Color")) == NULL)
+ xcuid = "Plum3";
+ appdata.parampix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "auxiliarycolor2", "Color")) == NULL)
+ xcuid = "Green";
+ appdata.auxpix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "selectcolor2", "Color")) == NULL)
+ xcuid = "Gold";
+ appdata.selectpix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "filtercolor2", "Color")) == NULL)
+ xcuid = "SteelBlue1";
+ appdata.gridpix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "snapcolor2", "Color")) == NULL)
+ xcuid = "Red";
+ appdata.snappix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "axescolor2", "Color")) == NULL)
+ xcuid = "NavajoWhite4";
+ appdata.axespix2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "background2", "Color")) == NULL)
+ xcuid = "DarkSlateGray";
+ appdata.bg2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "foreground2", "Color")) == NULL)
+ xcuid = "White";
+ appdata.fg2 = xc_alloccolor((char *)xcuid);
+ if ((xcuid = Tk_GetOption(tkwind, "barcolor", "Color")) == NULL)
+ xcuid = "Tan";
+ appdata.barpix = xc_alloccolor((char *)xcuid);
+
+ /* These are GUI colors---unused by Tcl */
+ appdata.buttonpix = xc_alloccolor("Gray85");
+ appdata.buttonpix2 = xc_alloccolor("Gray50");
+
+ /* Get some default fonts (Should be using Tk calls here. . . ) */
+
+ if ((xcuid = Tk_GetOption(tkwind, "filelistfont", "Font")) == NULL)
+ xcuid = "-*-helvetica-medium-r-normal--14-*";
+ appdata.filefont = XLoadQueryFont(dpy, (char *)xcuid);
+
+ if (appdata.filefont == NULL)
+ {
+ appdata.filefont = XLoadQueryFont(dpy, "-*-*-medium-r-normal--14-*");
+ if (appdata.filefont == NULL)
+ appdata.filefont = XLoadQueryFont(dpy, "-*-*-*-*-*--*-*");
+ }
+
+ /* Other defaults */
+
+ if ((xcuid = Tk_GetOption(tkwind, "timeout", "TimeOut")) == NULL)
+ xcuid = "10";
+ appdata.timeout = atoi((char *)xcuid);
+}
+
+/*--------------------------------------------------------------*/
+/* GUI Initialization under Tk */
+/* First argument is the Tk path name of the drawing window. */
+/* This function should be called for each new window created. */
+/*--------------------------------------------------------------*/
+
+XCWindowData *GUI_init(int objc, Tcl_Obj *CONST objv[])
+{
+ Tk_Window tkwind, tktop, tkdraw, tksb;
+ Tk_Window wsymb, wschema, corner;
+ int i, locobjc;
+ XGCValues values;
+ Window win;
+ popupstruct *fileliststruct;
+ char *xctopwin, *xcdrawwin;
+ char winpath[512];
+ XCWindowData *newwin;
+
+#ifdef OPENGL
+ int attributeList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
+ GLfloat params[2];
+ GLenum errnum;
+ int n;
+#endif
+
+ tktop = Tk_MainWindow(xcinterp);
+ if (tktop == (Tk_Window)NULL) {
+ Fprintf(stderr, "No Top-Level Tk window available. . .\n");
+ return NULL;
+ }
+
+ /* Check if any parameter is a Tk window name */
+
+ locobjc = objc;
+ while (locobjc > 0) {
+ xctopwin = Tcl_GetString(objv[locobjc - 1]);
+ tkwind = Tk_NameToWindow(xcinterp, xctopwin, tktop);
+ if (tkwind != (Tk_Window)NULL)
+ break;
+ locobjc--;
+ }
+
+ if (locobjc == 0) {
+ /* Okay to have no GUI wrapper. However, if this is the case, */
+ /* then the variable "XCOps(window)" must be set to the Tk path */
+ /* name of the drawing window. */
+
+ xcdrawwin = (char *)Tcl_GetVar2(xcinterp, "XCOps", "window", 0);
+ if (xcdrawwin == NULL) {
+ Fprintf(stderr, "The Tk window hierarchy must be rooted at"
+ " .xcircuit, or XCOps(top)");
+ Fprintf(stderr, " must point to the hierarchy. If XCOps(top)"
+ " is NULL, then XCOps(window) must");
+ Fprintf(stderr, " point to the drawing window.\n");
+ return NULL;
+ }
+ tkwind = Tk_NameToWindow(xcinterp, xcdrawwin, tktop);
+ if (tkwind == NULL) {
+ Fprintf(stderr, "Error: XCOps(window) is set but does not point to"
+ " a valid Tk window.\n");
+ return NULL;
+ }
+
+ /* Create new window data structure */
+ newwin = create_new_window();
+ newwin->area = tkwind;
+
+ /* No GUI---GUI widget pointers need to be NULL'd */
+ newwin->scrollbarv = NULL;
+ newwin->scrollbarh = NULL;
+ }
+ else {
+
+ /* Expect a top-level window name passed as the first argument. */
+ /* Having a fixed hierarchy is a total kludge and needs to be */
+ /* rewritten. . . */
+
+ if (tkwind == NULL) {
+ Fprintf(stderr, "Error: config init given a bad window name!\n");
+ return NULL;
+ }
+ else {
+ /* Make sure that this window does not already exist */
+ XCWindowDataPtr searchwin;
+ sprintf(winpath, "%s.mainframe.mainarea.drawing", xctopwin);
+ tkdraw = Tk_NameToWindow(xcinterp, winpath, tktop);
+ for (searchwin = xobjs.windowlist; searchwin != NULL; searchwin =
+ searchwin->next) {
+ if (searchwin->area == tkdraw) {
+ Fprintf(stderr, "Error: window already exists!\n");
+ return NULL;
+ }
+ }
+ }
+
+ /* Create new window data structure and */
+ /* fill in global variables from the Tk window values */
+
+ newwin = create_new_window();
+ sprintf(winpath, "%s.mainframe.mainarea.sbleft", xctopwin);
+ newwin->scrollbarv = Tk_NameToWindow(xcinterp, winpath, tktop);
+ sprintf(winpath, "%s.mainframe.mainarea.sbbottom", xctopwin);
+ newwin->scrollbarh = Tk_NameToWindow(xcinterp, winpath, tktop);
+ sprintf(winpath, "%s.mainframe.mainarea.drawing", xctopwin);
+ newwin->area = Tk_NameToWindow(xcinterp, winpath, tktop);
+
+ sprintf(winpath, "%s.mainframe.mainarea.corner", xctopwin);
+ corner = Tk_NameToWindow(xcinterp, winpath, tktop);
+
+ sprintf(winpath, "%s.infobar.symb", xctopwin);
+ wsymb = Tk_NameToWindow(xcinterp, winpath, tktop);
+
+ sprintf(winpath, "%s.infobar.schem", xctopwin);
+ wschema = Tk_NameToWindow(xcinterp, winpath, tktop);
+
+ Tk_CreateEventHandler(newwin->scrollbarh, ButtonMotionMask,
+ (Tk_EventProc *)xctk_panhbar, NULL);
+ Tk_CreateEventHandler(newwin->scrollbarv, ButtonMotionMask,
+ (Tk_EventProc *)xctk_panvbar, NULL);
+ Tk_CreateEventHandler(newwin->scrollbarh, StructureNotifyMask | ExposureMask,
+ (Tk_EventProc *)xctk_drawhbar, NULL);
+ Tk_CreateEventHandler(newwin->scrollbarv, StructureNotifyMask | ExposureMask,
+ (Tk_EventProc *)xctk_drawvbar, NULL);
+ Tk_CreateEventHandler(newwin->scrollbarh, ButtonReleaseMask,
+ (Tk_EventProc *)xctk_endhbar, NULL);
+ Tk_CreateEventHandler(newwin->scrollbarv, ButtonReleaseMask,
+ (Tk_EventProc *)xctk_endvbar, NULL);
+
+ Tk_CreateEventHandler(corner, ButtonPressMask,
+ (Tk_EventProc *)xctk_zoomview, Number(1));
+ Tk_CreateEventHandler(wsymb, ButtonPressMask,
+ (Tk_EventProc *)xctk_swapschem, Number(0));
+ Tk_CreateEventHandler(wschema, ButtonPressMask,
+ (Tk_EventProc *)xctk_swapschem, Number(0));
+ }
+
+ /* Setup event handlers for the drawing area and scrollbars */
+ /* There are purposely no callback functions for these windows---they are */
+ /* defined as type "simple" to keep down the cruft, as I will define my own */
+ /* event handlers. */
+
+ if (locobjc > 0) {
+ Tk_CreateEventHandler(newwin->area, StructureNotifyMask,
+ (Tk_EventProc *)xctk_resizearea, NULL);
+ Tk_CreateEventHandler(newwin->area, ExposureMask,
+ (Tk_EventProc *)xctk_drawarea, NULL);
+ }
+
+ /* Make sure the window is mapped */
+
+ Tk_MapWindow(tkwind);
+ win = Tk_WindowId(tkwind);
+
+ Tk_MapWindow(newwin->area);
+ newwin->window = Tk_WindowId(newwin->area);
+ newwin->width = Tk_Width(newwin->area);
+ newwin->height = Tk_Height(newwin->area);
+
+ /* Things to set once only */
+
+ if (dpy == NULL) {
+ dpy = Tk_Display(tkwind);
+ cmap = Tk_Colormap(tkwind);
+ // (The following may be required on some systems where
+ // Tk will not report a valid colormap after Tk_MapWindow())
+ // cmap = DefaultColormap(dpy, DefaultScreen(dpy));
+
+ /*-------------------------*/
+ /* Create stipple patterns */
+ /*-------------------------*/
+
+ for (i = 0; i < STIPPLES; i++)
+ STIPPLE[i] = XCreateBitmapFromData(dpy, win, STIPDATA[i], 4, 4);
+
+ /*----------------------------------------*/
+ /* Allocate space for the basic color map */
+ /*----------------------------------------*/
+
+ number_colors = 0;
+ colorlist = (colorindex *)malloc(sizeof(colorindex));
+ appcolors = (int *) malloc(NUMBER_OF_COLORS * sizeof(int));
+ areawin = newwin;
+ build_app_database(tkwind);
+ areawin = NULL;
+
+ /* Create the filelist window and its event handlers */
+
+ tksb = Tk_NameToWindow(xcinterp, ".filelist.listwin.sb", tktop);
+ tkdraw = Tk_NameToWindow(xcinterp, ".filelist.listwin.win", tktop);
+
+ fileliststruct = (popupstruct *) malloc(sizeof(popupstruct));
+ fileliststruct->popup = Tk_NameToWindow(xcinterp, ".filelist", tktop);
+ fileliststruct->textw = Tk_NameToWindow(xcinterp, ".filelist.textent",
+ fileliststruct->popup);
+ fileliststruct->filew = tkdraw;
+ fileliststruct->scroll = tksb;
+ fileliststruct->setvalue = NULL;
+ fileliststruct->filter = NULL;
+
+ if (tksb != NULL) {
+ Tk_CreateEventHandler(tksb, ButtonMotionMask,
+ (Tk_EventProc *)xctk_draglscroll, (ClientData)fileliststruct);
+ Tk_CreateEventHandler(tksb, ExposureMask,
+ (Tk_EventProc *)xctk_showlscroll, (ClientData)tksb);
+ }
+ if (tkdraw != NULL) {
+ Tk_CreateEventHandler(tkdraw, ButtonPressMask,
+ (Tk_EventProc *)xctk_fileselect, (ClientData)fileliststruct);
+ Tk_CreateEventHandler(tkdraw, ExposureMask,
+ (Tk_EventProc *)xctk_listfiles, (ClientData)fileliststruct);
+ Tk_CreateEventHandler(tkdraw, EnterWindowMask,
+ (Tk_EventProc *)xctk_startfiletrack, (ClientData)tkdraw);
+ Tk_CreateEventHandler(tkdraw, LeaveWindowMask,
+ (Tk_EventProc *)xctk_endfiletrack, (ClientData)tkdraw);
+ }
+
+ /* OpenGL setup */
+
+#ifdef OPENGL
+ grVisualInfo = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
+ grXcontext = glXCreateContext(dpy, grVisualInfo, NULL, GL_FALSE);
+
+ glLineWidth(1.0);
+ glShadeModel(GL_FLAT);
+ glPixelStorei(GL_PACK_LSB_FIRST, TRUE);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+
+ /* Check OpenGL line and point size limits. */
+ /* Note that one has to do glXMakeCurrent() for the values */
+ /* returned by glGet*() to be meaningful! */
+
+ glXMakeCurrent(dpy, (GLXDrawable)win, grXcontext);
+ params[0] = params[1] = 0.0;
+ glGetFloatv(GL_LINE_WIDTH_RANGE, (GLfloat *)params);
+ errnum = glGetError();
+ if (errnum != GL_NO_ERROR) Fprintf(stdout, "Error %d\n", errnum);
+ gl_line_limit = (float)params[1];
+ Fprintf(stdout, "line limits: %g and %g\n", (float)params[0], gl_line_limit);
+ /* glGetFloatv(GL_POINT_SIZE_RANGE, params); */
+ glGetFloatv(GL_POINT_SIZE_RANGE, (GLfloat *)params);
+ gl_point_limit = (float)params[1];
+ Fprintf(stdout, "point limits: %g and %g\n", (float)params[0], gl_point_limit);
+
+#endif /* OPENGL */
+ }
+
+ /*-------------------------------------------------------------------*/
+ /* Generate the GC */
+ /* Set "graphics_exposures" to False. Every XCopyArea function */
+ /* copies from virtual memory (dbuf pixmap), which can never be */
+ /* obscured. Otherwise, the server gets flooded with useless */
+ /* NoExpose events. */
+ /*-------------------------------------------------------------------*/
+
+ values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
+ values.background = WhitePixel(dpy, DefaultScreen(dpy));
+ values.graphics_exposures = False;
+ newwin->gc = XCreateGC(dpy, win, GCForeground | GCBackground
+ | GCGraphicsExposures, &values);
+
+ newwin->clipmask = XCreatePixmap(dpy, win, newwin->width,
+ newwin->height, 1);
+
+ values.foreground = 0;
+ values.background = 0;
+ newwin->cmgc = XCreateGC(dpy, newwin->clipmask, GCForeground
+ | GCBackground, &values);
+
+ XDefineCursor (dpy, win, *newwin->defaultcursor);
+ return newwin;
+}
+
+/*--------------------------------------*/
+/* Inline the main wrapper prodedure */
+/*--------------------------------------*/
+
+int xctcl_start(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ int result = TCL_OK;
+ Boolean rcoverride = False;
+ char *filearg = NULL;
+ Tcl_Obj *cmdname = objv[0];
+
+ Fprintf(stdout, "Starting xcircuit under Tcl interpreter\n");
+
+ /* xcircuit initialization routines --- these assume that the */
+ /* GUI has been created by the startup script; otherwise bad */
+ /* things will probably occur. */
+
+ pre_initialize();
+ areawin = GUI_init(--objc, ++objv);
+ if (areawin == NULL) {
+ Tcl_SetResult(interp, "Invalid or missing top-level windowname"
+ " given to start command.\n", NULL);
+ return TCL_ERROR;
+ }
+ post_initialize();
+
+#ifndef OPENGL
+ ghostinit();
+#endif
+
+ /* The Tcl version accepts some command-line arguments. Due */
+ /* to the way ".wishrc" is processed, all arguments are */
+ /* glommed into one Tcl (list) object, objv[1]. */
+
+ if (objc == 2) {
+ char **argv;
+ int argc;
+
+ Tcl_SplitList(interp, Tcl_GetString(objv[1]), &argc,
+ (CONST84 char ***)&argv);
+ while (argc) {
+ if (**argv == '-') {
+ if (!strncmp(*argv, "-exec", 5)) {
+ if (--argc > 0) {
+ argv++;
+ result = Tcl_EvalFile(interp, *argv);
+ if (result != TCL_OK)
+ return result;
+ else
+ rcoverride = True;
+ }
+ else {
+ Tcl_SetResult(interp, "No filename given to exec argument.", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else if (!strncmp(*argv, "-2", 2)) {
+ /* 2-button mouse bindings option */
+ pressmode = 1;
+ }
+ }
+ else filearg = *argv;
+ argv++;
+ argc--;
+ }
+ }
+ else {
+ /* Except---this appears to be no longer true. When did it change? */
+ int argc = objc;
+ char *argv;
+
+ for (argc = 0; argc < objc; argc++) {
+ argv = Tcl_GetString(objv[argc]);
+ if (*argv == '-') {
+ if (!strncmp(argv, "-exec", 5)) {
+ if (++argc < objc) {
+ argv = Tcl_GetString(objv[argc]);
+ result = Tcl_EvalFile(interp, argv);
+ if (result != TCL_OK)
+ return result;
+ else
+ rcoverride = True;
+ }
+ else {
+ Tcl_SetResult(interp, "No filename given to exec argument.", NULL);
+ return TCL_ERROR;
+ }
+ }
+ else if (!strncmp(argv, "-2", 2)) {
+ /* 2-button mouse bindings option */
+ pressmode = 1;
+ }
+ }
+ else filearg = argv;
+ }
+ }
+
+ if (!rcoverride) loadrcfile();
+
+ composelib(PAGELIB); /* make sure we have a valid page list */
+ composelib(LIBLIB); /* and library directory */
+ if ((objc >= 2) && (filearg != NULL)) {
+ char *libname;
+ int target = -1;
+
+ strcpy(_STR2, filearg);
+ libname = (char *)Tcl_GetVar2(xcinterp, "XCOps", "library", 0);
+ if (libname != NULL) {
+ target = NameToLibrary(libname);
+ }
+ startloadfile((target >= 0) ? target + LIBRARY : -1);
+ }
+ else {
+ findcrashfiles();
+ }
+ pressmode = 0; /* Done using this to track 2-button bindings */
+
+ /* Note that because the setup has the windows generated and */
+ /* mapped prior to calling the xcircuit routines, nothing */
+ /* gets CreateNotify, MapNotify, or other definitive events. */
+ /* So, we have to do all the drawing once. */
+
+ xobjs.suspend = -1; /* Release from suspend mode */
+ if (areawin->scrollbarv)
+ drawvbar(areawin->scrollbarv, NULL, NULL);
+ if (areawin->scrollbarh)
+ drawhbar(areawin->scrollbarh, NULL, NULL);
+ drawarea(areawin->area, NULL, NULL);
+
+ /* Return back to the interpreter; Tk is handling the GUI */
+ return XcTagCallback(interp, 1, &cmdname);
+}
+
+/*--------------------------------------------------------------*/
+/* Message printing procedures for the Tcl version */
+/* */
+/* Evaluate the variable-length argument, and make a call to */
+/* the routine xcircuit::print, which should be defined. */
+/*--------------------------------------------------------------*/
+
+void W0vprintf(char *window, const char *format, va_list args_in)
+{
+ char tstr[128], *bigstr = NULL, *strptr;
+ int n, size;
+ va_list args;
+
+ if (window != NULL) {
+ sprintf(tstr, "catch {xcircuit::print %s {", window);
+ size = strlen(tstr);
+
+ va_copy(args, args_in);
+ n = vsnprintf(tstr + size, 128 - size, format, args);
+ va_end(args);
+
+ if (n <= -1 || n > 125 - size) {
+ bigstr = malloc(n + size + 4);
+ strncpy(bigstr, tstr, size);
+ va_copy(args, args_in);
+ vsnprintf(bigstr + size, n + 1, format, args);
+ va_end(args);
+ strptr = bigstr;
+ strcat(bigstr, "}}");
+ }
+ else {
+ strptr = tstr;
+ strcat(tstr, "}}");
+ }
+ Tcl_Eval(xcinterp, strptr);
+ if (bigstr != NULL) free(bigstr);
+ }
+}
+
+/* Prints to pagename window */
+
+void W1printf(char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ W0vprintf("coord", format, args);
+ va_end(args);
+}
+
+/* Prints to coordinate window */
+
+void W2printf(char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ W0vprintf("page", format, args);
+ va_end(args);
+}
+
+/* Prints to status window but does not tee output to the console. */
+
+void W3printf(char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ W0vprintf("stat", format, args);
+ va_end(args);
+}
+
+/* Prints to status window and duplicates the output to stdout. */
+
+void Wprintf(char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ W0vprintf("stat", format, args);
+ if (strlen(format) > 0) {
+ if (strstr(format, "Error")) {
+ tcl_vprintf(stderr, format, args);
+ tcl_printf(stderr, "\n");
+ }
+ else {
+ tcl_vprintf(stdout, format, args);
+ tcl_printf(stdout, "\n");
+ }
+ }
+ va_end(args);
+}
+
+/*------------------------------------------------------*/
+
+#endif /* defined(TCL_WRAPPER) && !defined(HAVE_PYTHON) */
diff --git a/text.c b/text.c
new file mode 100644
index 0000000..078a92e
--- /dev/null
+++ b/text.c
@@ -0,0 +1,2286 @@
+/*-----------------------------------------------------------------------*/
+/* text.c --- text processing routines for xcircuit */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*-----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h> /* for isprint() and isdigit() */
+
+#ifndef _MSC_VER
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+/*------------------------------------------------------------------------*/
+/* Local includes */
+/*------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*------------------------------------------------------------------------*/
+/* External Variable definitions */
+/*------------------------------------------------------------------------*/
+
+extern Display *dpy;
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern short fontcount;
+extern fontinfo *fonts;
+extern int *appcolors;
+extern colorindex *colorlist;
+extern char _STR[150];
+
+/* Global value of distance between characters in the font catalog */
+short del;
+
+#ifndef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Evaluation of expression types in strings (non-Tcl version---these */
+/* are PostScript expressions). */
+/* */
+/* For now, expressions are just copied as-is, without evaluation. */
+/* An allocated string is returned, and it is the responsibility of the */
+/* calling routine to free it. */
+/*----------------------------------------------------------------------*/
+
+char *evaluate_expr(objectptr thisobj, oparamptr ops, objinstptr pinst)
+{
+ if (ops->type != XC_EXPR) return NULL;
+ return strdup(ops->parameter.expr);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Determine if a label contains a parameter. */
+/*----------------------------------------------------------------------*/
+
+Boolean hasparameter(labelptr curlabel)
+{
+ stringpart *chrptr;
+
+ for (chrptr = curlabel->string; chrptr != NULL; chrptr = chrptr->nextpart)
+ if (chrptr->type == PARAM_START)
+ return True;
+
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Join selected labels together. */
+/*----------------------------------------------------------------------*/
+
+void joinlabels()
+{
+ /* genericptr *genobj; (jdk) */
+ short *jl;
+ stringpart *endpart;
+ /* int tpos; (jdk) */
+ labelptr dest, source;
+
+ if (areawin->selects < 2) {
+ Wprintf("Not enough labels selected for joining");
+ return;
+ }
+
+ XcSetFunction(GXcopy);
+ XSetForeground(dpy, areawin->gc, BACKGROUND);
+
+ for (jl = areawin->selectlist; jl < areawin->selectlist +
+ areawin->selects; jl++) {
+ if (SELECTTYPE(jl) == LABEL) {
+ dest = SELTOLABEL(jl);
+ UDrawString(dest, DOFORALL, areawin->topinstance);
+ for (endpart = dest->string; endpart->nextpart != NULL; endpart =
+ endpart->nextpart);
+ break;
+ }
+ }
+
+ for (++jl; jl < areawin->selectlist + areawin->selects; jl++) {
+ if (SELECTTYPE(jl) == LABEL) {
+ source = SELTOLABEL(jl);
+ UDrawString(source, DOFORALL, areawin->topinstance);
+ endpart->nextpart = source->string;
+ for (; endpart->nextpart != NULL; endpart = endpart->nextpart);
+ free(source);
+ removep(jl, 0);
+ reviseselect(areawin->selectlist, areawin->selects, jl);
+ }
+ }
+
+ XSetForeground(dpy, areawin->gc, dest->color);
+ UDrawString(dest, dest->color, areawin->topinstance);
+
+ incr_changes(topobject);
+ clearselects();
+}
+
+/*----------------------------------------------------------------------*/
+/* Insert a new segment into a string */
+/*----------------------------------------------------------------------*/
+
+stringpart *makesegment(stringpart **strhead, stringpart *before)
+{
+ stringpart *newptr, *lastptr, *nextptr;
+
+ newptr = (stringpart *)malloc(sizeof(stringpart));
+ newptr->data.string = NULL;
+
+ if (before == *strhead) { /* insert at beginning */
+ newptr->nextpart = *strhead;
+ *strhead = newptr;
+ }
+ else { /* otherwise */
+ for(lastptr = *strhead; lastptr != NULL;) {
+ nextptr = nextstringpart(lastptr, areawin->topinstance);
+ if (nextptr == before) {
+ if (lastptr->type == PARAM_START) {
+ oparamptr obs = NULL;
+ char *key = lastptr->data.string;
+ obs = find_param(areawin->topinstance, key);
+ if (obs == NULL) {
+ Wprintf("Error: Bad parameter \"%s\"!", key);
+ } else {
+ obs->parameter.string = newptr; /* ?? */
+ }
+ }
+ else {
+ lastptr->nextpart = newptr;
+ }
+ newptr->nextpart = nextptr;
+ break;
+ }
+ else if (lastptr->nextpart == before && lastptr->type == PARAM_START) {
+ lastptr->nextpart = newptr;
+ newptr->nextpart = before;
+ break;
+ }
+ lastptr = nextptr;
+ }
+ }
+ return newptr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Split a string across text segments */
+/*----------------------------------------------------------------------*/
+
+stringpart *splitstring(int tpos, stringpart **strtop, objinstptr localinst)
+{
+ int locpos, slen;
+ stringpart *newpart, *ipart;
+
+ ipart = findstringpart(tpos, &locpos, *strtop, localinst);
+ if (locpos > 0) { /* split the string */
+ newpart = makesegment(strtop, ipart);
+ newpart->type = TEXT_STRING;
+ newpart->data.string = ipart->data.string;
+ slen = strlen(newpart->data.string) - locpos;
+ ipart->data.string = (u_char *)malloc(slen + 1);
+ strncpy(ipart->data.string, newpart->data.string + locpos, slen + 1);
+ *(newpart->data.string + locpos) = '\0';
+ }
+ else newpart = ipart;
+
+ return newpart;
+}
+
+/*----------------------------------------------------------------------*/
+/* Get the next string part, linking to a parameter if necessary */
+/*----------------------------------------------------------------------*/
+
+stringpart *nextstringpartrecompute(stringpart *strptr, objinstptr thisinst)
+{
+ stringpart *nextptr = strptr->nextpart;
+
+ if (strptr->type == PARAM_START)
+ nextptr = linkstring(thisinst, strptr, TRUE);
+ else if (strptr->type == PARAM_END) {
+ strptr->nextpart = NULL;
+
+ /* Parameters that have a non-NULL entry in data have */
+ /* been promoted from an expression or numerical value */
+ /* to a string. The memory allocated for this string */
+ /* should be free'd. */
+
+ if (strptr->data.string != (u_char *)NULL) {
+ fprintf(stderr, "Non-NULL data in PARAM_END segment\n");
+ free(strptr->data.string);
+ strptr->data.string = (u_char *)NULL;
+ }
+ }
+ return nextptr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Same as the above routine, but don't recompute expression parameters */
+/* when encountered. Use the previously generated result. */
+/*----------------------------------------------------------------------*/
+
+stringpart *nextstringpart(stringpart *strptr, objinstptr thisinst)
+{
+ stringpart *nextptr = strptr->nextpart;
+
+ if (strptr->type == PARAM_START)
+ nextptr = linkstring(thisinst, strptr, FALSE);
+ else if (strptr->type == PARAM_END) {
+ strptr->nextpart = NULL;
+ if (strptr->data.string != (u_char *)NULL) {
+ fprintf(stderr, "Non-NULL data in PARAM_END segment\n");
+ free(strptr->data.string);
+ strptr->data.string = (u_char *)NULL;
+ }
+ }
+ return nextptr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove a string part from the string */
+/*----------------------------------------------------------------------*/
+
+stringpart *deletestring0(stringpart *dstr, stringpart **strtop, objinstptr thisinst,
+ Boolean domerge)
+{
+ stringpart *strptr = NULL, *nextptr;
+ char *key;
+ oparamptr ops;
+
+ if (dstr == *strtop)
+ *strtop = dstr->nextpart;
+ else {
+ strptr = *strtop;
+ while (strptr != NULL) {
+ nextptr = nextstringpart(strptr, thisinst);
+ if (nextptr == dstr) break;
+ strptr = nextptr;
+ }
+ if (strptr == NULL)
+ return NULL;
+
+ /* If this is the begining of a parameter, then we have to figure */
+ /* out if it's an instance or a default, and change the pointer */
+ /* to the parameter in the parameter list, accordingly. */
+
+ else if ((strptr->type == PARAM_START) && (thisinst != NULL)) {
+ key = strptr->data.string;
+ ops = find_param(thisinst, key);
+ if (ops == NULL) {
+ Fprintf(stderr, "Error in deletestring: Bad parameter %s found\n", key);
+ }
+ else {
+ switch(ops->type) {
+ case XC_STRING:
+ ops->parameter.string = dstr->nextpart;
+ break;
+ default:
+ /* What to be done here? */
+ break;
+ }
+ }
+ }
+ /* If this is the end of a parameter, we have to link the */
+ /* PARAM_START, not the PARAM_END, which has already been nulled. */
+ else if (strptr->type == PARAM_END) {
+ for (strptr = *strtop; strptr != NULL; strptr = strptr->nextpart) {
+ if (strptr->nextpart == dstr) {
+ strptr->nextpart = dstr->nextpart;
+ break;
+ }
+ }
+ }
+ else
+ strptr->nextpart = dstr->nextpart;
+ }
+ if (dstr->type == TEXT_STRING)
+ free(dstr->data.string);
+ free(dstr);
+
+ /* attempt to merge, if legal, and requested */
+ if (strptr && domerge)
+ mergestring(strptr);
+
+ return strptr;
+}
+
+/*----------------------------------------------------------------------*/
+/* deletestring() is a wrapper for deletestring0() */
+/*----------------------------------------------------------------------*/
+
+stringpart *deletestring(stringpart *dstr, stringpart **strtop, objinstptr thisinst)
+{
+ return deletestring0(dstr, strtop, thisinst, TRUE);
+}
+
+/*----------------------------------------------------------------------*/
+/* Merge string parts at boundary, if parts can be legally merged */
+/* If the indicated string part is text and the part following the */
+/* indicated string part is also text, merge the two. The indicated */
+/* string part is returned, and the following part is freed. */
+/* */
+/* (Fixes thanks to Petter Larsson 11/17/03) */
+/*----------------------------------------------------------------------*/
+
+stringpart *mergestring(stringpart *firststr)
+{
+ stringpart *nextstr = NULL;
+
+ if (firststr) nextstr = firststr->nextpart;
+ if (nextstr != NULL) {
+ if (firststr->type == TEXT_STRING && nextstr->type == TEXT_STRING) {
+ firststr->nextpart = nextstr->nextpart;
+ firststr->data.string = (char *)realloc(firststr->data.string,
+ 1 + strlen(firststr->data.string) + strlen(nextstr->data.string));
+ strcat(firststr->data.string, nextstr->data.string);
+ free(nextstr->data.string);
+ free(nextstr);
+ }
+ }
+ return firststr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Link a parameter to a string */
+/* If compute_exprs is TRUE, then we should recompute any expression */
+/* parameters encountered. If FALSE, then we assume that all */
+/* expressions have been computed previously, and may use the recorded */
+/* instance value. */
+/* */
+/* 11/20/06---changed to allow two different static strings to save */
+/* promoted results. This is necessary because we may be comparing */
+/* two promoted results in, e.g., stringcomprelaxed(), and we don't */
+/* want to overwrite the first result with the second. */
+/*----------------------------------------------------------------------*/
+
+stringpart *linkstring(objinstptr localinst, stringpart *strstart,
+ Boolean compute_exprs)
+{
+ char *key;
+ stringpart *tmpptr, *nextptr = NULL;
+ static stringpart *promote[2] = {NULL, NULL};
+ static unsigned char pidx = 0;
+ oparamptr ops;
+
+ if (strstart->type != PARAM_START) return NULL;
+
+ key = strstart->data.string;
+
+ /* In case of no calling instance, always get the default from the */
+ /* current page object. */
+
+ if (localinst == NULL) {
+ ops = match_param(topobject, key);
+ if (ops == NULL)
+ return NULL;
+ }
+ else {
+ ops = find_param(localinst, key);
+ if (ops == NULL) {
+ /* We get here in cases where the object definition is being read, */
+ /* and there is no instance of the object to link to. In that */
+ /* case, we ignore parameters and move on to the next part. */
+ return strstart->nextpart;
+ }
+ }
+
+ if (ops->type != XC_STRING) {
+
+ if (promote[pidx] == NULL) {
+ /* Generate static string for promoting numerical parameters */
+ tmpptr = makesegment(&promote[pidx], NULL);
+ tmpptr->type = TEXT_STRING;
+ tmpptr = makesegment(&promote[pidx], NULL);
+ tmpptr->type = PARAM_END;
+ }
+ else {
+ if (promote[pidx]->data.string != NULL) {
+ free(promote[pidx]->data.string);
+ promote[pidx]->data.string = NULL;
+ }
+ }
+
+ /* Promote numerical type to string */
+ if (ops->type == XC_INT) {
+ promote[pidx]->data.string = (char *)malloc(13);
+ sprintf(promote[pidx]->data.string, "%12d", ops->parameter.ivalue);
+ nextptr = promote[pidx++];
+ }
+ else if (ops->type == XC_FLOAT) {
+ promote[pidx]->data.string = (char *)malloc(13);
+ sprintf(promote[pidx]->data.string, "%g", (double)(ops->parameter.fvalue));
+ nextptr = promote[pidx++];
+ }
+ else { /* ops->type == XC_EXPR */
+ oparamptr ips;
+ if (!compute_exprs && (ips = match_instance_param(localinst, key))
+ != NULL && (ips->type == XC_STRING)) {
+ nextptr = ips->parameter.string;
+ promote[pidx]->data.string = NULL;
+ }
+ else {
+ promote[pidx]->data.string = evaluate_expr(((localinst == NULL) ?
+ topobject : localinst->thisobject), ops, localinst);
+ if (promote[pidx]->data.string != NULL)
+ nextptr = promote[pidx++];
+ else
+ nextptr = NULL;
+ }
+ }
+ pidx &= 0x1; /* pidx toggles between 0 and 1 */
+ }
+ else
+ nextptr = ops->parameter.string;
+
+ /* If the parameter exists, link the end of the parameter back to */
+ /* the calling string. */
+
+ if (nextptr != NULL) {
+ tmpptr = nextptr;
+ while (tmpptr->type != PARAM_END)
+ if ((tmpptr = tmpptr->nextpart) == NULL)
+ return NULL;
+ tmpptr->nextpart = strstart->nextpart;
+ return nextptr;
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the last font used prior to the indicated text position */
+/*----------------------------------------------------------------------*/
+
+int findcurfont(int tpos, stringpart *strtop, objinstptr thisinst)
+{
+ stringpart *curpos;
+ int cfont = -1;
+ stringpart *strptr;
+
+ curpos = findstringpart(tpos, NULL, strtop, thisinst);
+ for (strptr = strtop; (strptr != NULL) && (strptr != curpos);
+ strptr = nextstringpart(strptr, thisinst))
+ if (strptr->type == FONT_NAME)
+ cfont = strptr->data.font;
+
+ return cfont;
+}
+
+/*----------------------------------------------------------------------*/
+/* Return a local position and stringpart for the first occurrence of */
+/* "substring" in the the indicated xcircuit string. If non-NULL, */
+/* "locpos" is set to the position of the substring in the stringpart, */
+/* or -1 if the text was not found. Text cannot cross stringpart */
+/* boundaries (although this should be allowed). */
+/*----------------------------------------------------------------------*/
+
+stringpart *findtextinstring(char *search, int *locpos, stringpart *strtop,
+ objinstptr localinst)
+{
+ stringpart *strptr = strtop;
+ char *strstart;
+
+ for (strptr = strtop; strptr != NULL; strptr = nextstringpart(strptr, localinst)) {
+ if ((strptr->type == TEXT_STRING) && strptr->data.string) {
+ strstart = strstr(strptr->data.string, search);
+ if (strstart != NULL) {
+ if (locpos != NULL)
+ *locpos = (int)(strstart - (char *)strptr->data.string);
+ return strptr;
+ }
+ }
+ }
+ if (locpos != NULL) *locpos = -1;
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Return a local position and stringpart for "tpos" positions into */
+/* the indicated string. Position and stringpart are for the character */
+/* or command immediately preceding "tpos" */
+/*----------------------------------------------------------------------*/
+
+stringpart *findstringpart(int tpos, int *locpos, stringpart *strtop,
+ objinstptr localinst)
+{
+ stringpart *strptr = strtop;
+ int testpos = 0, tmplen;
+
+ for (strptr = strtop; strptr != NULL; strptr = nextstringpart(strptr, localinst)) {
+ if ((strptr->type == TEXT_STRING) && strptr->data.string) {
+ tmplen = strlen(strptr->data.string);
+ if (testpos + tmplen > tpos) {
+ if (locpos != NULL) *locpos = (tpos - testpos);
+ return strptr;
+ }
+ else testpos += tmplen - 1;
+ }
+ if (locpos != NULL) *locpos = -1;
+ if (testpos >= tpos) return strptr;
+
+ testpos++;
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* The following must be in an order matching the "Text string part */
+/* types" defined in xcircuit.h. */
+/*----------------------------------------------------------------------*/
+
+static char *nonprint[] = {
+ "Text", "Subscript", "Superscript", "Normalscript",
+ "Underline", "Overline", "Noline",
+ "Tab_Stop", "Tab_Forward", "Tab_Backward",
+ "Halfspace", "Quarterspace", "<Return>",
+ "Font", "Scale", "Color", "Margin_Stop", "Kern",
+ "Parameter", ">", "Net_Name", "Error", NULL}; /* (jdk) */
+
+/* Handling of certain text escapes (subscript, superscript, underline, */
+/* and overline) in TeX (added by Fabian Inostroza) */
+
+static char *nonprinttex[] = {
+ "", "_{", "^{", "}",
+ "\\underline{", "\\overline{", "}",
+ "Tab_Stop", "Tab_Forward", "Tab_Backward",
+ "Halfspace", "Quarterspace", "<Return>",
+ "Font", "Scale", "Color", "Margin_Stop", "Kern",
+ "Parameter", ">", "Net_Name", "Error", NULL};
+
+/*----------------------------------------------------------------------*/
+/* charprint(): */
+/* Write a printable version of the character or command at the */
+/* indicated string part and position. */
+/*----------------------------------------------------------------------*/
+
+void charprint(char *sout, stringpart *strptr, int locpos)
+{
+ char sc;
+
+ switch (strptr->type) {
+ case TEXT_STRING:
+ if (strptr->data.string) {
+ if (locpos > strlen(strptr->data.string)) {
+ strcpy(sout, "<ERROR>");
+ }
+ else sc = *(strptr->data.string + locpos);
+ if (isprint(sc))
+ sprintf(sout, "%c", sc);
+ else
+ sprintf(sout, "/%03o", (u_char)sc);
+ }
+ else
+ *sout = '\0';
+ break;
+ case FONT_NAME:
+ sprintf(sout, "Font=%s", (strptr->data.font >= fontcount) ?
+ "(unknown)" : fonts[strptr->data.font].psname);
+ break;
+ case FONT_SCALE:
+ sprintf(sout, "Scale=%3.2f", strptr->data.scale);
+ break;
+ case KERN:
+ sprintf(sout, "Kern=(%d,%d)", strptr->data.kern[0], strptr->data.kern[1]);
+ break;
+ case PARAM_START:
+ sprintf(sout, "Parameter(%s)<", strptr->data.string);
+ break;
+ default:
+ strcpy(sout, nonprint[strptr->type]);
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Version of the above, for printing LaTeX strings */
+/* added by Fabian Inostroza 7/14/2013 */
+/*----------------------------------------------------------------------*/
+
+void charprinttex(char *sout, stringpart *strptr, int locpos)
+{
+ char sc;
+
+ switch (strptr->type) {
+ case TEXT_STRING:
+ if (strptr->data.string) {
+ if (locpos > strlen(strptr->data.string)) {
+ strcpy(sout, "<ERROR>");
+ }
+ else sc = *(strptr->data.string + locpos);
+ if (isprint(sc))
+ sprintf(sout, "%c", sc);
+ else
+ sprintf(sout, "/%03o", (u_char)sc);
+ }
+ else
+ *sout = '\0';
+ break;
+
+ default:
+ *sout = '\0';
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Print a string (allocates memory for the string; must be freed by */
+/* the calling routine). */
+/*----------------------------------------------------------------------*/
+
+char *xcstringtostring(stringpart *strtop, objinstptr localinst, Boolean textonly)
+{
+ stringpart *strptr;
+ int pos = 0, locpos;
+ char *sout;
+
+ sout = (char *)malloc(1);
+ sout[0] = '\0';
+
+ while ((strptr = findstringpart(pos++, &locpos, strtop, localinst)) != NULL) {
+ if (!textonly || strptr->type == TEXT_STRING) {
+ charprint(_STR, strptr, locpos);
+ sout = (char *)realloc(sout, strlen(sout) + strlen(_STR) + 1);
+ strcat(sout, _STR);
+ }
+ /* Overbar on schematic names is translated to logical-NOT ("!") */
+ else if (textonly && strptr->type == OVERLINE) {
+ sout = (char *)realloc(sout, strlen(sout) + 2);
+ strcat(sout, "!");
+ }
+ }
+ return sout;
+}
+
+/*----------------------------------------------------------------------*/
+/* Version of the above, for printing LaTeX strings */
+/* added by Fabian Inostroza 7/14/2013 */
+/*----------------------------------------------------------------------*/
+
+char *textprinttex(stringpart *strtop, objinstptr localinst)
+{
+ stringpart *strptr;
+ int pos = 0, locpos;
+ char *sout;
+
+ sout = (char *)malloc(1);
+ sout[0] = '\0';
+
+ while ((strptr = findstringpart(pos++, &locpos, strtop, localinst)) != NULL) {
+ charprinttex(_STR, strptr, locpos);
+ sout = (char *)realloc(sout, strlen(sout) + strlen(_STR) + 1);
+ strcat(sout, _STR);
+ }
+ return sout;
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrappers for xcstringtostring(): */
+/* stringprint() includes information on text controls appropriate */
+/* for printing in the message window (charreport()) */
+/*----------------------------------------------------------------------*/
+
+char *stringprint(stringpart *strtop, objinstptr localinst)
+{
+ return xcstringtostring(strtop, localinst, False);
+}
+
+/*----------------------------------------------------------------------*/
+/* textprint() excludes text controls, resulting in a string */
+/* appropriate for netlist information, or for promoting a string */
+/* parameter to a numeric type. */
+/*----------------------------------------------------------------------*/
+
+char *textprint(stringpart *strtop, objinstptr localinst)
+{
+ return xcstringtostring(strtop, localinst, True);
+}
+
+/*----------------------------------------------------------------------*/
+/* textprintsubnet() is like textprint(), except that strings in bus */
+/* notation are reduced to just the single subnet. */
+/*----------------------------------------------------------------------*/
+
+char *textprintsubnet(stringpart *strtop, objinstptr localinst, int subnet)
+{
+ char *newstr, *busptr, *endptr, *substr;
+
+ newstr = xcstringtostring(strtop, localinst, True);
+ if (subnet >= 0) {
+ busptr = strchr(newstr, areawin->buschar);
+ if (busptr != NULL) {
+ endptr = find_delimiter(busptr);
+ if (endptr != NULL) {
+ if (busptr == newstr)
+ sprintf(newstr, "%d", subnet);
+ else {
+ substr = strdup(newstr);
+ busptr++;
+ sprintf(substr + (int)(busptr - newstr), "%d%s", subnet, endptr);
+ free(newstr);
+ return substr;
+ }
+ }
+ }
+ else {
+ /* Promote a non-bus label to a bus label */
+ substr = malloc(10 + strlen(newstr));
+ strcpy(substr, newstr);
+ endptr = substr;
+ while ((*endptr) != '\0') endptr++;
+ sprintf(endptr, "%c%d%c", areawin->buschar, subnet,
+ standard_delimiter_end(areawin->buschar));
+ free(newstr);
+ return substr;
+ }
+ }
+ return newstr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Another variant: Print a subnet list according to the entries in */
+/* a netlist (Genericlist *) pointer. This includes the condition in */
+/* which the list is a single wire, not a bus. If "pinstring" is non- */
+/* NULL, it will be used as the name of the subnet. Otherwise, */
+/* "prefix" will be used, and will be appended with the net ID of the */
+/* first net in the sublist to make the identifier unique. */
+/*----------------------------------------------------------------------*/
+
+char *textprintnet(char *prefix, char *pinstring, Genericlist *sublist)
+{
+ char *newstr, *sptr;
+ buslist *sbus;
+ int i;
+
+ if (sublist->subnets == 0) {
+ newstr = (char *)malloc(strlen(prefix) + 10);
+ sprintf(newstr, "%s%d", prefix, sublist->net.id);
+ }
+ else { /* just make a comma-separated list */
+ newstr = (char *)malloc(strlen(prefix) + 20 + 3 * sublist->subnets);
+ sbus = sublist->net.list;
+ sprintf(newstr, "%s%d%c", prefix, sbus->netid, areawin->buschar);
+ for (i = 0; i < sublist->subnets; i++) {
+ sbus = sublist->net.list + i;
+ sptr = newstr + strlen(newstr);
+ if (i != 0)
+ strcat(sptr++, ",");
+ sprintf(sptr, "%d", sbus->subnetid);
+ }
+ sptr = newstr + strlen(newstr);
+ sprintf(sptr, "%c", standard_delimiter_end(areawin->buschar));
+ }
+ return newstr;
+}
+
+/*----------------------------------------------------------------------*/
+/* Test equivalence of the text string parts of a label with the */
+/* indicated char * string. */
+/* */
+/* Return 0 if the strings match. Return 1 or the result of strcmp() */
+/* on the first non-matching substring text segment if the strings */
+/* don't match. */
+/* */
+/* If "exact" is True, requires an exact match, otherwise requires */
+/* that the label only match text to the length of text. */
+/*----------------------------------------------------------------------*/
+
+int textcompx(stringpart *string, char *text, Boolean exact, objinstptr localinst)
+{
+ stringpart *strptr;
+ char *tptr = text;
+ char *sptr;
+ int rval, llen = strlen(text), slen;
+ Boolean has_text = FALSE;
+
+ for (strptr = string; strptr != NULL; strptr = nextstringpart(strptr, localinst)) {
+ if (strptr->type == TEXT_STRING) {
+ has_text = TRUE;
+ sptr = strptr->data.string;
+ slen = min(strlen(sptr), llen);
+ llen -= slen;
+ if (!exact && (rval = strncmp(sptr, tptr, slen)))
+ return rval;
+ else if (exact && (rval = strcmp(sptr, tptr)))
+ return rval;
+ else if (!exact && (llen == 0))
+ return 0;
+ else
+ tptr += slen;
+ }
+ }
+
+ /* Check condition that no text was encountered in the xcircuit string */
+ return ((llen > 0) && !has_text) ? 1 : 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrappers for textcompx(), equivalent to strcmp() and strncmp(). */
+/*----------------------------------------------------------------------*/
+
+int textcomp(stringpart *string, char *text, objinstptr localinst)
+{
+ return textcompx(string, text, True, localinst);
+}
+
+/*----------------------------------------------------------------------*/
+
+int textncomp(stringpart *string, char *text, objinstptr localinst)
+{
+ return textcompx(string, text, False, localinst);
+}
+
+/*----------------------------------------------------------------------*/
+/* Test equivalence of two label strings */
+/*----------------------------------------------------------------------*/
+
+int stringcomp(stringpart *string1, stringpart *string2)
+{
+ stringpart *strptr1, *strptr2;
+
+ for (strptr1 = string1, strptr2 = string2; strptr1 != NULL && strptr2 != NULL;
+ strptr1 = strptr1->nextpart, strptr2 = strptr2->nextpart) {
+ if (strptr1->type != strptr2->type)
+ return 1;
+ else {
+ switch (strptr1->type) {
+ case TEXT_STRING:
+ if (strptr1->data.string && strptr2->data.string) {
+ if (strcmp(strptr1->data.string, strptr2->data.string))
+ return 1;
+ }
+ else if (strptr1->data.string || strptr2->data.string)
+ return 1;
+ break;
+ case FONT_SCALE:
+ if (strptr1->data.scale != strptr2->data.scale) return 1;
+ break;
+ case FONT_COLOR:
+ if (strptr1->data.color != strptr2->data.color) return 1;
+ break;
+ case FONT_NAME:
+ if (strptr1->data.font != strptr2->data.font) return 1;
+ break;
+ case KERN:
+ if (strptr1->data.kern[0] != strptr2->data.kern[0] ||
+ strptr1->data.kern[1] != strptr2->data.kern[1]) return 1;
+ break;
+ }
+ }
+ }
+
+ /* One string continues after the other ends. . . */
+ if (strptr1 != NULL || strptr2 != NULL) return 1;
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Test if the specified font is in the "Symbol" font family. */
+/*----------------------------------------------------------------------*/
+
+Boolean issymbolfont(int fontnumber)
+{
+ if (!strcmp(fonts[fontnumber].family, "Symbol")) return True;
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Test if the specified font is in the "Helvetica" font family. */
+/* SVG uses this to make sure it scales down the font by 7/8 to match */
+/* our internal vectors, and to use "oblique" for the style instead of */
+/* "italic". */
+/*----------------------------------------------------------------------*/
+
+Boolean issansfont(int fontnumber)
+{
+ if (!strcmp(fonts[fontnumber].family, "Helvetica")) return True;
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* Test if the specified font is ISO-Latin1 encoding */
+/*----------------------------------------------------------------------*/
+
+Boolean isisolatin1(int fontnumber)
+{
+ if ((fonts[fontnumber].flags & 0xf80) == 0x100) return True;
+ return False;
+}
+
+/*----------------------------------------------------------------------*/
+/* For a label representing a single bus subnet, return the index of */
+/* the subnet. */
+/*----------------------------------------------------------------------*/
+
+int sub_bus_idx(labelptr thislab, objinstptr thisinst)
+{
+ stringpart *strptr;
+ char *busptr;
+ int busidx;
+
+ for (strptr = thislab->string; strptr != NULL; strptr =
+ nextstringpart(strptr, thisinst)) {
+ if (strptr->type == TEXT_STRING) {
+ if ((busptr = strchr(strptr->data.string, areawin->buschar)) != NULL) {
+ if (sscanf(++busptr, "%d", &busidx) == 1)
+ return busidx;
+ }
+ if (sscanf(strptr->data.string, "%d", &busidx) == 1)
+ return busidx;
+ }
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* The following routine is like sub_bus_idx but returns TRUE or FALSE */
+/* depending on whether the label was determined to be in bus notation */
+/* or not. Note that sub_bux_idx may be run on sub-bus names (those */
+/* that are internally generated from labels in bus notation), but */
+/* pin_is_bus should not, because pin numbers in bus notation get the */
+/* bus delimiters stripped from them. */
+/*----------------------------------------------------------------------*/
+
+Boolean pin_is_bus(labelptr thislab, objinstptr thisinst)
+{
+ stringpart *strptr;
+ char *busptr;
+ /* int busidx; (jdk) */
+ Boolean found_delimiter = FALSE;
+
+ for (strptr = thislab->string; strptr != NULL; strptr =
+ nextstringpart(strptr, thisinst)) {
+ if (strptr->type == TEXT_STRING) {
+ if ((busptr = strchr(strptr->data.string, areawin->buschar)) != NULL) {
+ if (isdigit(*(++busptr)))
+ return TRUE;
+ else
+ found_delimiter = TRUE;
+ }
+ else if (found_delimiter == TRUE) {
+ return (isdigit(*(strptr->data.string))) ? TRUE : FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* When encountering a label with bus notation, create a list of */
+/* subnets belonging to the bus. Return the list as a pointer to a */
+/* Genericlist structure. This structure is statically allocated and */
+/* is expected to have its contents copied into the target netlist */
+/* element. */
+/* */
+/* Unlike the above routine, this routine prints the original string */
+/* into a char* array using textprint() so that escape sequences are */
+/* removed and will not affect the result. */
+/* */
+/* To speed things up, the calling routine should have already called */
+/* pin_is_bus() to determine if the label does indeed represent a bus. */
+/* break_up_bus() is much slower in determining this. If break_up_bus */
+/* is passed a string that cannot be identified as a bus, then it */
+/* returns a NULL pointer. */
+/* */
+/* If netlist points to a structure with no subnets, then its net ID */
+/* is the starting point for the nets returned by break_up_bus. */
+/* Otherwise, netlist is assumed to be a valid netlist for a bus that */
+/* matches "blab", and we will use net IDs from this list. */
+/*----------------------------------------------------------------------*/
+
+Genericlist *break_up_bus(labelptr blab, objinstptr thisinst, Genericlist *netlist)
+{
+ static Genericlist *subnets = NULL;
+ char *tptr;
+ buslist *sbus, *jbus;
+ int bpos, istart, iend, tlen, i, j, netstart, matched;
+ char *buspos, *busend, *busptr;
+
+ if (pin_is_bus(blab, thisinst) == FALSE) return NULL;
+ if (subnets == NULL) {
+ /* This happens on the first pass only */
+ subnets = (Genericlist *)malloc(sizeof(Genericlist));
+ subnets->net.list = (buslist *)malloc(sizeof(buslist));
+ }
+ subnets->subnets = 0;
+
+ tptr = textprint(blab->string, thisinst);
+ tlen = strlen(tptr) + 1;
+ buspos = strchr(tptr, areawin->buschar);
+
+ /* The notation "(...)" with NO TEXT preceding the opening bus */
+ /* delimiter, is assumed to represent a numerical pin range. So */
+ /* instead of generating labels, e.g., "(1)", "(2)", etc., we */
+ /* generate labels "1", "2", etc. */
+
+ if (buspos == NULL) {
+ Fprintf(stderr, "Error: Bus specification has no start delimiter!\n");
+ goto doneBus;
+ }
+
+ netstart = (netlist->subnets == 0) ? netlist->net.id : 0;
+
+ bpos = (int)(buspos - tptr);
+ busend = find_delimiter(buspos);
+
+ if (busend == NULL) {
+ Fprintf(stderr, "Error: Bus specification has no end delimiter!\n");
+ goto doneBus;
+ }
+
+ /* Find the range of each bus */
+
+ matched = 0;
+ istart = -1;
+ for (busptr = buspos + 1; busptr < busend; busptr++) {
+ if (sscanf(busptr, "%d", &iend) == 0) break;
+ while ((*busptr != ':') && (*busptr != '-') && (*busptr != ',')
+ && (*busptr != *busend))
+ busptr++;
+ if ((*busptr == ':') || (*busptr == '-')) /* numerical range */
+ istart = iend;
+ else {
+ if (istart < 0) istart = iend;
+ i = istart;
+ while (1) {
+
+ /* Create a new list entry for this subnet number */
+
+ subnets->subnets++;
+ subnets->net.list = (buslist *)realloc(subnets->net.list,
+ subnets->subnets * sizeof(buslist));
+
+ sbus = subnets->net.list + subnets->subnets - 1;
+ sbus->subnetid = i;
+ if (netstart > 0) {
+ sbus->netid = netstart++;
+ matched++;
+ }
+ else {
+ /* Net ID is the net ID for the matching subnet of netlist */
+ for (j = 0; j < netlist->subnets; j++) {
+ jbus = netlist->net.list + j;
+ if (jbus->subnetid == i) {
+ matched++;
+ sbus->netid = jbus->netid;
+ break;
+ }
+ }
+ /* Insert a net ID of zero if it can't be found */
+ if (j == netlist->subnets) {
+ sbus->netid = 0;
+ }
+ }
+
+ if (i == iend) break;
+ else if (istart > iend) i--;
+ else i++;
+ }
+ istart = -1;
+ }
+ }
+
+doneBus:
+ free(tptr);
+ return (matched == 0) ? NULL : subnets;
+}
+
+/*----------------------------------------------------------------------*/
+/* Test equivalence of two label strings (relaxed constraints) */
+/* Like stringcomp(), but ignores "superficial" differences such as */
+/* color and font (unless one of the fonts is Symbol), scale, */
+/* underlining, tabbing, and kerning. */
+/* */
+/* Return 0 if matching. Return 1 if not matching. */
+/* */
+/* For bus notation, ignore everything inside the bus delimiters. */
+/* The calling routine must determine if the labels being compared */
+/* have matching subnet ranges. Note that as written, this does not */
+/* check any text occurring after the opening bus delimiter! Thus, */
+/* "mynet(1:2)" and "mynet(3:4)" and "mynet(1)_alt" are all considered */
+/* exact matches in bus notation. */
+/*----------------------------------------------------------------------*/
+
+int stringcomprelaxed(stringpart *string1, stringpart *string2,
+ objinstptr thisinst)
+{
+ stringpart *strptr1 = string1, *strptr2 = string2;
+ Boolean font1 = False, font2 = False, inbus_match = TRUE;
+ int in_bus = 0;
+ char *buspos;
+ int bpos;
+
+ if (strptr1->type == FONT_NAME)
+ font1 = issymbolfont(strptr1->data.font);
+ if (strptr2->type == FONT_NAME)
+ font2 = issymbolfont(strptr2->data.font);
+
+ while ((strptr1 != NULL) || (strptr2 != NULL)) {
+ while (strptr1 != NULL && strptr1->type != TEXT_STRING &&
+ strptr1->type != OVERLINE) {
+ if (strptr1->type == FONT_NAME)
+ font1 = issymbolfont(strptr1->data.font);
+ strptr1 = nextstringpart(strptr1, thisinst);
+ }
+ while (strptr2 != NULL && strptr2->type != TEXT_STRING &&
+ strptr2->type != OVERLINE) {
+ if (strptr2->type == FONT_NAME)
+ font2 = issymbolfont(strptr2->data.font);
+ strptr2 = nextstringpart(strptr2, thisinst);
+ }
+ if (strptr1 == NULL || strptr2 == NULL) break;
+ if (font1 != font2) return 1;
+ if (strptr1->type != strptr2->type) return 1;
+ else {
+ switch (strptr1->type) {
+ case TEXT_STRING:
+ if (in_bus == 1) {
+ char matchchar = areawin->buschar;
+ switch (areawin->buschar) {
+ case '(': matchchar = ')'; break;
+ case '[': matchchar = ']'; break;
+ case '{': matchchar = '}'; break;
+ case '<': matchchar = '>'; break;
+ }
+ buspos = strchr(strptr1->data.string, matchchar);
+ if (buspos != NULL) {
+ bpos = (int)(buspos - (char *)(strptr1->data.string));
+ if (strlen(strptr2->data.string) > bpos) {
+ if (!strcmp(strptr1->data.string + bpos,
+ strptr2->data.string + bpos)) {
+ in_bus = 2;
+ break;
+ }
+ }
+ return 1;
+ }
+ if (inbus_match == TRUE)
+ if (strcmp(strptr1->data.string, strptr2->data.string))
+ inbus_match = FALSE;
+ }
+ else if (!strcmp(strptr1->data.string, strptr2->data.string))
+ break;
+
+ /* To be a matching bus, the strings match everywhere */
+ /* except between the bus notation delimiters (default */
+ /* "()". */
+
+ buspos = strchr(strptr1->data.string, areawin->buschar);
+ if (buspos != NULL) {
+
+ bpos = (int)(buspos - (char *)(strptr1->data.string)) + 1;
+ if (!strncmp(strptr1->data.string, strptr2->data.string, bpos)) {
+ in_bus = 1;
+ break;
+ }
+ }
+ return 1; /* strings did not match, exactly or as bus notation */
+ break;
+ case OVERLINE:
+ if (strptr1->type != strptr2->type) return 1;
+ break;
+ }
+ strptr1 = nextstringpart(strptr1, thisinst);
+ strptr2 = nextstringpart(strptr2, thisinst);
+ }
+ }
+
+ /* One string continues after the other ends. . . */
+ if (strptr1 != NULL || strptr2 != NULL) return 1;
+
+ /* Treat no closing bus delimiter as a non-bus string */
+ else if ((in_bus == 1) && (inbus_match == FALSE)) return 1;
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/* Find the number of parts in a string (excluding parameter contents) */
+/*----------------------------------------------------------------------*/
+
+int stringparts(stringpart *string)
+{
+ stringpart *strptr;
+ int ptotal = 0;
+
+ for (strptr = string; strptr != NULL; strptr = strptr->nextpart)
+ ptotal++;
+
+ return ptotal;
+}
+
+/*----------------------------------------------------------------------*/
+/* Compute the total character length of a string */
+/* If "doparam" is True, include parameter contents. */
+/*----------------------------------------------------------------------*/
+
+int stringlength(stringpart *string, Boolean doparam, objinstptr thisinst)
+{
+ stringpart *strptr;
+ int ctotal = 0;
+
+ for (strptr = string; strptr != NULL; strptr = (doparam) ?
+ nextstringpart(strptr, thisinst) : strptr->nextpart) {
+ if (strptr->type == TEXT_STRING) {
+ if (strptr->data.string)
+ ctotal += strlen(strptr->data.string);
+ }
+ else
+ ctotal++;
+ }
+
+ return ctotal;
+}
+
+/*----------------------------------------------------------------------*/
+/* Copy the contents of a string (excluding parameter contents) */
+/*----------------------------------------------------------------------*/
+
+stringpart *stringcopy(stringpart *string)
+{
+ stringpart *strptr, *newpart, *newtop = NULL, *topptr;
+
+ for (strptr = string; strptr != NULL; strptr = strptr->nextpart) {
+
+ /* Don't use makesegment(), which looks at parameter contents */
+ newpart = (stringpart *)malloc(sizeof(stringpart));
+ newpart->nextpart = NULL;
+ if (newtop == NULL)
+ newtop = newpart;
+ else
+ topptr->nextpart = newpart;
+ topptr = newpart;
+
+ newpart->type = strptr->type;
+ if ((strptr->type == TEXT_STRING) || (strptr->type == PARAM_START)) {
+ newpart->data.string = (char *)malloc(1 + strlen(strptr->data.string));
+ strcpy(newpart->data.string, strptr->data.string);
+ }
+ else
+ newpart->data = strptr->data;
+ }
+ return newtop;
+}
+
+/*----------------------------------------------------------------------*/
+/* Copy the contents of a string, embedding parameter contents */
+/*----------------------------------------------------------------------*/
+
+stringpart *stringcopyall(stringpart *string, objinstptr thisinst)
+{
+ stringpart *strptr, *newpart, *newtop, *topend;
+
+ for (strptr = string; strptr != NULL;
+ strptr = nextstringpart(strptr, thisinst)) {
+ newpart = (stringpart *)malloc(sizeof(stringpart));
+ newpart->type = strptr->type;
+ newpart->nextpart = NULL;
+ if (strptr == string) newtop = newpart;
+ else topend->nextpart = newpart;
+ topend = newpart;
+ if ((strptr->type == TEXT_STRING || strptr->type == PARAM_START)
+ && strptr->data.string) {
+ newpart->data.string = (char *)malloc(1 + strlen(strptr->data.string));
+ strcpy(newpart->data.string, strptr->data.string);
+ }
+ else
+ newpart->data = strptr->data;
+ }
+ return newtop;
+}
+
+/*----------------------------------------------------------------------*/
+/* Copy the contents of a saved string with embedded parameter contents */
+/* back to the string and the instance parameters. */
+/*----------------------------------------------------------------------*/
+
+stringpart *stringcopyback(stringpart *string, objinstptr thisinst)
+{
+ stringpart *strptr, *newpart, *curend = NULL;
+ stringpart *rettop, *curtop, *savend = NULL;
+ char *key = NULL;
+ oparamptr pparam;
+ Boolean need_free;
+
+ for (strptr = string; strptr != NULL; strptr = strptr->nextpart) {
+
+ newpart = (stringpart *)malloc(sizeof(stringpart));
+ newpart->type = strptr->type;
+ newpart->nextpart = NULL;
+ newpart->data.string = NULL;
+
+ if (strptr == string) rettop = newpart; /* initial segment */
+ else curend->nextpart = newpart; /* append segment to label */
+
+ if (curend) {
+ if (curend->type == PARAM_START) {
+ key = curend->data.string;
+ curtop = newpart;
+ savend = curend;
+ need_free = False;
+ }
+ else if (curend->type == PARAM_END) {
+ curend->nextpart = NULL;
+ savend->nextpart = newpart;
+ if (need_free) freelabel(curtop);
+ need_free = False;
+ }
+ }
+ curend = newpart;
+
+ if (strptr->type == TEXT_STRING || strptr->type == PARAM_START) {
+ if (strptr->data.string) {
+ newpart->data.string = (char *)malloc(1 + strlen(strptr->data.string));
+ strcpy(newpart->data.string, strptr->data.string);
+ }
+ else
+ newpart->data.string = NULL;
+ }
+ else if (strptr->type == PARAM_END) {
+ if (key != NULL) {
+ pparam = find_param(thisinst, key);
+ if (pparam == NULL) {
+ Fprintf(stderr, "Error: Bad parameter %s encountered!\n", key);
+ }
+ else if (pparam->type == XC_STRING) {
+ freelabel(pparam->parameter.string);
+ pparam->parameter.string = curtop;
+ key = NULL;
+ }
+ else {
+ float fval;
+ int ival;
+ char *tmpstr = textprint(curtop, thisinst);
+
+ /* Promote string types into the type of the parameter */
+ switch (pparam->type) {
+ case XC_INT:
+ if (sscanf(tmpstr, "%d", &ival) == 1)
+ pparam->parameter.ivalue = ival;
+ free(tmpstr);
+ break;
+ case XC_FLOAT:
+ if (sscanf(tmpstr, "%g", &fval) == 1)
+ pparam->parameter.fvalue = fval;
+ break;
+ case XC_EXPR:
+ /* Expression results are derived and cannot be */
+ /* changed except by changing the expression */
+ /* itself. */
+ break;
+ }
+ free(tmpstr);
+ need_free = True;
+ key = NULL;
+ }
+ }
+ else {
+ Fprintf(stderr, "Error: Bad parameter in stringcopyback()\n");
+ }
+ }
+ else
+ newpart->data = strptr->data;
+ }
+
+ /* tie up loose ends, if necessary */
+ if ((curend != NULL) && (curend->type == PARAM_END)) {
+ savend->nextpart = NULL;
+ if (need_free) freelabel(curtop);
+ }
+
+ return rettop;
+}
+
+/*---------------------------------------------------------------------*/
+/* draw a single character at 0, 0 using current transformation matrix */
+/*---------------------------------------------------------------------*/
+
+short UDrawChar(u_char code, short styles, short ffont, int groupheight,
+ int passcolor, float passwidth)
+{
+ objectptr drawchar;
+ XPoint alphapts[2];
+ short localwidth;
+ objinst charinst;
+
+ if ((ffont >= fontcount) || (fonts[ffont].encoding == NULL))
+ return 0;
+
+ alphapts[0].x = 0;
+ alphapts[0].y = 0;
+ charinst.type = OBJINST;
+ charinst.color = DEFAULTCOLOR;
+ charinst.rotation = 0;
+ charinst.scale = fonts[ffont].scale;
+ charinst.position = alphapts[0];
+ charinst.params = NULL;
+
+ /* get proper font and character */
+
+ drawchar = fonts[ffont].encoding[(u_char)code];
+ charinst.thisobject = drawchar;
+
+ localwidth = (drawchar->bbox.lowerleft.x + drawchar->bbox.width) * fonts[ffont].scale;
+
+ if ((fonts[ffont].flags & 0x22) == 0x22) { /* font is derived and italic */
+ USlantCTM(DCTM, 0.25); /* premultiply by slanting function */
+ }
+
+ if (!(styles & 64)) {
+
+ UDrawObject(&charinst, SINGLE, passcolor, passwidth, NULL);
+
+ /* under- and overlines */
+ if (styles & 8)
+ alphapts[0].y = alphapts[1].y = -6;
+ else if (styles & 16)
+ alphapts[0].y = alphapts[1].y = groupheight + 4;
+ if (styles & 24) {
+ alphapts[0].x = 0; alphapts[1].x = localwidth;
+ UDrawSimpleLine(&alphapts[0], &alphapts[1]);
+ }
+ }
+ return localwidth;
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw an entire string, including parameter substitutions */
+/* (Normally called as UDrawString(); see below) */
+/*----------------------------------------------------------------------*/
+
+void UDrawString0(labelptr drawlabel, int passcolor, objinstptr localinst,
+ Boolean drawX)
+{
+ stringpart *strptr;
+ char *textptr;
+ short fstyle, ffont, tmpjust, baseline;
+ int pos, group = 0;
+ int defaultcolor, curcolor, scolor;
+ short oldx, oldfont, oldstyle;
+ float tmpscale = 1.0, natscale = 1.0, tmpthick = 2.0;
+ XPoint newpoint, bboxin[2], bboxout[2];
+ u_char xm, ym;
+ TextExtents tmpext;
+ short *tabstops = NULL;
+ short tabno, numtabs = 0;
+ int marginstop = 0;
+
+ if (fontcount == 0) return;
+
+ /* Don't draw temporary labels from schematic capture system */
+ if (drawlabel->string->type != FONT_NAME) return;
+
+ if (passcolor == DOSUBSTRING)
+ defaultcolor = curcolor = drawlabel->color;
+ else
+ defaultcolor = curcolor = passcolor;
+
+ if (defaultcolor != DOFORALL) {
+ if (drawlabel->color != DEFAULTCOLOR)
+ curcolor = drawlabel->color;
+ else
+ curcolor = defaultcolor;
+ XTopSetForeground(curcolor);
+ }
+
+ /* calculate the transformation matrix for this object */
+ /* in natural units of the alphabet vectors */
+ /* (conversion to window units) */
+
+ UPushCTM();
+ UPreMultCTM(DCTM, drawlabel->position, drawlabel->scale, drawlabel->rotation);
+
+ /* check for flip invariance; recompute CTM and justification if necessary */
+
+ tmpjust = flipadjust(drawlabel->justify);
+
+ /* "natural" (unscaled) length */
+ tmpext = ULength(drawlabel, localinst, 0, NULL);
+
+ newpoint.x = (tmpjust & NOTLEFT ?
+ (tmpjust & RIGHT ? -tmpext.maxwidth : -tmpext.maxwidth >> 1) : 0);
+ newpoint.y = (tmpjust & NOTBOTTOM ?
+ (tmpjust & TOP ? -tmpext.ascent : -(tmpext.ascent + tmpext.base) >> 1)
+ : -tmpext.base);
+
+ /* Pinlabels have an additional offset spacing to pad */
+ /* them from the circuit point to which they attach. */
+
+ if (drawlabel->pin) {
+ pinadjust(tmpjust, &(newpoint.x), &(newpoint.y), 1);
+ }
+
+ oldx = newpoint.x;
+ baseline = newpoint.y;
+
+ /* do quick calculation on bounding box; don't draw if off-screen */
+
+ bboxin[0].x = newpoint.x;
+ bboxin[0].y = newpoint.y + tmpext.descent;
+ bboxin[1].x = newpoint.x + tmpext.width;
+ bboxin[1].y = newpoint.y + tmpext.ascent;
+ UTransformbyCTM(DCTM, bboxin, bboxout, 2);
+ xm = (bboxout[0].x < bboxout[1].x) ? 0 : 1;
+ ym = (bboxout[0].y < bboxout[1].y) ? 0 : 1;
+
+ if (bboxout[xm].x < areawin->width && bboxout[ym].y < areawin->height &&
+ bboxout[1 - xm].x > 0 && bboxout[1 - ym].y > 0) {
+
+ pos = 0;
+ for (strptr = drawlabel->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+
+ /* All segments other than text cancel any */
+ /* existing overline/underline in effect. */
+
+ if (strptr->type != TEXT_STRING)
+ fstyle &= 0xfc7;
+
+ /* deal with each text segment type */
+
+ switch(strptr->type) {
+ case FONT_NAME:
+ if (strptr->data.font < fontcount) {
+ ffont = strptr->data.font;
+ fstyle = 0; /* style reset by font change */
+ if (baseline == newpoint.y) { /* set top-level font and style */
+ oldfont = ffont;
+ oldstyle = fstyle;
+ }
+ }
+
+ /* simple boldface technique for derived fonts */
+
+ tmpthick = ((fonts[ffont].flags & 0x21) == 0x21) ? 4.0 : 2.0;
+ break;
+
+ case FONT_SCALE:
+ tmpscale = natscale * strptr->data.scale;
+ // if (baseline == newpoint.y) /* reset top-level scale */
+ // natscale = tmpscale;
+ break;
+
+ case KERN:
+ newpoint.x += strptr->data.kern[0];
+ newpoint.y += strptr->data.kern[1];
+ break;
+
+ case FONT_COLOR:
+ if (defaultcolor != DOFORALL) {
+ if (strptr->data.color != DEFAULTCOLOR)
+ curcolor = colorlist[strptr->data.color].color.pixel;
+ else {
+ if (curcolor != DEFAULTCOLOR) {
+ XTopSetForeground(defaultcolor);
+ }
+ curcolor = DEFAULTCOLOR;
+ }
+ }
+ break;
+
+ case TABBACKWARD: /* find first tab value with x < xtotal */
+ for (tabno = numtabs - 1; tabno >= 0; tabno--) {
+ if (tabstops[tabno] < newpoint.x) {
+ newpoint.x = tabstops[tabno];
+ break;
+ }
+ }
+ break;
+
+ case TABFORWARD: /* find first tab value with x > xtotal */
+ for (tabno = 0; tabno < numtabs; tabno++) {
+ if (tabstops[tabno] > newpoint.x) {
+ newpoint.x = tabstops[tabno];
+ break;
+ }
+ }
+ break;
+
+ case TABSTOP:
+ numtabs++;
+ if (tabstops == NULL) tabstops = (short *)malloc(sizeof(short));
+ else tabstops = (short *)realloc(tabstops, numtabs * sizeof(short));
+ tabstops[numtabs - 1] = newpoint.x;
+ break;
+
+ case RETURN:
+ tmpscale = natscale = 1.0;
+ baseline -= BASELINE;
+ newpoint.y = baseline;
+ newpoint.x = oldx;
+ break;
+
+ case SUBSCRIPT:
+ natscale *= SUBSCALE;
+ tmpscale = natscale;
+ newpoint.y -= (short)((TEXTHEIGHT >> 1) * natscale);
+ break;
+
+ case SUPERSCRIPT:
+ natscale *= SUBSCALE;
+ tmpscale = natscale;
+ newpoint.y += (short)(TEXTHEIGHT * natscale);
+ break;
+
+ case NORMALSCRIPT:
+ tmpscale = natscale = 1.0;
+ ffont = oldfont; /* revert to top-level font and style */
+ fstyle = oldstyle;
+ newpoint.y = baseline;
+ break;
+
+ case UNDERLINE:
+ fstyle |= 8;
+ break;
+
+ case OVERLINE:
+ if (strptr->nextpart != NULL && strptr->nextpart->type == TEXT_STRING) {
+ objectptr charptr;
+ int tmpheight;
+
+ group = 0;
+ for (textptr = strptr->nextpart->data.string;
+ textptr && *textptr != '\0'; textptr++) {
+ charptr = fonts[ffont].encoding[*(u_char *)textptr];
+ tmpheight = (int)((float)charptr->bbox.height
+ * fonts[ffont].scale);
+ if (group < tmpheight) group = tmpheight;
+ }
+ fstyle |= 16;
+ }
+ break;
+
+ case NOLINE:
+ break;
+
+ case HALFSPACE: case QTRSPACE: {
+ short addx;
+ UPushCTM();
+ UPreMultCTM(DCTM, newpoint, tmpscale, 0);
+ addx = UDrawChar((u_char)32, fstyle, ffont, group,
+ curcolor, tmpthick);
+ newpoint.x += addx >> ((strptr->type == HALFSPACE) ? 1 : 2);
+ UPopCTM();
+ } break;
+
+ case TEXT_STRING:
+ textptr = strptr->data.string;
+
+ /* Don't write technology names in catalog mode if this */
+ /* option is enabled (but *not* CATTEXT_MODE!) */
+
+ if (((eventmode == CATALOG_MODE) && !xobjs.showtech)
+ || ((eventmode == CATTEXT_MODE)
+ && (drawlabel != TOLABEL(EDITPART)))) {
+ char *nsptr = strstr(textptr, "::");
+ if (nsptr != NULL) {
+ textptr = nsptr + 2;
+ pos += (pointertype)nsptr - (pointertype)strptr->data.string + 2;
+ }
+ }
+
+ for (; textptr && *textptr != '\0'; textptr++) {
+ pos++;
+ UPushCTM();
+ UPreMultCTM(DCTM, newpoint, tmpscale, 0);
+
+ /* Special case of selection: only substring is */
+ /* drawn in the selection color. */
+
+ scolor = curcolor;
+ if (passcolor == DOSUBSTRING) {
+ if (pos <= areawin->textpos && pos > areawin->textend)
+ scolor = SELECTCOLOR;
+ else if (pos > areawin->textpos) {
+ XTopSetForeground(curcolor);
+ }
+ }
+ newpoint.x += UDrawChar(*textptr, fstyle, ffont,
+ group, scolor, tmpthick) * tmpscale;
+
+ UPopCTM();
+ }
+ pos--;
+ break;
+ }
+ pos++;
+ }
+ }
+
+ /* enddraw: (jdk) */
+
+ if (tabstops != NULL) free(tabstops);
+
+ /* Pop the string transformation matrix */
+
+ UPopCTM();
+
+ if (drawX && drawlabel->pin) UDrawXDown(drawlabel);
+
+ if ((defaultcolor != DOFORALL) && (passcolor != curcolor)) {
+ XTopSetForeground(passcolor);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw String, with an "x" mark at the origin */
+/*----------------------------------------------------------------------*/
+
+void UDrawString(labelptr drawlabel, int passcolor, objinstptr localinst)
+{
+ UDrawString0(drawlabel, passcolor, localinst, TRUE);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw String, without the "x" mark */
+/*----------------------------------------------------------------------*/
+
+void UDrawStringNoX(labelptr drawlabel, int passcolor, objinstptr localinst)
+{
+ UDrawString0(drawlabel, passcolor, localinst, FALSE);
+}
+
+/*----------------------------------------------------------------------*/
+/* Compute the actual length of a string or portion thereof. */
+/*----------------------------------------------------------------------*/
+
+TextExtents ULength(labelptr drawlabel, objinstptr localinst,
+ short dostop, XPoint *tbreak)
+{
+ float oldscale, strscale, natscale, locscale = 1.0, xtotal = 0.5;
+ float lasttotal = xtotal;
+ stringpart *strptr;
+ u_char *textptr;
+ objectptr *somebet = NULL, chptr;
+ short locpos = 0, lastpos = 0;
+ float ykern = 0.0;
+ TextExtents retext;
+ short *tabstops = NULL;
+ short tabno, numtabs = 0;
+ int marginstop = 0;
+ Boolean dobreak = FALSE;
+
+ retext.ascent = retext.descent = retext.base = 0;
+ retext.width = retext.maxwidth = 0;
+
+ if (fontcount == 0) return retext;
+
+ /* Don't draw temporary labels from schematic capture system */
+ else if (drawlabel->string->type != FONT_NAME) return retext;
+
+ natscale = 1.0;
+
+ oldscale = strscale = natscale;
+
+ for (strptr = drawlabel->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+ switch (strptr->type) {
+ case SUPERSCRIPT:
+ natscale *= SUBSCALE;
+ strscale = natscale;
+ ykern += TEXTHEIGHT * natscale;
+ break;
+ case SUBSCRIPT:
+ natscale *= SUBSCALE;
+ strscale = natscale;
+ ykern -= TEXTHEIGHT * natscale / 2.0;
+ break;
+ case NORMALSCRIPT:
+ natscale = strscale = oldscale;
+ ykern = 0.0;
+ break;
+ case RETURN:
+ natscale = strscale = oldscale;
+ ykern = 0.0;
+ retext.base -= BASELINE;
+ retext.maxwidth = max(retext.width, xtotal);
+ xtotal = 0.5;
+ break;
+ case HALFSPACE:
+ if (somebet) {
+ chptr = (*(somebet + 32));
+ xtotal += (float)(chptr->bbox.width + chptr->bbox.lowerleft.x)
+ * locscale * natscale / 2;
+ }
+ break;
+ case QTRSPACE:
+ if (somebet) {
+ chptr = (*(somebet + 32));
+ xtotal += (float)(chptr->bbox.width + chptr->bbox.lowerleft.x)
+ * locscale * natscale / 4;
+ }
+ break;
+ case TABBACKWARD: /* find first tab value with x < xtotal */
+ for (tabno = numtabs - 1; tabno >= 0; tabno--) {
+ if (tabstops[tabno] < xtotal) {
+ xtotal = tabstops[tabno];
+ break;
+ }
+ }
+ break;
+ case TABFORWARD: /* find first tab value with x > xtotal */
+ for (tabno = 0; tabno < numtabs; tabno++) {
+ if (tabstops[tabno] > xtotal) {
+ xtotal = tabstops[tabno];
+ break;
+ }
+ }
+ break;
+ case TABSTOP:
+ numtabs++;
+ if (tabstops == NULL) tabstops = (short *)malloc(sizeof(short));
+ else tabstops = (short *)realloc(tabstops, numtabs * sizeof(short));
+ tabstops[numtabs - 1] = xtotal;
+ break;
+ case FONT_SCALE:
+ strscale = natscale * strptr->data.scale;
+ if (ykern == 0.0)
+ natscale = strscale;
+ break;
+ case KERN:
+ xtotal += strptr->data.kern[0];
+ ykern += strptr->data.kern[1];
+ break;
+ case FONT_NAME:
+ if (strptr->data.font < fontcount) {
+ somebet = fonts[strptr->data.font].encoding;
+ locscale = fonts[strptr->data.font].scale;
+ if (ykern == 0.0)
+ natscale = locscale;
+ }
+ break;
+ case TEXT_STRING:
+ textptr = strptr->data.string;
+
+ /* Don't write technology names in catalog mode if */
+ /* the option is enabled, so ignore when measuring */
+
+ if (((eventmode == CATALOG_MODE) && !xobjs.showtech)
+ || ((eventmode == CATTEXT_MODE)
+ && (drawlabel != TOLABEL(EDITPART)))) {
+ char *nsptr = strstr(textptr, "::");
+ if (nsptr != NULL) {
+ textptr = nsptr + 2;
+ locpos += (pointertype)nsptr - (pointertype)strptr->data.string + 2;
+ }
+ }
+
+ if (somebet == NULL) break;
+
+ for (; textptr && *textptr != '\0'; textptr++) {
+ if (dostop && (locpos >= dostop)) break;
+ locpos++;
+
+ chptr = (*(somebet + *textptr));
+ xtotal += (float)(chptr->bbox.width + chptr->bbox.lowerleft.x)
+ * locscale * strscale;
+ retext.ascent = max(retext.ascent, (short)(retext.base + ykern +
+ (float)((chptr->bbox.height + chptr->bbox.lowerleft.y)
+ * locscale * strscale)));
+ retext.descent = min(retext.descent, (short)(retext.base + ykern +
+ (float)(chptr->bbox.lowerleft.y * locscale * strscale)));
+
+ if (tbreak != NULL)
+ if ((xtotal > tbreak->x) && (retext.base <= tbreak->y)) {
+ dobreak = TRUE;
+ break;
+ }
+ lasttotal = xtotal;
+ lastpos = locpos;
+ }
+ break;
+ }
+ if (strptr->type != TEXT_STRING) locpos++;
+ if (dostop && (locpos >= dostop)) break;
+ if (dobreak) break;
+ }
+ if (tabstops != NULL) free(tabstops);
+
+ /* special case: return character position in retext.width */
+ if (tbreak != NULL) {
+ int slen = stringlength(drawlabel->string, True, localinst);
+ if ((tbreak->x - lasttotal) < (xtotal - tbreak->x))
+ locpos = lastpos + 1;
+ if (locpos < 1) locpos = 1;
+ else if (locpos > slen) locpos = slen;
+ retext.width = locpos;
+ return retext;
+ }
+ retext.width = max(retext.width, xtotal);
+ retext.maxwidth = max(retext.maxwidth, xtotal);
+ return retext;
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove all RETURN directives following a MARGINSTOP. Automatically */
+/* generated line breaks are identified by an nonzero "flags" field. */
+/*----------------------------------------------------------------------*/
+
+void RemoveMarginNewlines(labelptr settext, objinstptr localinst)
+{
+ stringpart *strptr, *nextptr;
+ int strpos = 0;
+
+ for (strptr = settext->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+ switch (strptr->type) {
+ case RETURN:
+ if (strptr->data.flags != 0) {
+ // Remove (without merge)
+ strptr = deletestring0(strptr, &settext->string, localinst, FALSE);
+ if (strpos <= areawin->textpos) areawin->textpos--;
+ }
+ strpos++;
+ break;
+
+ case TEXT_STRING:
+ if (strptr->data.string)
+ strpos += strlen(strptr->data.string);
+ break;
+
+ default:
+ strpos++;
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Analyze a text label and insert RETURN directives as necessary to */
+/* keep the text within the width limit set by MARGIN. Break up text */
+/* at word boundaries where necessary. This routine is run only when */
+/* (1) editing a text label or loading one from a file, and (2) the */
+/* text label both contains a MARGIN directive and exceeds the margin */
+/* width, as determined by CheckMarginStop(). */
+/*----------------------------------------------------------------------*/
+
+void InsertMarginNewlines(labelptr settext, objinstptr localinst)
+{
+ stringpart *strptr, *lastseg = NULL;
+ int margin = 0;
+ int strpos = 0, locpos, tmplen, slen, savelen;
+ TextExtents tmpext;
+
+ /* 1) Find the position of the margin stop. Track position */
+ /* in string a la findstringpart(), as we need to pass this */
+ /* to ULength() */
+
+ for (strptr = settext->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+ switch (strptr->type) {
+ case MARGINSTOP:
+ margin = strptr->data.width;
+ strpos++;
+ break;
+
+ case TEXT_STRING:
+ if (strptr->data.string)
+ strpos += strlen(strptr->data.string);
+ break;
+
+ default:
+ strpos++;
+ break;
+ }
+ if (margin > 0) break;
+ }
+ if (margin == 0) return; // Should not happen. . .
+ lastseg = strptr;
+
+ /* 2) Compute the drawn string length at each word break. When a */
+ /* word overruns the margin, place a line break in front of it. */
+
+ while (1) {
+ strptr = findstringpart(strpos, &locpos, settext->string, localinst);
+ if (strptr == NULL) break;
+ else if (strptr->type == TEXT_STRING) {
+ slen = strlen(strptr->data.string);
+ /* Ignore trailing spaces */
+ while ((slen > 0) && (*(strptr->data.string + slen - 1) == ' ')) slen--;
+ tmpext = ULength(settext, localinst, strpos + slen, NULL);
+ if (tmpext.width > margin) {
+ savelen = 0;
+ while ((slen > 0) && (tmpext.width > margin)) {
+ while ((slen > 0) && (*(strptr->data.string + slen - 1) != ' ')) slen--;
+ while ((slen > 0) && (*(strptr->data.string + slen - 1) == ' ')) {
+ slen--;
+ savelen = slen;
+ }
+ tmpext = ULength(settext, localinst, strpos + slen - 1, NULL);
+ }
+ /* Take the first space, in case we have a single word so long that */
+ /* it exceeds the margin by itself. */
+ if (savelen > slen) slen = savelen;
+ if (slen > 0) {
+ // Split string at word separation before the margin.
+
+ while ((slen > 0) && (*(strptr->data.string + slen) == ' ')) slen++;
+ strptr = splitstring(strpos + slen, &settext->string, localinst);
+ strptr = nextstringpart(strptr, localinst);
+ }
+
+ // Insert a carriage return, if the previous segment was not
+ // already one.
+ if (slen > 0 || (lastseg->type != RETURN)) {
+ strptr = makesegment(&settext->string, strptr);
+ strptr->type = RETURN;
+ strptr->data.flags = 1; /* Mark as auto-generated line wrap */
+ strpos += slen;
+ if (areawin->textpos > strpos) areawin->textpos++;
+ }
+ else
+ strpos += strlen(strptr->data.string);
+ }
+ else
+ strpos += strlen(strptr->data.string);
+ }
+ else if (strptr->type == MARGINSTOP) {
+ // Allows multiple margin stops in the same text block
+ margin = strptr->data.width;
+ strpos++;
+ }
+ else
+ strpos++;
+
+ lastseg = strptr;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Check a string for presence of a MARGINSTOP directive. If it has */
+/* one, check if ULength exceeds the margin. If so, remove all Return */
+/* directives after the MARGINSTOP, and re-insert them such that the */
+/* text stays within the margin. */
+/*----------------------------------------------------------------------*/
+
+void CheckMarginStop(labelptr settext, objinstptr localinst, Boolean force)
+{
+ stringpart *strptr;
+ int margin = 0;
+ TextExtents tmpext;
+
+ for (strptr = settext->string; strptr != NULL;
+ strptr = nextstringpart(strptr, localinst)) {
+ switch (strptr->type) {
+ case MARGINSTOP:
+ margin = strptr->data.width;
+ break;
+ }
+ if (margin > 0) break;
+ }
+ if (margin > 0) {
+ tmpext = ULength(settext, localinst, 0, NULL);
+ if ((force == TRUE) || (tmpext.maxwidth > margin)) {
+ RemoveMarginNewlines(settext, localinst);
+ InsertMarginNewlines(settext, localinst);
+ }
+ }
+ else {
+ // In case the Margin Stop directive just got deleted. . .
+ RemoveMarginNewlines(settext, localinst);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* low-level routines for drawing and erasing labels */
+/*----------------------------------------------------------------------*/
+
+void undrawtextsimple(labelptr settext)
+{
+ SetFunction(dpy, areawin->gc, GXcopy);
+ XTopSetForeground(BACKGROUND);
+ UDrawString(settext, DOFORALL, areawin->topinstance);
+}
+
+/*----------------------------------------------------------------------*/
+
+void redrawtextsimple(labelptr settext)
+{
+ UDrawString(settext, settext->color, areawin->topinstance);
+}
+
+/*----------------------------------------------------------------------*/
+/* Redraw all labels in the current object which contain the same */
+/* parameter(s) as the indicated label. */
+/* (It's easier not to bother to check for the same parameter, as there */
+/* are typically so few parameters in an object that the extra compute */
+/* and draw time is negligible.) */
+/* */
+/* Function pointer (undrawtextsimple or redrawtextsimple) indicates */
+/* which function to call on this text label. */
+/*----------------------------------------------------------------------*/
+
+void drawtextandupdate(labelptr curlabel, void (*function)(labelptr))
+{
+ genericptr *pgen;
+ labelptr slab;
+
+ for (pgen = topobject->plist; pgen < topobject->plist + topobject->parts;
+ pgen++) {
+ if (IS_LABEL(*pgen)) {
+ slab = TOLABEL(pgen);
+ if (slab == curlabel) continue;
+ if (hasparameter(slab))
+ function(slab);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Wrapper functions for drawtextandupdate() */
+/*----------------------------------------------------------------------*/
+
+void undrawtext(labelptr curlabel)
+{
+ undrawtextsimple(curlabel);
+
+ if (hasparameter(curlabel))
+ drawtextandupdate(curlabel, undrawtextsimple);
+}
+
+/*----------------------------------------------------------------------*/
+
+void redrawtext(labelptr curlabel)
+{
+ redrawtextsimple(curlabel);
+
+ if (hasparameter(curlabel))
+ drawtextandupdate(curlabel, redrawtextsimple);
+}
+
+/*----------------------------------------------------------------------*/
+/* Draw the catalog of font characters */
+/*----------------------------------------------------------------------*/
+
+void composefontlib(short cfont)
+{
+ /* genericptr *pgen; (jdk) */
+ objinstptr *drawinst;
+ objectptr *curlib, libobj, nullobj;
+ objectptr directory = xobjs.libtop[FONTLIB]->thisobject;
+ short visobjects, i, qdel;
+ polyptr *drawbox;
+ pointlist pointptr;
+
+ reset(directory, NORMAL);
+
+ /* Create a pointer to the font library */
+
+ curlib = xobjs.fontlib.library;
+
+ /* Find the number of non-null characters. Do this by assuming */
+ /* that all fonts encode nullchar at position zero. */
+
+ visobjects = 0;
+ nullobj = fonts[cfont].encoding[0];
+ for(i = 1; i < 256; i++)
+ if (fonts[cfont].encoding[i] != nullobj) visobjects++;
+
+ /* add the box and gridlines */
+
+ visobjects += 34;
+
+ /* generate the list of object instances */
+
+ directory->plist = (genericptr *) realloc(directory->plist, visobjects
+ * sizeof(genericptr));
+ directory->parts = 0;
+
+ /* 0.5 is the default vscale; 16 is no. characters per line */
+ del = min(areawin->width, areawin->height) / (0.5 * 16);
+ qdel = del >> 2;
+
+ for (i = 0; i < 256; i++) {
+
+ if ((libobj = fonts[cfont].encoding[i]) == nullobj) continue;
+
+ NEW_OBJINST(drawinst, directory);
+ instancedefaults(*drawinst, libobj,
+ (i % 16) * del + qdel, /* X position */
+ -(i / 16) * del + qdel); /* Y position */
+ drawinst = (objinstptr *)directory->plist + directory->parts - 1;
+ (*drawinst)->color = DEFAULTCOLOR;
+ }
+
+ /* separate characters with gridlines (17 vert., 17 horiz.) */
+
+ for (i = 0; i < 34; i++) {
+ NEW_POLY(drawbox, directory);
+ polydefaults(*drawbox, 2, 0, 0);
+
+ (*drawbox)->color = SNAPCOLOR; /* default red */
+ (*drawbox)->style = UNCLOSED;
+ (*drawbox)->width = 1.0;
+
+ if (i < 17) {
+ pointptr = (*drawbox)->points;
+ pointptr->x = i * del;
+ pointptr->y = 0;
+ pointptr = (*drawbox)->points + 1;
+ pointptr->x = i * del;
+ pointptr->y = -16 * del;
+ }
+ else {
+ pointptr = (*drawbox)->points;
+ pointptr->x = 0;
+ pointptr->y = (17 - i) * del;
+ pointptr = (*drawbox)->points + 1;
+ pointptr->x = 16 * del;
+ pointptr->y = (17 - i) * del;
+ }
+ }
+
+ /* Set the bounding box for this display. */
+ /* This is just the bounds of the grid built above, so there's no */
+ /* need to call any of the bounding box calculation routines. */
+
+ directory->bbox.lowerleft.x = 0;
+ directory->bbox.lowerleft.y = pointptr->y;
+ directory->bbox.width = pointptr->x;
+ directory->bbox.height = pointptr->x;
+
+ xobjs.libtop[FONTLIB]->bbox.lowerleft.x = 0;
+ xobjs.libtop[FONTLIB]->bbox.lowerleft.y = pointptr->y;
+ xobjs.libtop[FONTLIB]->bbox.width = pointptr->x;
+ xobjs.libtop[FONTLIB]->bbox.height = pointptr->x;
+
+ centerview(xobjs.libtop[FONTLIB]);
+}
+
+/*------------------------------------------------------*/
+/* ButtonPress handler during font catalog viewing mode */
+/*------------------------------------------------------*/
+
+void fontcat_op(int op, int x, int y)
+{
+ short chx, chy;
+ u_long rch = 0;
+
+ if (op != XCF_Cancel) {
+
+ window_to_user(x, y, &areawin->save);
+
+ chy = -areawin->save.y / del + 1;
+ chx = areawin->save.x / del;
+
+ chx = min(15, chx);
+ chy = min(15, chy);
+
+ rch = (u_long)(chy * 16 + chx);
+ }
+
+ catreturn();
+
+ if (rch != 0)
+ labeltext(rch, NULL);
+}
+
+/*-------------------------------------------------------------------------*/
diff --git a/tkSimple.c b/tkSimple.c
new file mode 100644
index 0000000..1cf0d13
--- /dev/null
+++ b/tkSimple.c
@@ -0,0 +1,524 @@
+/*
+ *-----------------------------------------------------------------------
+ * tkSimple.c --
+ *
+ * Implementation of a Very simple window which relies on C code for
+ * almost all of its event handlers.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#ifdef TCL_WRAPPER
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tk.h>
+/*
+#include <tkInt.h>
+#include <tkIntDecls.h> not portable! (jdk)
+ this trick seems very broken on my machine so:
+declare this thing here, and hope the linker can resolve it
+*/
+EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, CONST char * string));
+
+/* Backwards compatibility to tk8.3 and earlier */
+#if TK_MAJOR_VERSION == 8
+ #if TK_MINOR_VERSION <= 3
+ #define Tk_SetClassProcs(a,b,c) TkSetClassProcs(a,b,c)
+ #endif
+#endif
+
+#ifndef CONST84
+#define CONST84
+#endif
+
+/*
+ * A data structure of the following type is kept for each
+ * simple that currently exists for this process:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the simple. NULL
+ * means that the window has been destroyed
+ * but the data structures haven't yet been
+ * cleaned up. */
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. Used
+ * to delete widget command. */
+ Tcl_Command widgetCmd; /* Token for simple's widget command. */
+ char *className; /* Class name for widget (from configuration
+ * option). Malloc-ed. */
+ int width; /* Width to request for window. <= 0 means
+ * don't request any size. */
+ int height; /* Height to request for window. <= 0 means
+ * don't request any size. */
+ XColor *background; /* background pixel used by XClearArea */
+ char *useThis; /* If the window is embedded, this points to
+ * the name of the window in which it is
+ * embedded (malloc'ed). For non-embedded
+ * windows this is NULL. */
+ char *exitProc; /* Callback procedure upon window deletion. */
+ char *commandProc; /* Callback procedure for commands sent to the window */
+ char *mydata; /* This space for hire. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} Simple;
+
+/*
+ * Flag bits for simples:
+ *
+ * GOT_FOCUS: non-zero means this widget currently has the input focus.
+ */
+
+#define GOT_FOCUS 1
+
+static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_COLOR, "-background", "background", "Background",
+ "White", Tk_Offset(Simple, background), 0},
+ {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {TK_CONFIG_PIXELS, "-height", "height", "Height",
+ "0", Tk_Offset(Simple, height), 0},
+ {TK_CONFIG_PIXELS, "-width", "width", "Width",
+ "0", Tk_Offset(Simple, width), 0},
+ {TK_CONFIG_STRING, "-use", "use", "Use",
+ "", Tk_Offset(Simple, useThis), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_STRING, "-exitproc", "exitproc", "ExitProc",
+ "", Tk_Offset(Simple, exitProc), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_STRING, "-commandproc", "commandproc", "CommandProc",
+ "", Tk_Offset(Simple, commandProc), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_STRING, "-data", "data", "Data",
+ "", Tk_Offset(Simple, mydata), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, 0}
+};
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int ConfigureSimple _ANSI_ARGS_((Tcl_Interp *interp,
+ Simple *simplePtr, int objc, Tcl_Obj *CONST objv[],
+ int flags));
+static void DestroySimple _ANSI_ARGS_((char *memPtr));
+static void SimpleCmdDeletedProc _ANSI_ARGS_((
+ ClientData clientData));
+static void SimpleEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static int SimpleWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SimpleObjCmd --
+ *
+ * This procedure is invoked to process the "simple"
+ * Tcl command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation. These procedures are just wrappers;
+ * they call ButtonCreate to do all of the real work.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_SimpleObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Main window associated with
+ * interpreter. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ Tk_Window tkwin = (Tk_Window) clientData;
+ Simple *simplePtr;
+ Tk_Window new;
+ char *arg, *useOption;
+ int i, c; /* , depth; (jdk) */
+ size_t length;
+ unsigned int mask;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Pre-process the argument list. Scan through it to find any
+ * "-use" option, or the "-main" option. If the "-main" option
+ * is selected, then the application will exit if this window
+ * is deleted.
+ */
+
+ useOption = NULL;
+ for (i = 2; i < objc; i += 2) {
+ arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
+ if (length < 2) {
+ continue;
+ }
+ c = arg[1];
+ if ((c == 'u') && (strncmp(arg, "-use", length) == 0)) {
+ useOption = Tcl_GetString(objv[i+1]);
+ }
+ }
+
+ /*
+ * Create the window, and deal with the special option -use.
+ */
+
+ if (tkwin != NULL) {
+ new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
+ NULL);
+ }
+ if (new == NULL) {
+ goto error;
+ }
+ Tk_SetClass(new, "Simple");
+ if (useOption == NULL) {
+ useOption = (char *)Tk_GetOption(new, "use", "Use");
+ }
+ if (useOption != NULL) {
+ if (TkpUseWindow(interp, new, useOption) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ /*
+ * Create the widget record, process configuration options, and
+ * create event handlers. Then fill in a few additional fields
+ * in the widget record from the special options.
+ */
+
+ simplePtr = (Simple *) ckalloc(sizeof(Simple));
+ simplePtr->tkwin = new;
+ simplePtr->display = Tk_Display(new);
+ simplePtr->interp = interp;
+ simplePtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(new), SimpleWidgetObjCmd,
+ (ClientData) simplePtr, SimpleCmdDeletedProc);
+ simplePtr->className = NULL;
+ simplePtr->width = 0;
+ simplePtr->height = 0;
+ simplePtr->background = NULL;
+ simplePtr->useThis = NULL;
+ simplePtr->exitProc = NULL;
+ simplePtr->commandProc = NULL;
+ simplePtr->flags = 0;
+ simplePtr->mydata = NULL;
+
+ /*
+ * Store backreference to simple widget in window structure.
+ */
+ Tk_SetClassProcs(new, NULL, (ClientData) simplePtr);
+
+ /* We only handle focus and structure events, and even that might change. */
+ mask = StructureNotifyMask|FocusChangeMask|NoEventMask;
+ Tk_CreateEventHandler(new, mask, SimpleEventProc, (ClientData) simplePtr);
+
+ if (ConfigureSimple(interp, simplePtr, objc-2, objv+2, 0) != TCL_OK) {
+ goto error;
+ }
+ Tcl_SetResult(interp, Tk_PathName(new), TCL_STATIC);
+ return TCL_OK;
+
+ error:
+ if (new != NULL) {
+ Tk_DestroyWindow(new);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SimpleWidgetObjCmd --
+ *
+ * This procedure is invoked to process the Tcl command
+ * that corresponds to a simple widget. See the user
+ * documentation for details on what it does. If the
+ * "-commandProc" option has been set for the window,
+ * then any unknown command (neither "cget" nor "configure")
+ * will execute the command procedure first, then attempt
+ * to execute the remainder of the command as an independent
+ * Tcl command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SimpleWidgetObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Information about simple widget. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ static char *simpleOptions[] = {
+ "cget", "configure", (char *) NULL
+ };
+ enum options {
+ SIMPLE_CGET, SIMPLE_CONFIGURE
+ };
+ register Simple *simplePtr = (Simple *) clientData;
+ int result = TCL_OK, index;
+ size_t length;
+ int c, i;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1],
+ (CONST84 char **)simpleOptions, "option", 0,
+ &index) != TCL_OK) {
+ if (simplePtr->commandProc != NULL) {
+ Tcl_ResetResult(simplePtr->interp);
+ if (Tcl_EvalEx(simplePtr->interp, simplePtr->commandProc, -1, 0)
+ != TCL_OK)
+ return TCL_ERROR;
+ else
+ return Tcl_EvalObjv(simplePtr->interp, --objc, ++objv, TCL_EVAL_DIRECT);
+ }
+ else
+ return TCL_ERROR;
+ }
+ Tcl_Preserve((ClientData) simplePtr);
+ switch ((enum options) index) {
+ case SIMPLE_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ goto done;
+ }
+ result = Tk_ConfigureValue(interp, simplePtr->tkwin, configSpecs,
+ (char *) simplePtr, Tcl_GetString(objv[2]), 0);
+ break;
+ }
+ case SIMPLE_CONFIGURE: {
+ if (objc == 2) {
+ result = Tk_ConfigureInfo(interp, simplePtr->tkwin, configSpecs,
+ (char *) simplePtr, (char *) NULL, 0);
+ } else if (objc == 3) {
+ result = Tk_ConfigureInfo(interp, simplePtr->tkwin, configSpecs,
+ (char *) simplePtr, Tcl_GetString(objv[2]), 0);
+ } else {
+ for (i = 2; i < objc; i++) {
+ char *arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
+ if (length < 2) {
+ continue;
+ }
+ c = arg[1];
+ if ((c == 'u') && (strncmp(arg, "-use", length) == 0)) {
+ Tcl_AppendResult(interp, "can't modify ", arg,
+ " option after widget is created", (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ }
+ result = ConfigureSimple(interp, simplePtr, objc-2, objv+2,
+ TK_CONFIG_ARGV_ONLY);
+ }
+ break;
+ }
+ }
+
+ done:
+ Tcl_Release((ClientData) simplePtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroySimple --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
+ * to clean up the internal structure of a simple at a safe time
+ * (when no-one is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the simple is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroySimple(memPtr)
+ char *memPtr; /* Info about simple widget. */
+{
+ register Simple *simplePtr = (Simple *) memPtr;
+
+ Tk_FreeOptions(configSpecs, (char *) simplePtr, simplePtr->display,
+ TK_CONFIG_USER_BIT);
+ if (simplePtr->exitProc != NULL) {
+ /* Call the exit procedure */
+ Tcl_EvalEx(simplePtr->interp, simplePtr->exitProc, -1, 0);
+ }
+ ckfree((char *) simplePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSimple --
+ *
+ * This procedure is called to process an objv/objc list, plus
+ * the Tk option database, in order to configure (or
+ * reconfigure) a simple widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is
+ * returned, then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font,
+ * etc. get set for simplePtr; old resources get freed, if there
+ * were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSimple(interp, simplePtr, objc, objv, flags)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ register Simple *simplePtr; /* Information about widget; may or may
+ * not already have values for some fields. */
+ int objc; /* Number of valid entries in objv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
+ int flags; /* Flags to pass to Tk_ConfigureWidget. */
+{
+ /* char *oldMenuName; (jdk) */
+
+ if (Tk_ConfigureWidget(interp, simplePtr->tkwin, configSpecs,
+ objc, (CONST84 char **) objv, (char *) simplePtr,
+ flags | TK_CONFIG_OBJS) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if ((simplePtr->width > 0) || (simplePtr->height > 0)) {
+ Tk_GeometryRequest(simplePtr->tkwin, simplePtr->width,
+ simplePtr->height);
+ }
+
+ if (simplePtr->background != NULL) {
+ Tk_SetWindowBackground(simplePtr->tkwin, simplePtr->background->pixel);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SimpleEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher on
+ * structure changes to a simple. For simples with 3D
+ * borders, this procedure is also invoked for exposures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get
+ * cleaned up. When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SimpleEventProc(clientData, eventPtr)
+ ClientData clientData; /* Information about window. */
+ register XEvent *eventPtr; /* Information about event. */
+{
+ register Simple *simplePtr = (Simple *) clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ if (simplePtr->tkwin != NULL) {
+
+ /*
+ * If this window is a container, then this event could be
+ * coming from the embedded application, in which case
+ * Tk_DestroyWindow hasn't been called yet. When Tk_DestroyWindow
+ * is called later, then another destroy event will be generated.
+ * We need to be sure we ignore the second event, since the simple
+ * could be gone by then. To do so, delete the event handler
+ * explicitly (normally it's done implicitly by Tk_DestroyWindow).
+ */
+
+ Tk_DeleteEventHandler(simplePtr->tkwin,
+ StructureNotifyMask | FocusChangeMask,
+ SimpleEventProc, (ClientData) simplePtr);
+ simplePtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(simplePtr->interp, simplePtr->widgetCmd);
+ }
+ Tcl_EventuallyFree((ClientData) simplePtr, DestroySimple);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ simplePtr->flags |= GOT_FOCUS;
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ simplePtr->flags &= ~GOT_FOCUS;
+ }
+ }
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SimpleCmdDeletedProc --
+ *
+ * This procedure is invoked when a widget command is deleted. If
+ * the widget isn't already in the process of being destroyed,
+ * this command destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SimpleCmdDeletedProc(clientData)
+ ClientData clientData; /* Pointer to widget record for widget. */
+{
+ Simple *simplePtr = (Simple *) clientData;
+ Tk_Window tkwin = simplePtr->tkwin;
+
+ /*
+ * This procedure could be invoked either because the window was
+ * destroyed and the command was then deleted (in which case tkwin
+ * is NULL) or because the command was deleted, and then this procedure
+ * destroys the widget.
+ */
+
+ if (tkwin != NULL) {
+ simplePtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+#endif /* TCL_WRAPPER */
diff --git a/tkwin32.h b/tkwin32.h
new file mode 100644
index 0000000..b9fe6a8
--- /dev/null
+++ b/tkwin32.h
@@ -0,0 +1,39 @@
+#ifndef __TKWIN32_H__
+
+#include <windows.h>
+struct direct {
+ char *d_name;
+};
+typedef struct {
+ HANDLE hnd;
+ WIN32_FIND_DATA fd;
+ int dirty;
+ struct direct d;
+} DIR;
+DIR* opendir(const char*);
+struct direct* readdir(DIR*);
+void closedir(DIR*);
+
+typedef short Dimension;
+typedef Bool Boolean;
+typedef unsigned long Pixel;
+typedef void* caddr_t;
+#define TRUE 1
+#define FALSE 0
+typedef void* XtAppContext;
+typedef struct {
+ unsigned int size;
+ XPointer addr;
+} XrmValue, *XrmValuePtr;
+#define snprintf _snprintf
+#define pipe _pipe
+#define unlink _unlink
+#define putenv _putenv
+#define vsnprintf _vsnprintf
+#define XDefineCursor XDefineCursor_TkW32
+#define XLookupColor XLookupColor_TkW32
+#define XQueryColors XQueryColors_TkW32
+
+extern XFontStruct* XLoadQueryFont(Display *dpy, char *fontname);
+
+#endif
diff --git a/tool_bar.h b/tool_bar.h
new file mode 100644
index 0000000..fe30a1d
--- /dev/null
+++ b/tool_bar.h
@@ -0,0 +1,39 @@
+/* Include all of the XPM files */
+
+#ifdef HAVE_XPM
+
+#ifndef XC_WIN32
+#include <X11/xpm.h>
+#endif
+
+#include "lib/pixmaps/a.xpm"
+#include "lib/pixmaps/b.xpm"
+#include "lib/pixmaps/bd.xpm"
+#include "lib/pixmaps/ccw.xpm"
+#include "lib/pixmaps/co.xpm"
+#include "lib/pixmaps/cp.xpm"
+#include "lib/pixmaps/cw.xpm"
+#include "lib/pixmaps/d2.xpm"
+#include "lib/pixmaps/e.xpm"
+#include "lib/pixmaps/fi.xpm"
+#include "lib/pixmaps/fx.xpm"
+#include "lib/pixmaps/pz.xpm"
+#include "lib/pixmaps/li.xpm"
+#include "lib/pixmaps/mk.xpm"
+#include "lib/pixmaps/mv.xpm"
+#include "lib/pixmaps/po2.xpm"
+#include "lib/pixmaps/pu2.xpm"
+#include "lib/pixmaps/i.xpm"
+#include "lib/pixmaps/s.xpm"
+#include "lib/pixmaps/t.xpm"
+#include "lib/pixmaps/uj.xpm"
+#include "lib/pixmaps/fy.xpm"
+#include "lib/pixmaps/yp.xpm"
+#include "lib/pixmaps/z4.xpm"
+#include "lib/pixmaps/z5.xpm"
+#include "lib/pixmaps/pl.xpm"
+#include "lib/pixmaps/pm.xpm"
+#include "lib/pixmaps/pn.xpm"
+#include "lib/pixmaps/w.xpm"
+
+#endif
diff --git a/undo.c b/undo.c
new file mode 100644
index 0000000..e21eb1c
--- /dev/null
+++ b/undo.c
@@ -0,0 +1,1744 @@
+/*----------------------------------------------------------------------*/
+/* undo.c */
+/* */
+/* The comprehensive "undo" and "redo" command handler */
+/* */
+/* Copyright (c) 2004 Tim Edwards, Open Circuit Design, Inc., and */
+/* MultiGiG, Inc. */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 1/29/04 */
+/*----------------------------------------------------------------------*/
+
+#define MODE_UNDO (u_char)0
+#define MODE_REDO (u_char)1
+
+#define MAX_UNDO_EVENTS 100
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Local structure definitions for holding undo information */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ float angle1;
+ float angle2;
+ short radius;
+ short yaxis;
+ XPoint position;
+} arcinfo;
+
+/* Smaller data structure used when saving paths in the undo stacks. */
+/* We don't need the rendering data from points[]. */
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed;
+ u_short style;
+ float width;
+ XPoint ctrl[4];
+} splineinfo;
+
+typedef struct {
+ int number;
+ pointlist points;
+} pathinfo;
+
+typedef struct editelem {
+ genericptr element; /* element being edited */
+ union {
+ stringpart *string; /* original contents of string, for label */
+ pointlist points; /* original polygon */
+ arcinfo *arcspecs; /* original arc values */
+ pathinfo *pathspecs; /* original parts of a path */
+ XPoint instpos; /* original position, for an object instance */
+ } save;
+} editelement;
+
+typedef struct {
+ genericptr element; /* element modified */
+ float scale; /* old scale value */
+} scaleinfo;
+
+u_char undo_collect = (u_char)0;
+
+/*----------------------------------------------------------------------*/
+/* Externally declared variables */
+/*----------------------------------------------------------------------*/
+
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+
+/*----------------------------------------------------------------------*/
+/* Attempt to set the window. If the window exists, set it as current */
+/* and return TRUE. Otherwise, return FALSE. This prevents the undo */
+/* mechanism from crashing if we close a window and then try to undo */
+/* events that were created relative to it. */
+/*----------------------------------------------------------------------*/
+
+Boolean setwindow(XCWindowData *trywindow)
+{
+ XCWindowData *chkwin;
+
+ for (chkwin = xobjs.windowlist; chkwin != NULL; chkwin = chkwin->next) {
+ if (chkwin == trywindow) {
+ areawin = trywindow;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*----------------------------------------------------------------------*/
+/* remember_selection --- */
+/* */
+/* Copy a selection list into a "uselection" record. The uselection */
+/* record maintains the order of the elements as well as pointers to */
+/* each element, so the original element ordering can be recovered. */
+/*----------------------------------------------------------------------*/
+
+uselection *remember_selection(objinstptr topinst, short *slist, int number)
+{
+ int i, idx;
+ uselection *newlist;
+
+ newlist = (uselection *)malloc(sizeof(uselection));
+ if (number > 0) {
+ newlist->element = (genericptr *)malloc(number * sizeof(genericptr));
+ newlist->idx = (short *)malloc(number * sizeof(short));
+ }
+ else {
+ newlist->element = NULL;
+ newlist->idx = NULL;
+ }
+ newlist->number = number;
+ for (i = 0; i < number; i++) {
+ idx = *(slist + i);
+ *(newlist->element + i) = *(topinst->thisobject->plist + idx);
+ *(newlist->idx + i) = idx;
+ }
+ return newlist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a selection list in areawin from the saved uselection */
+/* record. */
+/*----------------------------------------------------------------------*/
+
+short *regen_selection(objinstptr thisinst, uselection *srec)
+{
+ int i, j, k;
+ genericptr egen;
+ objectptr thisobj = thisinst->thisobject;
+ Boolean reorder = False;
+ short *slist;
+
+ if (srec->number > 0)
+ slist = (short *)malloc(srec->number * sizeof(short));
+
+ k = 0;
+ for (i = 0; i < srec->number; i++) {
+
+ /* Use the element address, not the selection order. */
+ egen = *(srec->element + i);
+ if (egen == *(thisobj->plist + *(srec->idx + i)))
+ j = *(srec->idx + i);
+ else {
+ reorder = True;
+ for (j = 0; j < thisobj->parts; j++) {
+ if (egen == *(thisobj->plist + j))
+ break;
+ }
+ }
+ if (j < thisobj->parts) {
+ *(slist + k) = j;
+ k++;
+ }
+ else
+ Fprintf(stderr, "Error: element %p in select list but not object\n",
+ egen);
+ }
+
+ /* If the selection order is different from the order in the object, */
+ /* then rearrange the object's list to match the selection order. */
+
+ if (reorder) {
+ /* (to be done) */
+ }
+
+ if (k == 0) {
+ if (srec->number > 0) free(slist);
+ return NULL;
+ }
+ else
+ return slist;
+}
+
+/*----------------------------------------------------------------------*/
+/* Use the selection list in the undo record to reorder parts in the */
+/* object's part list. Invert the selection list and return it. */
+/*----------------------------------------------------------------------*/
+
+void reorder_selection(Undoptr thisrecord)
+{
+ short *slist, *newlist, snum, i;
+ genericptr *pgen, *plist, egen;
+ objinstptr thisinst = thisrecord->thisinst;
+ objectptr thisobj = thisinst->thisobject;
+
+ snum = (short)thisrecord->idata;
+ slist = (short *)thisrecord->undodata;
+ plist = (genericptr *)malloc(snum * sizeof(genericptr));
+ newlist = (short *)malloc(snum * sizeof(short));
+
+ i = 0;
+ for (pgen = plist; pgen < plist + snum; pgen++) {
+ egen = *(thisobj->plist + i);
+ *(plist + *(slist + i)) = egen;
+ i++;
+ }
+ i = 0;
+ for (pgen = plist; pgen < plist + snum; pgen++) {
+ *(thisobj->plist + i) = *pgen;
+ *(newlist + *(slist + i)) = i;
+ i++;
+ }
+ free(plist);
+ free(thisrecord->undodata);
+ thisrecord->undodata = (char *)newlist;
+}
+
+/*----------------------------------------------------------------------*/
+/* free_editelement --- */
+/* */
+/* Free memory allocated to an undo record edit element structure. */
+/*----------------------------------------------------------------------*/
+
+void free_editelement(Undoptr thisrecord)
+{
+ editelement *erec;
+ pathinfo *ppi;
+
+ erec = (editelement *)thisrecord->undodata;
+ switch (erec->element->type) {
+ case LABEL:
+ freelabel(erec->save.string);
+ break;
+ case POLYGON: case SPLINE:
+ free(erec->save.points);
+ break;
+ case ARC:
+ free(erec->save.arcspecs);
+ break;
+ case PATH:
+ for (ppi = erec->save.pathspecs; ppi < erec->save.pathspecs +
+ thisrecord->idata; ppi++)
+ free(ppi->points);
+ free(erec->save.pathspecs);
+ break;
+ }
+ free(erec);
+}
+
+/*----------------------------------------------------------------------*/
+/* free_selection --- */
+/* */
+/* Free memory allocated to an undo record selection list. */
+/*----------------------------------------------------------------------*/
+
+void free_selection(uselection *selrec)
+{
+ if (selrec->number > 0) {
+ free(selrec->element);
+ free(selrec->idx);
+ }
+ free(selrec);
+}
+
+/*----------------------------------------------------------------------*/
+/* get_original_string --- */
+/* */
+/* Find the original version of the given label. */
+/*----------------------------------------------------------------------*/
+
+stringpart *get_original_string(labelptr thislab)
+{
+ Undoptr chkrecord, thisrecord;
+ editelement *erec;
+ labelptr elab;
+
+ thisrecord = xobjs.undostack;
+ if (thisrecord == NULL) return NULL;
+
+ for (chkrecord = thisrecord; chkrecord != NULL; chkrecord = chkrecord->next) {
+ switch (chkrecord->type) {
+ case XCF_Edit:
+ erec = (editelement *)(chkrecord->undodata);
+ elab = (labelptr)(erec->element);
+ if (elab != thislab) return NULL;
+ return erec->save.string;
+
+ default:
+ return NULL;
+ }
+ }
+ return NULL; /* yes, this can be reached, if thisrecord->next == NULL */
+}
+
+/*----------------------------------------------------------------------*/
+/* select_previous --- */
+/* */
+/* Set the selection to what was previously selected in the undo list. */
+/* Return 0 on success, -1 if no previous selection was found. */
+/*----------------------------------------------------------------------*/
+
+int select_previous(Undoptr thisrecord)
+{
+ Undoptr chkrecord;
+ uselection *srec;
+
+ clearselects_noundo();
+ for (chkrecord = thisrecord->next; chkrecord != NULL; chkrecord = chkrecord->next) {
+
+ /* Selections may cross page changes, but only if in the same series */
+ if ((chkrecord->thisinst != thisrecord->thisinst) &&
+ (chkrecord->idx != thisrecord->idx))
+ break;
+
+ switch (chkrecord->type) {
+ case XCF_Delete: case XCF_Pop: case XCF_Push:
+ /* Delete/Push/Pop records imply a canceled selection */
+ return 0;
+ case XCF_Copy:
+ case XCF_Select:
+ srec = (uselection *)chkrecord->undodata;
+ areawin->selectlist = regen_selection(thisrecord->thisinst, srec);
+ areawin->selects = (areawin->selectlist) ? srec->number : 0;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/* This is similar to the above routine, but we just return a pointer */
+/* to the index list in the uselection record. This lets the undelete */
+/* function restore the original ordering of parts that were deleted. */
+/*----------------------------------------------------------------------*/
+
+short *recover_selectlist(Undoptr thisrecord)
+{
+ Undoptr chkrecord;
+ uselection *srec;
+
+ for (chkrecord = thisrecord->next; chkrecord != NULL; chkrecord = chkrecord->next) {
+
+ /* Selections may cross page changes, but only if in the same series */
+ if ((chkrecord->thisinst != thisrecord->thisinst) &&
+ (chkrecord->idx != thisrecord->idx))
+ break;
+
+ switch (chkrecord->type) {
+ case XCF_Delete: case XCF_Pop: case XCF_Push:
+ /* Delete/Push/Pop records imply a canceled selection */
+ return NULL;
+ case XCF_Copy:
+ /* Copy is the same as Select, but the copied objects are */
+ /* always at the end of the element list. Returning NULL */
+ /* is the same as declaring that elements should be */
+ /* appended to the end of the object's element list. */
+ return NULL;
+ case XCF_Select:
+ srec = (uselection *)chkrecord->undodata;
+ return srec->idx;
+ }
+ }
+ return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* Put element "thiselem" back into object "thisobj". This is only */
+/* used in the case where the elements were previously at the end of */
+/* the object's element list. */
+/*----------------------------------------------------------------------*/
+
+void undelete_one_element(objinstptr thisinst, genericptr thiselem)
+{
+ objectptr thisobj = thisinst->thisobject;
+
+ PLIST_INCR(thisobj);
+ *(thisobj->plist + thisobj->parts) = thiselem;
+ thisobj->parts++;
+}
+
+/*----------------------------------------------------------------------*/
+/* register_for_undo --- */
+/* */
+/* Register an event with the undo handler. This creates a record */
+/* based on the type, which is one of the XCF_* bindings (see */
+/* xcircuit.h for the list). This is a variable-argument routine, */
+/* with the arguments dependent on the command. */
+/* */
+/* thisinst is the instance of the object in which the event occurred */
+/* and is registered for every event type. */
+/* */
+/* "mode" is UNDO_MORE if one or more undo records are expected to */
+/* follow in a series, or UNDO_DONE if this completes a series, or is */
+/* as single undo event. The command-line command "undo series start" */
+/* forces all events to be UNDO_MORE until "undo series end" is */
+/* issued. */
+/*----------------------------------------------------------------------*/
+
+void register_for_undo(u_int type, u_char mode, objinstptr thisinst, ...)
+{
+ va_list args;
+ int drawmode, nval, oval, *idata, snum, deltax, deltay, dir, i;
+ short *slist;
+ objectptr delobj;
+ objinstptr newinst;
+ Undoptr newrecord;
+ uselection *srec;
+ editelement *erec;
+ scaleinfo *escale;
+ genericptr egen;
+ XPoint *fpoint;
+ double scale;
+
+ /* Do not register new events while running undo/redo actions! */
+ if (eventmode == UNDO_MODE) return;
+
+ /* This action invalidates everything in the "redo" stack, so flush it */
+ flush_redo_stack();
+
+ /* Create the new record and push it onto the stack */
+ newrecord = (Undoptr)malloc(sizeof(Undostack));
+ newrecord->next = xobjs.undostack;
+ newrecord->last = NULL;
+ newrecord->type = type;
+ newrecord->thisinst = thisinst;
+ newrecord->window = areawin;
+ newrecord->undodata = (char *)NULL;
+ newrecord->idata = 0;
+
+ if (xobjs.undostack) {
+ xobjs.undostack->last = newrecord;
+ if (xobjs.undostack->idx < 0) {
+ xobjs.undostack->idx = -xobjs.undostack->idx;
+ newrecord->idx = xobjs.undostack->idx;
+ }
+ else
+ newrecord->idx = xobjs.undostack->idx + 1;
+ }
+ else
+ newrecord->idx = 1;
+
+ if (mode == UNDO_MORE || undo_collect > (u_char)0)
+ newrecord->idx = -newrecord->idx;
+
+ xobjs.undostack = newrecord;
+
+ va_start(args, thisinst);
+
+ switch(type) {
+ case XCF_Delete:
+ /* 2 args: */
+ /* delobj = pointer to object containing deleted entries */
+ /* drawmode = true if elements should be erased */
+ delobj = va_arg(args, objectptr);
+ drawmode = va_arg(args, int);
+ newrecord->undodata = (char *)delobj;
+ newrecord->idata = drawmode;
+ break;
+
+ case XCF_Select_Save:
+ /* 1 arg: */
+ /* newobj = pointer to instance of new object */
+ newinst = va_arg(args, objinstptr);
+ newrecord->undodata = (char *)newinst;
+ break;
+
+ case XCF_Page:
+ /* 2 args: */
+ /* oval = original integer value */
+ /* nval = new integer value */
+ oval = va_arg(args, int);
+ nval = va_arg(args, int);
+ idata = (int *)malloc(sizeof(int));
+ *idata = nval;
+ newrecord->undodata = (char *)idata;
+ newrecord->idata = oval;
+ break;
+
+ case XCF_Pop:
+ /* No args; instance to pop is the instance passed. */
+ break;
+
+ case XCF_Push:
+ /* 1 arg: */
+ /* newinst = object instance to push */
+ newinst = va_arg(args, objinstptr);
+ newrecord->undodata = (char *)newinst;
+ break;
+
+ case XCF_Copy:
+ case XCF_Select:
+ case XCF_Library_Pop:
+ /* 2 args: */
+ /* slist = current selection list (short *) */
+ /* snum = number of selections (int) */
+ slist = va_arg(args, short *);
+ snum = va_arg(args, int);
+ srec = remember_selection(thisinst, slist, snum);
+ newrecord->undodata = (char *)srec;
+ /* Fprintf(stdout, "Undo: registered selection or copy action\n"); */
+ break;
+
+ case XCF_Box: case XCF_Arc: case XCF_Wire: case XCF_Text:
+ case XCF_Pin_Label: case XCF_Pin_Global: case XCF_Info_Label:
+ case XCF_Spline: case XCF_Dot: case XCF_Graphic: case XCF_Join:
+ /* 1 arg: */
+ /* egen = element just created (genericptr) */
+ egen = va_arg(args, genericptr);
+ newrecord->undodata = (char *)egen;
+ break;
+
+ case XCF_Edit:
+ /* 1 arg: */
+ /* egen = element to be edited (genericptr) */
+ egen = va_arg(args, genericptr);
+
+ /* Create a copy of the element to save */
+ erec = (editelement *)malloc(sizeof(editelement));
+ erec->element = egen;
+ switch(egen->type) {
+ case LABEL:
+ erec->save.string =
+ stringcopyall(((labelptr)egen)->string,
+ areawin->topinstance);
+ newrecord->idata = ((labelptr)egen)->justify;
+ break;
+ case POLYGON:
+ newrecord->idata = ((polyptr)egen)->number;
+ erec->save.points = copypoints(((polyptr)egen)->points,
+ newrecord->idata);
+ break;
+ case SPLINE:
+ erec->save.points =
+ copypoints((pointlist)((splineptr)egen)->ctrl, 4);
+ break;
+ case OBJINST:
+ erec->save.instpos = ((objinstptr)egen)->position;
+ break;
+ case ARC:
+ erec->save.arcspecs = (arcinfo *)malloc(sizeof(arcinfo));
+ erec->save.arcspecs->angle1 = ((arcptr)egen)->angle1;
+ erec->save.arcspecs->angle2 = ((arcptr)egen)->angle2;
+ erec->save.arcspecs->radius = ((arcptr)egen)->radius;
+ erec->save.arcspecs->yaxis = ((arcptr)egen)->yaxis;
+ erec->save.arcspecs->position = ((arcptr)egen)->position;
+ break;
+ case PATH:
+ newrecord->idata = ((pathptr)egen)->parts; /* not needed? */
+ erec->save.pathspecs = (pathinfo *)malloc(newrecord->idata *
+ sizeof(pathinfo));
+ for (i = 0; i < newrecord->idata; i++) {
+ pathinfo *ppi = erec->save.pathspecs + i;
+ genericptr *pgen = ((pathptr)egen)->plist + i;
+ switch (ELEMENTTYPE(*pgen)) {
+ case POLYGON:
+ ppi->number = (TOPOLY(pgen))->number;
+ ppi->points = copypoints((TOPOLY(pgen))->points,
+ ppi->number);
+ break;
+ case SPLINE:
+ ppi->number = 4;
+ ppi->points = copypoints((pointlist)
+ (TOSPLINE(pgen))->ctrl, 4);
+ break;
+ }
+ }
+ break;
+ }
+ newrecord->undodata = (char *)erec;
+ break;
+
+ case XCF_ChangeStyle:
+ case XCF_Justify:
+ case XCF_Color:
+ /* 2 args: */
+ /* egen = element that was changed (with new value) */
+ /* oval = old style value */
+ egen = va_arg(args, genericptr);
+ oval = va_arg(args, int);
+ newrecord->undodata = (char *)egen;
+ newrecord->idata = oval;
+ break;
+
+ case XCF_Rescale:
+ /* 2 args: */
+ /* egen = element that was changed (with new value) */
+ /* ofloat = old float value */
+
+ egen = va_arg(args, genericptr);
+ scale = va_arg(args, double); /* warning! only takes "double"! */
+
+ escale = (scaleinfo *)malloc(sizeof(scaleinfo));
+ escale->element = egen;
+ escale->scale = (float)scale;
+
+ newrecord->undodata = (char *)escale;
+ break;
+
+ case XCF_Flip_X: case XCF_Flip_Y:
+ /* 1 arg: */
+ /* fpoint = point of flip (XPoint *) */
+ fpoint = va_arg(args, XPoint *);
+ newrecord->undodata = (char *)malloc(sizeof(XPoint));
+ ((XPoint *)newrecord->undodata)->x = fpoint->x;
+ ((XPoint *)newrecord->undodata)->y = fpoint->y;
+ break;
+
+ case XCF_Rotate:
+ /* 2 args: */
+ /* fpoint = point of flip (XPoint *) */
+ /* dir = direction and amound of rotation (int) */
+ fpoint = va_arg(args, XPoint *);
+ dir = va_arg(args, int);
+ newrecord->undodata = (char *)malloc(sizeof(XPoint));
+ ((XPoint *)newrecord->undodata)->x = fpoint->x;
+ ((XPoint *)newrecord->undodata)->y = fpoint->y;
+ newrecord->idata = dir;
+ break;
+
+ case XCF_Move:
+ /* 2 args: */
+ /* deltax = change in x position (int) */
+ /* deltay = change in y position (int) */
+ deltax = va_arg(args, int);
+ deltay = va_arg(args, int);
+ newrecord->undodata = (char *)malloc(sizeof(XPoint));
+ ((XPoint *)newrecord->undodata)->x = deltax;
+ ((XPoint *)newrecord->undodata)->y = deltay;
+ /* Fprintf(stdout, "Undo: registered move of delta (%d, %d)\n",
+ deltax, deltay); */
+ break;
+
+ case XCF_Reorder:
+ /* 2 args: */
+ /* slist = "before" order of elements */
+ /* snum = number of elements in list (= # parts) */
+ slist = va_arg(args, short *);
+ snum = va_arg(args, int);
+ newrecord->undodata = (char *)slist;
+ newrecord->idata = snum;
+ }
+
+ va_end(args);
+}
+
+/*----------------------------------------------------------------------*/
+/* undo_one_action --- */
+/* Play undo record back one in the stack. */
+/*----------------------------------------------------------------------*/
+
+short undo_one_action()
+{
+ Undoptr thisrecord; /* , chkrecord; (jdk) */
+ objectptr thisobj;
+ objinstptr thisinst;
+ uselection *srec;
+ editelement *erec;
+ scaleinfo *escale;
+ short *slist;
+ XPoint *delta, position;
+ int i, j, snum;
+ int savemode;
+ float fnum;
+ genericptr egen;
+ labelptr thislabel;
+ pathptr thispath;
+ polyptr thispoly;
+ arcptr thisarc;
+ splineptr thisspline;
+ graphicptr thisgraphic;
+ Boolean need_redraw;
+ XCWindowData *savewindow = areawin;
+
+ /* Undo the recorded action and shift the undo record pointer. */
+
+ thisrecord = xobjs.undostack;
+ if (thisrecord == NULL) {
+ Fprintf(stderr, "Nothing to undo!\n");
+ return 0;
+ }
+
+ xobjs.undostack = thisrecord->next;
+ xobjs.redostack = thisrecord;
+
+ /* Set window, if event occurred in a different window */
+ if (setwindow(thisrecord->window) == FALSE) {
+ Wprintf("Error: Undo event in nonexistant window! Flushing stack.\n");
+ flush_undo_stack();
+ return 0;
+ }
+
+ /* Setting eventmode to UNDO_MODE prevents register_for_undo() from */
+ /* being called again while executing the event. */
+
+ savemode = eventmode;
+ eventmode = UNDO_MODE;
+
+ /* type-dependent part */
+
+ switch(thisrecord->type) {
+ case XCF_Delete:
+ unselect_all();
+ thisobj = (objectptr)thisrecord->undodata;
+ areawin->selects = thisobj->parts;
+ areawin->selectlist = xc_undelete(thisrecord->thisinst,
+ thisobj, (short)thisrecord->idata,
+ recover_selectlist(thisrecord));
+ srec = remember_selection(thisrecord->thisinst, areawin->selectlist,
+ areawin->selects);
+ thisrecord->undodata = (char *)srec;
+ draw_all_selected();
+ break;
+
+ /* To be finished: Needs to remove the object & instance from */
+ /* the library and library page. Should keep the empty object */
+ /* around so we have the name. */
+
+ case XCF_Select_Save:
+ unselect_all();
+ thisinst = (objinstptr)thisrecord->undodata;
+ thisobj = thisinst->thisobject;
+
+ /* Remove the instance */
+ i = thisrecord->thisinst->thisobject->parts - 1;
+ if ((genericptr)thisinst != *(thisrecord->thisinst->thisobject->plist + i)) {
+ Fprintf(stderr, "Error: No such element!\n");
+ thisrecord->undodata = NULL;
+ break;
+ }
+ else {
+ delete_one_element(thisrecord->thisinst, (genericptr)thisinst);
+ }
+
+ /* Put back all the parts */
+ areawin->selects = thisobj->parts;
+ areawin->selectlist = xc_undelete(thisrecord->thisinst,
+ thisobj, (short)thisrecord->idata,
+ recover_selectlist(thisrecord));
+ srec = remember_selection(thisrecord->thisinst, areawin->selectlist,
+ areawin->selects);
+ thisrecord->undodata = (char *)srec;
+ draw_all_selected();
+ break;
+
+ case XCF_Push:
+ popobject(areawin->area, 0, NULL);
+ break;
+
+ case XCF_Pop:
+ pushobject((objinstptr)thisrecord->thisinst);
+ break;
+
+ case XCF_Page:
+ newpage(thisrecord->idata);
+ break;
+
+ case XCF_Justify:
+ thislabel = (labelptr)(thisrecord->undodata);
+ snum = thisrecord->idata;
+ thisrecord->idata = thislabel->justify;
+ thislabel->justify = snum;
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Select:
+
+ /* If there was a previous selection in the undo list, */
+ /* revert to it. */
+
+ need_redraw = (areawin->selects > 0) ? True : False;
+ select_previous(thisrecord);
+ if (need_redraw)
+ drawarea(areawin->area, NULL, NULL);
+ else
+ draw_all_selected();
+ break;
+
+ case XCF_Box: case XCF_Arc: case XCF_Wire: case XCF_Text:
+ case XCF_Pin_Label: case XCF_Pin_Global: case XCF_Info_Label:
+ case XCF_Spline: case XCF_Dot: case XCF_Graphic: case XCF_Join:
+ egen = (genericptr)thisrecord->undodata;
+ i = thisrecord->thisinst->thisobject->parts - 1;
+ if (egen != *(thisrecord->thisinst->thisobject->plist + i)) {
+ Fprintf(stderr, "Error: No such element!\n");
+ thisrecord->undodata = NULL;
+ }
+ else {
+ delete_one_element(thisrecord->thisinst, egen);
+ drawarea(areawin->area, NULL, NULL);
+ }
+ break;
+
+ case XCF_Edit:
+ erec = (editelement *)thisrecord->undodata;
+ switch (erec->element->type) {
+ case LABEL: {
+ stringpart *tmpstr;
+ int tmpjust;
+ labelptr elab = (labelptr)(erec->element);
+ undrawtext(elab);
+ tmpstr = elab->string;
+ tmpjust = (int)elab->justify;
+ elab->string = stringcopyback(erec->save.string,
+ thisrecord->thisinst);
+ elab->justify = (short)thisrecord->idata;
+ erec->save.string = tmpstr;
+ thisrecord->idata = tmpjust;
+ resolveparams(thisrecord->thisinst);
+ redrawtext(elab);
+ } break;
+ case ARC: {
+ arcinfo tmpinfo;
+ arcptr earc = (arcptr)(erec->element);
+ tmpinfo.angle1 = earc->angle1;
+ tmpinfo.angle2 = earc->angle2;
+ tmpinfo.radius = earc->radius;
+ tmpinfo.yaxis = earc->yaxis;
+ tmpinfo.position = earc->position;
+ earc->angle1 = erec->save.arcspecs->angle1;
+ earc->angle2 = erec->save.arcspecs->angle2;
+ earc->radius = erec->save.arcspecs->radius;
+ earc->yaxis = erec->save.arcspecs->yaxis;
+ earc->position = erec->save.arcspecs->position;
+ *(erec->save.arcspecs) = tmpinfo;
+ calcarc(earc);
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case OBJINST: {
+ XPoint tmppt;
+ objinstptr einst = (objinstptr)(erec->element);
+ // Swap instance and saved positions.
+ tmppt = einst->position;
+ einst->position = erec->save.instpos;
+ erec->save.instpos = tmppt;
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case POLYGON: {
+ pointlist tmppts;
+ int tmpnum;
+ polyptr epoly = (polyptr)(erec->element);
+ tmppts = epoly->points;
+ tmpnum = epoly->number;
+ epoly->points = erec->save.points;
+ epoly->number = thisrecord->idata;
+ erec->save.points = tmppts;
+ thisrecord->idata = tmpnum;
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case SPLINE: {
+ pointlist tmppts;
+ splineptr espline = (splineptr)(erec->element);
+ tmppts = copypoints((pointlist)espline->ctrl, 4);
+ for (i = 0; i < 4; i++)
+ espline->ctrl[i] = *(erec->save.points + i);
+ free(erec->save.points);
+ erec->save.points = tmppts;
+ calcspline(espline);
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case PATH: {
+ pointlist tmppts;
+ int tmpnum;
+ polyptr epoly;
+ splineptr espline;
+ pathptr epath = (pathptr)(erec->element);
+ for (i = 0; i < epath->parts; i++) {
+ genericptr ggen = *(epath->plist + i);
+ switch (ELEMENTTYPE(ggen)) {
+ case POLYGON:
+ epoly = (polyptr)ggen;
+ tmppts = epoly->points;
+ tmpnum = epoly->number;
+ epoly->points = (erec->save.pathspecs + i)->points;
+ epoly->number = (erec->save.pathspecs + i)->number;
+ (erec->save.pathspecs + i)->points = tmppts;
+ (erec->save.pathspecs + i)->number = tmpnum;
+ break;
+ case SPLINE:
+ espline = (splineptr)ggen;
+ tmppts = copypoints((pointlist)espline->ctrl, 4);
+ for (j = 0; j < 4; j++)
+ espline->ctrl[j] = *((erec->save.pathspecs + i)->points + j);
+ free((erec->save.pathspecs + i)->points);
+ (erec->save.pathspecs + i)->points = tmppts;
+ calcspline(espline);
+ break;
+ }
+ }
+ drawarea(areawin->area, NULL, NULL);
+ }
+ }
+ break;
+
+ case XCF_Library_Pop:
+ srec = (uselection *)thisrecord->undodata;
+ slist = regen_selection(thisrecord->thisinst, srec);
+ thisobj = delete_element(thisrecord->thisinst, slist,
+ srec->number, DRAW);
+ free(slist);
+ thisrecord->undodata = (char *)thisobj;
+ break;
+
+ case XCF_Copy:
+ clearselects_noundo();
+ srec = (uselection *)thisrecord->undodata;
+ slist = regen_selection(thisrecord->thisinst, srec);
+ thisobj = delete_element(thisrecord->thisinst, slist,
+ srec->number, DRAW);
+ free(slist);
+ thisrecord->undodata = (char *)thisobj;
+
+ /* Revert selection to previously selected */
+ select_previous(thisrecord);
+ drawarea(areawin->area, NULL, NULL);
+ draw_all_selected();
+ break;
+
+ case XCF_ChangeStyle:
+ /* Style changes */
+ egen = (genericptr)thisrecord->undodata;
+ snum = thisrecord->idata;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)(thisrecord->undodata);
+ thisrecord->idata = thispath->style;
+ thispath->style = snum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)(thisrecord->undodata);
+ thisrecord->idata = thispoly->style;
+ thispoly->style = snum;
+ break;
+ case ARC:
+ thisarc = (arcptr)(thisrecord->undodata);
+ thisrecord->idata = thisarc->style;
+ thisarc->style = snum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)(thisrecord->undodata);
+ thisrecord->idata = thisspline->style;
+ thisspline->style = snum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Color:
+ /* Color changes */
+ egen = (genericptr)thisrecord->undodata;
+ snum = thisrecord->idata;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)(thisrecord->undodata);
+ thisrecord->idata = thispath->color;
+ thispath->color = snum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)(thisrecord->undodata);
+ thisrecord->idata = thispoly->color;
+ thispoly->color = snum;
+ break;
+ case ARC:
+ thisarc = (arcptr)(thisrecord->undodata);
+ thisrecord->idata = thisarc->color;
+ thisarc->color = snum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)(thisrecord->undodata);
+ thisrecord->idata = thisspline->color;
+ thisspline->color = snum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Rescale:
+ escale = (scaleinfo *)thisrecord->undodata;
+ egen = escale->element;
+ fnum = escale->scale;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)egen;
+ escale->scale = thispath->width;
+ thispath->width = fnum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)egen;
+ escale->scale = thispoly->width;
+ thispoly->width = fnum;
+ break;
+ case ARC:
+ thisarc = (arcptr)egen;
+ escale->scale = thisarc->width;
+ thisarc->width = fnum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)egen;
+ escale->scale = thisspline->width;
+ thisspline->width = fnum;
+ break;
+ case OBJINST:
+ thisinst = (objinstptr)egen;
+ escale->scale = thisinst->scale;
+ thisinst->scale = fnum;
+ break;
+ case GRAPHIC:
+ thisgraphic = (graphicptr)egen;
+ escale->scale = thisgraphic->scale;
+ thisgraphic->scale = fnum;
+ thisgraphic->valid = FALSE;
+ break;
+ case LABEL:
+ thislabel = (labelptr)egen;
+ escale->scale = thislabel->scale;
+ thislabel->scale = fnum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Flip_X:
+ position = *((XPoint *)thisrecord->undodata);
+ elementflip(&position);
+ break;
+
+ case XCF_Flip_Y:
+ position = *((XPoint *)thisrecord->undodata);
+ elementvflip(&position);
+ break;
+
+ case XCF_Rotate:
+ position = *((XPoint *)thisrecord->undodata);
+ elementrotate(-thisrecord->idata, &position);
+ break;
+
+ case XCF_Move:
+ delta = (XPoint *)thisrecord->undodata;
+ select_connected_pins();
+ placeselects(-(delta->x), -(delta->y), NULL);
+ reset_cycles();
+ drawarea(areawin->area, NULL, NULL);
+ draw_all_selected();
+ break;
+
+ case XCF_Reorder:
+ reorder_selection(thisrecord);
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ default:
+ Fprintf(stderr, "Undo not implemented for this action!\n");
+ break;
+ }
+
+ /* Does this need to be set on a per-event-type basis? */
+ switch (savemode) {
+ case CATALOG_MODE:
+ case CATTEXT_MODE:
+ eventmode = CATALOG_MODE;
+ break;
+ default:
+ eventmode = NORMAL_MODE;
+ break;
+ }
+
+ /* Diagnostic, to check if all multiple-event undo series are resolved */
+ if (thisrecord->idx < 0) {
+ Fprintf(stderr, "Warning: Unfinished undo series in stack!\n");
+ thisrecord->idx = -thisrecord->idx;
+ }
+ areawin = savewindow;
+ return thisrecord->idx;
+}
+
+/*----------------------------------------------------------------------*/
+/* undo_finish_series --- */
+/* Complete a possibly incomplete undo series by forcing the */
+/* topmost entry to have a positive index. */
+/* Note that for "undo series start|end" to work, undo_collect */
+/* must be set to 0 prior to calling undo_finish_series(). */
+/*----------------------------------------------------------------------*/
+
+void undo_finish_series()
+{
+ if (undo_collect == (u_char)0)
+ if (xobjs.undostack && xobjs.undostack->idx < 0)
+ xobjs.undostack->idx = -xobjs.undostack->idx;
+}
+
+/*----------------------------------------------------------------------*/
+/* undo_action --- */
+/* Play undo record back to the completion of a series. */
+/*----------------------------------------------------------------------*/
+
+void undo_action()
+{
+ short idx;
+
+ // Cannot undo while in the middle of an undo series. Failsafe.
+ if (undo_collect != (u_char)0) return;
+
+ idx = undo_one_action();
+ while (xobjs.undostack && xobjs.undostack->idx == idx)
+ undo_one_action();
+}
+
+/*----------------------------------------------------------------------*/
+/* redo_one_action --- */
+/* Play undo record forward one in the stack. */
+/*----------------------------------------------------------------------*/
+
+short redo_one_action()
+{
+ Undoptr thisrecord;
+ objectptr thisobj;
+ genericptr egen;
+ short *slist;
+ XPoint *delta, position;
+ uselection *srec;
+ editelement *erec;
+ scaleinfo *escale;
+ int i, j, snum;
+ int savemode;
+ float fnum;
+ labelptr thislabel;
+ arcptr thisarc;
+ pathptr thispath;
+ splineptr thisspline;
+ polyptr thispoly;
+ graphicptr thisgraphic;
+ objinstptr thisinst;
+ XCWindowData *savewindow = areawin;
+
+ /* Undo the recorded action and shift the undo record pointer. */
+
+ thisrecord = xobjs.redostack;
+ if (thisrecord == NULL) {
+ Fprintf(stderr, "Nothing to redo!\n");
+ return 0;
+ }
+ xobjs.undostack = thisrecord;
+ xobjs.redostack = thisrecord->last;
+
+ /* Set window, if event occurred in a different window */
+ if (setwindow(thisrecord->window) == FALSE) {
+ Wprintf("Error: Undo event in nonexistant window! Flushing stack.\n");
+ flush_undo_stack();
+ return 0;
+ }
+
+ savemode = eventmode;
+ eventmode = UNDO_MODE;
+
+ /* type-dependent part */
+
+ switch(thisrecord->type) {
+ case XCF_Delete:
+ srec = (uselection *)thisrecord->undodata;
+ slist = regen_selection(thisrecord->thisinst, srec);
+ thisobj = delete_element(thisrecord->thisinst, slist,
+ srec->number, DRAW);
+ free(slist);
+ thisrecord->undodata = (char *)thisobj;
+ thisrecord->idata = (int)DRAW;
+ unselect_all();
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ /* Unfinished! */
+ case XCF_Select_Save:
+ srec = (uselection *)thisrecord->undodata;
+ slist = regen_selection(thisrecord->thisinst, srec);
+ break;
+
+ case XCF_Page:
+ newpage(*((int *)thisrecord->undodata));
+ break;
+
+ case XCF_Justify:
+ thislabel = (labelptr)(thisrecord->undodata);
+ snum = thisrecord->idata;
+ thisrecord->idata = thislabel->justify;
+ thislabel->justify = snum;
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Pop:
+ popobject(areawin->area, 0, NULL);
+ break;
+
+ case XCF_Push:
+ pushobject((objinstptr)thisrecord->undodata);
+ break;
+
+ case XCF_Select:
+ unselect_all();
+ srec = (uselection *)thisrecord->undodata;
+ areawin->selectlist = regen_selection(thisrecord->thisinst, srec);
+ areawin->selects = (areawin->selectlist) ? srec->number : 0;
+ draw_all_selected();
+ break;
+
+ case XCF_Library_Pop:
+ thisobj = (objectptr)thisrecord->undodata;
+ if (thisobj != NULL) {
+ unselect_all();
+ snum = thisobj->parts;
+ slist = xc_undelete(thisrecord->thisinst, thisobj, DRAW, NULL);
+ thisrecord->undodata = (char *)remember_selection(thisrecord->thisinst,
+ slist, snum);
+ free(slist);
+ }
+ break;
+
+ case XCF_Copy:
+ thisobj = (objectptr)thisrecord->undodata;
+ if (thisobj != NULL) {
+ unselect_all();
+ areawin->selects = thisobj->parts;
+ areawin->selectlist = xc_undelete(thisrecord->thisinst, thisobj, DRAW,
+ NULL);
+ thisrecord->undodata = (char *)remember_selection(thisrecord->thisinst,
+ areawin->selectlist, areawin->selects);
+ draw_all_selected();
+ }
+ break;
+
+ case XCF_Box: case XCF_Arc: case XCF_Wire: case XCF_Text:
+ case XCF_Pin_Label: case XCF_Pin_Global: case XCF_Info_Label:
+ case XCF_Spline: case XCF_Dot: case XCF_Graphic: case XCF_Join:
+ egen = (genericptr)thisrecord->undodata;
+ undelete_one_element(thisrecord->thisinst, egen);
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Edit:
+ erec = (editelement *)thisrecord->undodata;
+ switch (erec->element->type) {
+ case LABEL: {
+ stringpart *tmpstr;
+ int tmpjust;
+ labelptr elab = (labelptr)(erec->element);
+ undrawtext(elab);
+ tmpstr = elab->string;
+ tmpjust = (int)elab->justify;
+ elab->string = stringcopyback(erec->save.string,
+ thisrecord->thisinst);
+ elab->justify = (short)thisrecord->idata;
+ erec->save.string = tmpstr;
+ thisrecord->idata = tmpjust;
+ resolveparams(thisrecord->thisinst);
+ redrawtext(elab);
+ } break;
+ case OBJINST: {
+ XPoint tmppt;
+ objinstptr einst = (objinstptr)(erec->element);
+ // Swap instance position and saved position
+ tmppt = einst->position;
+ einst->position = erec->save.instpos;
+ erec->save.instpos = tmppt;
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case ARC: {
+ arcinfo tmpinfo;
+ arcptr earc = (arcptr)(erec->element);
+ tmpinfo.angle1 = earc->angle1;
+ tmpinfo.angle2 = earc->angle2;
+ tmpinfo.radius = earc->radius;
+ tmpinfo.yaxis = earc->yaxis;
+ tmpinfo.position = earc->position;
+ earc->angle1 = erec->save.arcspecs->angle1;
+ earc->angle2 = erec->save.arcspecs->angle2;
+ earc->radius = erec->save.arcspecs->radius;
+ earc->yaxis = erec->save.arcspecs->yaxis;
+ earc->position = erec->save.arcspecs->position;
+ *(erec->save.arcspecs) = tmpinfo;
+ calcarc(earc);
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case POLYGON: {
+ pointlist tmppts;
+ int tmpnum;
+ polyptr epoly = (polyptr)(erec->element);
+ tmppts = epoly->points;
+ tmpnum = epoly->number;
+ epoly->points = erec->save.points;
+ epoly->number = thisrecord->idata;
+ erec->save.points = tmppts;
+ thisrecord->idata = tmpnum;
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case SPLINE: {
+ pointlist tmppts;
+ splineptr espline = (splineptr)(erec->element);
+ tmppts = copypoints((pointlist)espline->ctrl, 4);
+ for (i = 0; i < 4; i++)
+ espline->ctrl[i] = *(erec->save.points + i);
+ free(erec->save.points);
+ erec->save.points = tmppts;
+ calcspline(espline);
+ drawarea(areawin->area, NULL, NULL);
+ } break;
+ case PATH: {
+ pointlist tmppts;
+ int tmpnum;
+ polyptr epoly;
+ splineptr espline;
+ pathptr epath = (pathptr)(erec->element);
+ for (i = 0; i < epath->parts; i++) {
+ genericptr ggen = *(epath->plist + i);
+ switch (ELEMENTTYPE(ggen)) {
+ case POLYGON:
+ epoly = (polyptr)ggen;
+ tmppts = epoly->points;
+ tmpnum = epoly->number;
+ epoly->points = (erec->save.pathspecs + i)->points;
+ epoly->number = (erec->save.pathspecs + i)->number;
+ (erec->save.pathspecs + i)->points = tmppts;
+ (erec->save.pathspecs + i)->number = tmpnum;
+ break;
+ case SPLINE:
+ espline = (splineptr)ggen;
+ tmppts = copypoints((pointlist)espline->ctrl, 4);
+ for (j = 0; j < 4; j++)
+ espline->ctrl[j] = *((erec->save.pathspecs + i)->points + j);
+ free((erec->save.pathspecs + i)->points);
+ (erec->save.pathspecs + i)->points = tmppts;
+ calcspline(espline);
+ break;
+ }
+ }
+ drawarea(areawin->area, NULL, NULL);
+ }
+ }
+ break;
+
+ case XCF_Flip_X:
+ position = *((XPoint *)thisrecord->undodata);
+ elementflip(&position);
+ break;
+
+ case XCF_Flip_Y:
+ position = *((XPoint *)thisrecord->undodata);
+ elementvflip(&position);
+ break;
+
+ case XCF_ChangeStyle:
+ /* Style changes */
+ egen = (genericptr)thisrecord->undodata;
+ snum = thisrecord->idata;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)(thisrecord->undodata);
+ thisrecord->idata = thispath->style;
+ thispath->style = snum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)(thisrecord->undodata);
+ thisrecord->idata = thispoly->style;
+ thispoly->style = snum;
+ break;
+ case ARC:
+ thisarc = (arcptr)(thisrecord->undodata);
+ thisrecord->idata = thisarc->style;
+ thisarc->style = snum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)(thisrecord->undodata);
+ thisrecord->idata = thisspline->style;
+ thisspline->style = snum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Color:
+ /* Color changes */
+ egen = (genericptr)thisrecord->undodata;
+ snum = thisrecord->idata;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)(thisrecord->undodata);
+ thisrecord->idata = thispath->color;
+ thispath->color = snum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)(thisrecord->undodata);
+ thisrecord->idata = thispoly->color;
+ thispoly->color = snum;
+ break;
+ case ARC:
+ thisarc = (arcptr)(thisrecord->undodata);
+ thisrecord->idata = thisarc->color;
+ thisarc->color = snum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)(thisrecord->undodata);
+ thisrecord->idata = thisspline->color;
+ thisspline->color = snum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Rescale:
+ escale = (scaleinfo *)thisrecord->undodata;
+ egen = escale->element;
+ fnum = escale->scale;
+ switch(egen->type) {
+ case PATH:
+ thispath = (pathptr)egen;
+ escale->scale = thispath->width;
+ thispath->width = fnum;
+ break;
+ case POLYGON:
+ thispoly = (polyptr)egen;
+ escale->scale = thispoly->width;
+ thispoly->width = fnum;
+ break;
+ case ARC:
+ thisarc = (arcptr)egen;
+ escale->scale = thisarc->width;
+ thisarc->width = fnum;
+ break;
+ case SPLINE:
+ thisspline = (splineptr)egen;
+ escale->scale = thisspline->width;
+ thisspline->width = fnum;
+ break;
+ case OBJINST:
+ thisinst = (objinstptr)egen;
+ escale->scale = thisinst->scale;
+ thisinst->scale = fnum;
+ break;
+ case GRAPHIC:
+ thisgraphic = (graphicptr)egen;
+ escale->scale = thisgraphic->scale;
+ thisgraphic->scale = fnum;
+ thisgraphic->valid = FALSE;
+ break;
+ case LABEL:
+ thislabel = (labelptr)egen;
+ escale->scale = thislabel->scale;
+ thislabel->scale = fnum;
+ break;
+ }
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Rotate:
+ position = *((XPoint *)thisrecord->undodata);
+ elementrotate(thisrecord->idata, &position);
+ break;
+
+ case XCF_Move:
+ delta = (XPoint *)thisrecord->undodata;
+ select_connected_pins();
+ placeselects(delta->x, delta->y, NULL);
+ reset_cycles();
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ case XCF_Reorder:
+ reorder_selection(thisrecord);
+ drawarea(areawin->area, NULL, NULL);
+ break;
+
+ default:
+ Fprintf(stderr, "Undo not implemented for this action!\n");
+ break;
+ }
+
+ /* Does this need to be set on a per-event-type basis? */
+ switch (savemode) {
+ case CATALOG_MODE:
+ case CATTEXT_MODE:
+ eventmode = CATALOG_MODE;
+ break;
+ default:
+ eventmode = NORMAL_MODE;
+ break;
+ }
+
+ areawin = savewindow;
+
+ return thisrecord->idx;
+}
+
+/*----------------------------------------------------------------------*/
+/* redo_action --- */
+/* Play undo record forward to the completion of a series. */
+/*----------------------------------------------------------------------*/
+
+void redo_action()
+{
+ short idx;
+
+ // Cannot redo while in the middle of an undo series. Failsafe.
+ if (undo_collect != (u_char)0) return;
+
+ idx = redo_one_action();
+ while (xobjs.redostack && xobjs.redostack->idx == idx)
+ redo_one_action();
+}
+
+/*----------------------------------------------------------------------*/
+/* flush_redo_stack --- */
+/* Free all memory allocated to the redo stack due to the */
+/* insertion of a new undo record. */
+/*----------------------------------------------------------------------*/
+
+void flush_redo_stack()
+{
+ Undoptr thisrecord, nextrecord;
+
+ if (xobjs.redostack == NULL) return; /* no redo stack */
+
+ thisrecord = xobjs.redostack;
+
+ while (thisrecord != NULL) {
+ nextrecord = thisrecord->last;
+ free_redo_record(thisrecord);
+ thisrecord = nextrecord;
+ }
+ xobjs.redostack = NULL;
+
+ if (xobjs.undostack)
+ xobjs.undostack->last = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* flush_undo_stack --- */
+/* Free all memory allocated to the undo and redo stacks. */
+/*----------------------------------------------------------------------*/
+
+void flush_undo_stack()
+{
+ Undoptr thisrecord, nextrecord;
+
+ flush_redo_stack();
+
+ thisrecord = xobjs.undostack;
+
+ while (thisrecord != NULL) {
+ nextrecord = thisrecord->next;
+ free_undo_record(thisrecord);
+ thisrecord = nextrecord;
+ }
+ xobjs.undostack = NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/* free_undo_data --- */
+/* Free memory allocated to the "undodata" part of the undo */
+/* record, based on the record type. */
+/* */
+/* "mode" specifies whether this is for an "undo" or a "redo" event. */
+/* */
+/* Note that the action taken for a specific record may *NOT* be */
+/* the same for a record in the undo stack as it is for a record */
+/* in the redo stack, because the data types are changed when */
+/* moving from one record to the next. */
+/*----------------------------------------------------------------------*/
+
+void free_undo_data(Undoptr thisrecord, u_char mode)
+{
+ u_int type;
+ objectptr uobj;
+ uselection *srec;
+ editelement *erec;
+
+ type = thisrecord->type;
+ switch (type) {
+ case XCF_Delete:
+ if (mode == MODE_UNDO) {
+ uobj = (objectptr)thisrecord->undodata;
+ reset(uobj, DESTROY);
+ }
+ else { /* MODE_REDO */
+ srec = (uselection *)thisrecord->undodata;
+ free_selection(srec);
+ }
+ break;
+
+ case XCF_Box: case XCF_Arc: case XCF_Wire: case XCF_Text:
+ case XCF_Pin_Label: case XCF_Pin_Global: case XCF_Info_Label:
+ case XCF_Spline: case XCF_Dot: case XCF_Graphic: case XCF_Join:
+ /* if MODE_UNDO, the element is on the page, so don't destroy it! */
+ if (mode == MODE_REDO)
+ free(thisrecord->undodata);
+ break;
+
+ case XCF_Edit:
+ erec = (editelement *)thisrecord->undodata;
+ free_editelement(thisrecord);
+ break;
+
+ case XCF_Copy:
+ case XCF_Library_Pop:
+ if (mode == MODE_UNDO) {
+ srec = (uselection *)thisrecord->undodata;
+ free_selection(srec);
+ }
+ else { /* MODE_REDO */
+ uobj = (objectptr)thisrecord->undodata;
+ reset(uobj, DESTROY);
+ }
+ break;
+
+ case XCF_Push:
+ case XCF_ChangeStyle:
+ case XCF_Justify:
+ case XCF_Color:
+ /* Do nothing --- undodata points to a valid element */
+ break;
+
+ case XCF_Select:
+ srec = (uselection *)thisrecord->undodata;
+ free_selection(srec);
+ break;
+
+ default:
+ if (thisrecord->undodata != NULL)
+ free(thisrecord->undodata);
+ break;
+ }
+ thisrecord->undodata = NULL;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* free_undo_record --- */
+/* Free allocated memory for one record in the undo stack. */
+/*----------------------------------------------------------------------*/
+
+void free_undo_record(Undoptr thisrecord)
+{
+ /* Undoptr nextrecord, lastrecord; (jdk) */
+
+ /* Reset the master list pointers */
+
+ if (xobjs.undostack == thisrecord)
+ xobjs.undostack = thisrecord->next;
+
+ /* Relink the stack pointers */
+
+ if (thisrecord->last)
+ thisrecord->last->next = thisrecord->next;
+
+ if (thisrecord->next)
+ thisrecord->next->last = thisrecord->last;
+
+ /* Free memory allocated to the record */
+
+ free_undo_data(thisrecord, MODE_UNDO);
+ free(thisrecord);
+}
+
+/*----------------------------------------------------------------------*/
+/* free_redo_record --- */
+/* Free allocated memory for one record in the redo stack. */
+/*----------------------------------------------------------------------*/
+
+void free_redo_record(Undoptr thisrecord)
+{
+ /* Undoptr nextrecord, lastrecord; (jdk) */
+
+ /* Reset the master list pointers */
+
+ if (xobjs.redostack == thisrecord)
+ xobjs.redostack = thisrecord->last;
+
+ /* Relink the stack pointers */
+
+ if (thisrecord->next)
+ thisrecord->next->last = thisrecord->last;
+
+ if (thisrecord->last)
+ thisrecord->last->next = thisrecord->next;
+
+ /* Free memory allocated to the record */
+
+ free_undo_data(thisrecord, MODE_REDO);
+ free(thisrecord);
+}
+
+/*----------------------------------------------------------------------*/
+/* truncate_undo_stack --- */
+/* If the limit MAX_UNDO_EVENTS has been reached, discard the */
+/* last undo series on the stack (index = 1) and renumber the */
+/* others by decrementing. */
+/*----------------------------------------------------------------------*/
+
+void truncate_undo_stack()
+{
+ Undoptr thisrecord, nextrecord;
+
+ thisrecord = xobjs.undostack;
+ while (thisrecord != NULL) {
+ nextrecord = thisrecord->next;
+ if (thisrecord->idx > 1)
+ thisrecord->idx--;
+ else
+ free_undo_record(thisrecord);
+ thisrecord = nextrecord;
+ }
+}
+
+#ifndef TCL_WRAPPER
+
+/* Calls from the Xt menus (see menus.h) */
+/* These are wrappers for undo_action and redo_action */
+
+void undo_call(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ undo_action();
+}
+
+void redo_call(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ redo_action();
+}
+
+#endif
+/*----------------------------------------------------------------------*/
diff --git a/w32x11.c b/w32x11.c
new file mode 100644
index 0000000..a7d14ac
--- /dev/null
+++ b/w32x11.c
@@ -0,0 +1,421 @@
+#include <tk.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <xcircuit.h>
+
+#include <tk.h>
+#include <tkPlatDecls.h>
+
+#include <X11/cursorfont.h>
+
+extern Tcl_Interp *xcinterp;
+extern XCWindowData *areawin;
+extern char* TkKeysymToString(KeySym ks);
+
+static void unimplemented(const char *str)
+{
+ printf(">>>>>>>>> Unimplemented: %s\n", str);
+}
+
+typedef struct font_item {
+ Tk_Font tkfont;
+ Font fid;
+ struct font_item *next;
+};
+static struct font_item *font_map = NULL;
+
+static void add_tkfont(Tk_Font tkfont, Font fid)
+{
+ struct font_item *item = (struct font_item*)malloc(sizeof(struct font_item));
+
+ item->next = font_map;
+ font_map = item;
+ item->tkfont = tkfont;
+ item->fid = fid;
+}
+
+static Tk_Font get_tkfont(Font fid)
+{
+ struct font_item *item = font_map;
+
+ while (item != NULL) {
+ if (item->fid == fid)
+ return item->tkfont;
+ item = item->next;
+ }
+ fprintf(stderr, "Font not found: ID=%d\n", fid);
+ return (Tk_Font)NULL;
+}
+
+#ifndef STATIC_BUILD
+int XDrawPoint(Display *dpy, Drawable d, GC gc, int x, int y)
+{
+ HDC hdc;
+ HWND hwnd;
+
+ hwnd = Tk_GetHWND(d);
+ if (IsWindow(hwnd)) {
+ hdc = GetDC(hwnd);
+ SetPixelV(hdc, x, y, gc->foreground);
+ ReleaseDC(hwnd, hdc);
+ hdc = NULL;
+ } else {
+ /* This is pretty slow when called a lot
+ hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, hwnd);
+ SetPixelV(hdc, x, y, gc->foreground);
+ DeleteDC(hdc);
+ */
+ }
+ return 1;
+}
+#endif
+
+int XClearArea(Display *dpy, Window w, int x, int y, unsigned int width, unsigned int height, Bool exposures)
+{
+ HWND hnd;
+ RECT r;
+ HDC hdc;
+ int oldROP;
+
+ hnd = Tk_GetHWND(w);
+ hdc = GetDC(hnd);
+ oldROP = SetROP2(hdc, R2_COPYPEN);
+ GetClientRect(hnd, &r);
+ if (width != 0 || height != 0) {
+ r.left = x;
+ r.top = y;
+ r.right = x+width;
+ r.bottom = y+height;
+ FillRect(hdc, &r, (HBRUSH)(COLOR_WINDOW+1));
+ }
+ SetROP2(hdc, oldROP);
+ ReleaseDC(hnd, hdc);
+ return 1;
+}
+
+Pixmap XCreatePixmap(Display *dpy, Drawable d, unsigned int width, unsigned int height, unsigned int depth)
+{
+ return Tk_GetPixmap(dpy, d, width, height, depth);
+}
+
+int XLookupString(XKeyEvent *event, char *buf, int buflen, KeySym *keysym, XComposeStatus *status)
+{
+#if 0
+ printf("code : %04x\n", event->keycode);
+ printf("state: %04x\n", event->state);
+#endif
+ switch (event->keycode) {
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
+ *keysym = XK_KP_0 + (event->keycode - VK_NUMPAD0);
+ event->state |= ShiftMask;
+ break;
+ default:
+ *keysym = XKeycodeToKeysym(NULL, event->keycode, event->state);
+ break;
+ }
+ return 1;
+}
+
+Bool XCheckWindowEvent(Display *dpy, Window w, long event_mask, XEvent *event)
+{
+ unimplemented("XCheckWindowEvent");
+ return False;
+}
+
+int XTextWidth(XFontStruct *font, char *string, int len)
+{
+ Tk_Font tkfont = get_tkfont(font->fid);
+ return Tk_TextWidth(tkfont, string, len);
+}
+
+int XDrawString(Display *dpy, Drawable d, GC gc, int x, int y, char *string, int len)
+{
+ Tk_Font tkfont = get_tkfont(gc->font);
+ Tk_DrawChars(dpy, d, gc, tkfont, string, len, x, y);
+ return 1;
+}
+
+int XFreePixmap(Display *dpy, Pixmap pix)
+{
+ Tk_FreePixmap(dpy, pix);
+ return 1;
+}
+
+#ifndef STATIC_BUILD
+int XPutImage(Display *dpy, Drawable d, GC gc, XImage *img, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
+{
+ // unimplemented("XPutImage");
+
+ TkPutImage(NULL, 0, dpy, d, gc, img, src_x, src_y, dest_x, dest_y,
+ width, height);
+ return 1;
+}
+#endif
+
+// The following two functions may be defined as macros. . .
+
+#ifndef XSync
+int XSync(Display *dpy, Bool discard)
+{
+ unimplemented("XSync");
+ return 1;
+}
+#endif
+
+#ifndef XFlush
+int XFlush(Display *dpy)
+{
+ unimplemented("XFlush");
+ return 1;
+}
+#endif
+
+#ifndef STATIC_BUILD
+Cursor XCreateFontCursor(Display *dpy, unsigned int shape)
+{
+ Tk_Window win = Tk_MainWindow(xcinterp);
+
+ switch (shape) {
+ case XC_xterm: return (Cursor)Tk_GetCursor(xcinterp, win, "xterm");
+ case XC_watch: return (Cursor)Tk_GetCursor(xcinterp, win, "watch");
+ default: return (Cursor)NULL;
+ }
+}
+#endif
+
+void XDefineCursor_TkW32(Display *dpy, Window w, Cursor c)
+{
+ Tk_DefineCursor(Tk_IdToWindow(dpy, w), (Tk_Cursor)c);
+}
+
+static u_char reverse_byte(u_char c)
+{
+ u_char rc = 0;
+ int i;
+
+ for (i=(sizeof(char)*8-1); i>=0; i--, c>>=1)
+ rc |= (c&0x01) << i;
+ return rc;
+}
+
+static void compute_cursor_src_mask(u_char *src, u_char *mask)
+{
+ u_char pixsrc = *src, pixmask = *mask;
+ *src = ~(reverse_byte(pixmask));
+ *mask = reverse_byte(~pixsrc & pixmask);
+}
+
+typedef struct tkw32cursor {
+ struct tkcursor {
+ Tk_Cursor cursor;
+ Display *display;
+ int resourceCount;
+ int objRefCount;
+ Tcl_HashTable *otherTable;
+ Tcl_HashEntry *hashPtr;
+ Tcl_HashEntry *idHashPtr;
+ struct tkcursor *nextPtr;
+ } info;
+ HCURSOR winCursor;
+ int system;
+} w32cursor;
+
+static
+Cursor Tk_GetCursorFromData_TkW32(Tcl_Interp *interp, Tk_Window w, u_char *src, u_char *mask, int width, int height, int xhot, int yhot, Tk_Uid fg, Tk_Uid bg)
+{
+ w32cursor *wcursor;
+
+ wcursor = (w32cursor*)ckalloc(sizeof(w32cursor));
+ wcursor->info.cursor = (Tk_Cursor)wcursor;
+ wcursor->winCursor = NULL;
+ wcursor->system = 0;
+
+ wcursor->winCursor = CreateCursor(Tk_GetHINSTANCE(), xhot, yhot, width, height, src, mask);
+ if (wcursor->winCursor == NULL) {
+ ckfree((char*)wcursor);
+ return (Cursor)NULL;
+ }
+
+ return (Cursor)wcursor;
+}
+
+Cursor CreateW32Cursor(Tcl_Interp *interp, Tk_Window w, u_char *src, u_char *mask, int width, int height, int xhot, int yhot, Tk_Uid fg, Tk_Uid bg)
+{
+ u_char *new_src, *new_mask;
+ int nb = (width-1)/(8*sizeof(char))+1;
+ int nb2 = (GetSystemMetrics(SM_CXCURSOR)-1)/(8*sizeof(char))+1, height2 = GetSystemMetrics(SM_CYCURSOR);
+ int i, j, idx1 = 0, idx2 = 0;
+ Cursor cursor;
+
+ new_src = (u_char*)malloc(sizeof(char)*nb2*height2);
+ new_mask = (u_char*)malloc(sizeof(char)*nb2*height2);
+
+ for (j=0; j<height; j++) {
+ for (i=0; i<nb; i++, idx1++, idx2++) {
+ new_src[idx2] = src[idx1];
+ new_mask[idx2] = mask[idx1];
+ compute_cursor_src_mask(&new_src[idx2], &new_mask[idx2]);
+ /*printf("%02x ", new_src[idx2]);*/
+ }
+ for (i=0; i<(nb2-nb); i++, idx2++) {
+ new_src[idx2] = 0xff;
+ new_mask[idx2] = 0x00;
+ /*printf("%02x ", new_src[idx2]);*/
+ }
+ /*printf("\n");*/
+ }
+ for (j=0; j<(height2-height); j++) {
+ for (i=0; i<nb2; i++, idx2++) {
+ new_src[idx2] = 0xff;
+ new_mask[idx2] = 0x00;
+ /*printf("%02x ", new_src[idx2]);*/
+ }
+ /*printf("\n");*/
+ }
+ /*printf("\n");*/
+
+ cursor = Tk_GetCursorFromData_TkW32(interp, w, new_src, new_mask, nb2*8, height2, xhot, yhot, fg, bg);
+
+ free(new_src);
+ free(new_mask);
+
+ return cursor;
+}
+
+int XRecolorCursor(Display *dpy, Cursor cursor, XColor *foreground, XColor *background)
+{
+ unimplemented("XRecolorCursor");
+ return 1;
+}
+
+Status XAllocNamedColor(Display *dpy, Colormap cm, char* cname, XColor *screen_return, XColor *exact_return)
+{
+ XColor *c = Tk_GetColor(xcinterp, (areawin ? areawin->area : NULL), cname);
+
+ if (c != NULL) {
+ screen_return->pixel = c->pixel;
+ exact_return->pixel = c->pixel;
+ return True;
+ }
+ return False;
+}
+
+Status XLookupColor_TkW32(Display *dpy, Colormap cmap, const char *name, XColor *cvcolor, XColor *cvexact)
+{
+ if (XParseColor(dpy, cmap, name, cvcolor)) {
+ return True;
+ }
+ else {
+ return False;
+ }
+}
+
+int XQueryColors_TkW32(Display *dpy, Colormap cmap, XColor *colors, int ncolors)
+{
+ int i;
+
+ for (i=0; i<ncolors; i++) {
+ int pixel = colors[i].pixel;
+ colors[i].red = ((pixel&0x000000ff)<<8)|(pixel&0x000000ff);
+ colors[i].green = (pixel&0x0000ff00)|((pixel&0x0000ff00)>>8);
+ colors[i].blue = ((pixel&0x00ff0000)>>8)|((pixel&0x00ff0000)>>16);
+ }
+
+ return 1;
+}
+
+Bool XQueryPointer_TkW32(Display *dpy, Window w, Window *root_return, Window *child_return,
+ int *root_x, int *root_y, int *win_x, int *win_y, unsigned int *mask)
+{
+ POINT p;
+
+ GetCursorPos(&p);
+ *root_x = p.x;
+ *root_y = p.y;
+ ScreenToClient(Tk_GetHWND(w), &p);
+ *win_x = p.x;
+ *win_y = p.y;
+ *mask = 0;
+
+ return True;
+}
+
+Colormap XCopyColormapAndFree(Display *dpy, Colormap cmap)
+{
+ unimplemented("XCopyColormapAndFree");
+ return cmap;
+}
+
+char* XDisplayString(Display *dpy)
+{
+ /*printf("XDisplayString\n");*/
+ return "localhost:0.0\n";
+}
+
+
+char* XKeysymToString_TkW32(KeySym ks)
+{
+ return TkKeysymToString(ks);
+}
+
+XFontStruct* XLoadQueryFont(Display *dpy, char *fontname)
+{
+ Tk_Font tkfont;
+ Tk_FontMetrics tkfm;
+ XFontStruct *fs;
+
+ tkfont = Tk_GetFont(xcinterp, Tk_MainWindow(xcinterp), fontname);
+ if (tkfont != NULL)
+ {
+ fs = (XFontStruct*)malloc(sizeof(XFontStruct));
+ fs->fid = Tk_FontId(tkfont);
+ Tk_GetFontMetrics(tkfont, &tkfm);
+ fs->ascent = tkfm.ascent;
+ fs->descent = tkfm.descent;
+ add_tkfont(tkfont, fs->fid);
+ return fs;
+ }
+ else
+ return NULL;
+}
+
+DIR* opendir(const char *name)
+{
+ DIR *d = (DIR*)malloc(sizeof(DIR));
+ static char buffer[MAX_PATH];
+
+ strncpy(buffer, name, MAX_PATH);
+ strncat(buffer, "\\*", MAX_PATH);
+ d->hnd = FindFirstFile(buffer, &(d->fd));
+ if (d->hnd == INVALID_HANDLE_VALUE)
+ return NULL;
+ d->dirty = 1;
+ return d;
+}
+
+void closedir(DIR *d)
+{
+ free(d);
+}
+
+struct direct* readdir(DIR *d)
+{
+ if (!d->dirty)
+ {
+ if (!FindNextFile(d->hnd, &(d->fd)))
+ return NULL;
+ }
+ d->d.d_name = d->fd.cFileName;
+ d->dirty = 0;
+ return &(d->d);
+}
diff --git a/wishexe.ini b/wishexe.ini
new file mode 100644
index 0000000..34b9634
--- /dev/null
+++ b/wishexe.ini
@@ -0,0 +1,19 @@
+[Settings]
+NumFields=2
+
+[Field 1]
+Type=Label
+Text=Enter the location of the wish (Tcl/Tk) executable:
+Left=0
+Right=-1
+Top=0
+Bottom=14
+
+[Field 2]
+Type=FileRequest
+Filter=Wish executable|wish*.exe
+Left=0
+Right=-1
+Top=14
+Bottom=27
+
diff --git a/xcircexec.c b/xcircexec.c
new file mode 100644
index 0000000..36678af
--- /dev/null
+++ b/xcircexec.c
@@ -0,0 +1,80 @@
+/*----------------------------------------------------------------------*/
+/* xcircexec.c */
+/* */
+/* Written by R. Timothy Edwards for MultiGiG, Inc., September 2004 */
+/* This file mainly lifted from the main application routine for */
+/* "wish" from the Tk distribution. */
+/* */
+/* This is a compact re-write of the "wish" executable that calls */
+/* Tk_MainEx with application-specific processing. Specifically, */
+/* "wish" doesn't allow the startup script (~/.wishrc) to be renamed. */
+/* However, for xcircuit running as an extension of Tcl, we want to */
+/* source the xcircuit.tcl file instead of ~/.wishrc. So, all this */
+/* file really does is to set the Tcl variable "tcl_rcFileName" to */
+/* xcircuit.tcl, so that it will be processed as the startup script, */
+/* followed by a drop back to the Tcl interpreter command-line main */
+/* loop. */
+/* */
+/* This is a standalone executable. However, it is only called when */
+/* "-noconsole" is specified on the UNIX command-line. When the */
+/* console is used, the console is capable of sourcing the magic.tcl */
+/* script itself, and so it uses "wish" as the executable. However, */
+/* the console redirects standard input, so it prevents magic from */
+/* being used in a batch processing mode. Thus, to batch-process with */
+/* xcircuit, use "xcircuit -noc < script.tcl" or, interactively, */
+/* "xcircuit -noc << EOF" followed by commands entered from stdin */
+/* and ending with "EOF". */
+/* */
+/* The "xcircexec" method replaces the former use of "wish" with the */
+/* "xcircuit" script setting HOME to point to the directory containing */
+/* ".wishrc", a symbolic link to "xcircuit.tcl". That failed to work */
+/* on remote systems because the $HOME environment variable is also */
+/* used to find the user's .Xauthority file to authenticate the X11 */
+/* connection. */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include <tk.h>
+#include <tcl.h>
+
+/*----------------------------------------------------------------------*/
+/* Application initiation. This is exactly like the AppInit routine */
+/* for "wish", minus the cruft, but with "tcl_rcFileName" set to */
+/* "xcircuit.tcl" instead of "~/.wishrc". */
+/*----------------------------------------------------------------------*/
+
+int
+xcircuit_AppInit(interp)
+ Tcl_Interp *interp;
+{
+ if (Tcl_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (Tk_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);
+
+ /* This is where we replace the home ".wishrc" file with */
+ /* xcircuit's startup script. */
+
+ Tcl_SetVar(interp, "tcl_rcFileName", SCRIPTS_DIR "/xcircuit.tcl",
+ TCL_GLOBAL_ONLY);
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* The main procedure; replacement for "wish". */
+/*----------------------------------------------------------------------*/
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ Tk_Main(argc, argv, xcircuit_AppInit);
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
diff --git a/xcircuit-tcl.nsi b/xcircuit-tcl.nsi
new file mode 100644
index 0000000..2a51826
--- /dev/null
+++ b/xcircuit-tcl.nsi
@@ -0,0 +1,900 @@
+; Script generated by the HM NIS Edit Script Wizard.
+
+; HM NIS Edit Wizard helper defines
+!define PRODUCT_NAME "XCircuit-dev-tcl"
+!define PRODUCT_VERSION "3.7"
+!define PRODUCT_REVISION "21"
+!define PRODUCT_PUBLISHER "Tim Edwards"
+!define PRODUCT_WEB_SITE "http://opencircuitdesign.com/xcircuit/"
+!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\xcircuit-dev-win32.exe"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+
+; MUI 1.67 compatible ------
+!include "MUI.nsh"
+!include "Sections.nsh"
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+; License page
+!insertmacro MUI_PAGE_LICENSE "COPYRIGHT"
+; Components page
+!insertmacro MUI_PAGE_COMPONENTS
+Page custom WishExePage WishExeValidate
+; Directory page
+!insertmacro MUI_PAGE_DIRECTORY
+; Instfiles page
+!insertmacro MUI_PAGE_INSTFILES
+; Finish page
+!define MUI_FINISHPAGE_RUN "$INSTDIR\bin\xcircuit-win32.exe"
+!insertmacro MUI_PAGE_FINISH
+
+; Uninstaller pages
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Language files
+!insertmacro MUI_LANGUAGE "English"
+
+; MUI end ------
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION} (revision ${PRODUCT_REVISION})"
+OutFile "Setup-dev-tcl.exe"
+InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
+InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
+ShowInstDetails show
+ShowUnInstDetails show
+
+Function .onInit
+!insertmacro MUI_INSTALLOPTIONS_EXTRACT "wishexe.ini"
+FunctionEnd
+
+Section "XCircuit" SEC01
+ SetOutPath "$INSTDIR\bin"
+ SetOverwrite ifnewer
+ File "xcircuit-win32.exe"
+ CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\XCircuit.lnk" "$INSTDIR\bin\xcircuit-win32.exe"
+ CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\bin\xcircuit-win32.exe"
+ File "lib\tcl\xcircuit.bat"
+ SetOutPath "$INSTDIR\xcircuit-${PRODUCT_VERSION}"
+ File "lib\tcl\autoincr.tcl"
+ File "lib\tcl\bparams.tcl"
+ File "lib\tcl\console.tcl"
+ File "lib\tcl\files.tcl"
+ File "lib\tcl\library.tcl"
+ File "lib\tcl\mousehint.tcl"
+ File "lib\tcl\ngspice.tcl"
+ File "lib\tcl\panzoom.tcl"
+ File "lib\tcl\pcbout.tcl"
+ File "lib\tcl\xcircuit.tcl"
+ File "lib\tcl\wrapper.tcl"
+ File "lib\tcl\tkcon.tcl"
+ File "lib\tcl\sue_xc.tcl"
+ File "lib\tcl\resource.tcl"
+ File "lib\tcl\xcstartup.tcl"
+ File "lib\tcl\sinusoid.tcl"
+ File "lib\tcl\symbol.tcl"
+ File "lib\tcl\xchelp.tcl"
+ File "lib\tcl\xcircuit.dll"
+ File "xcircexec.exe"
+ File "lib\signal.lps"
+ File "lib\series74xx.lps"
+ File "lib\quadparts.lps"
+ File "lib\pcb_layout.lps"
+ File "lib\pcb.lps"
+ File "lib\musiclib.lps"
+ File "lib\lgf.lps"
+ File "lib\ic_templates.lps"
+ File "lib\generic.lps"
+ File "lib\digital.lps"
+ File "lib\avlsi.lps"
+ File "lib\asg_spice.lps"
+ File "lib\analoglib3.lps"
+ File "lib\analoglib2.lps"
+ File "lib\analog.lps"
+ File "lib\xcircps2.pro"
+ SetOutPath "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts"
+ File "lib\fonts\times_romaniso.xfe"
+ File "lib\fonts\times_romaniso5.xfe"
+ File "lib\fonts\times_romaniso5.lps"
+ File "lib\fonts\times_romaniso2.xfe"
+ File "lib\fonts\times_romaniso2.lps"
+ File "lib\fonts\times_roman.xfe"
+ File "lib\fonts\times_roman.lps"
+ File "lib\fonts\symbol.xfe"
+ File "lib\fonts\symbol.lps"
+ File "lib\fonts\myfont.xfe"
+ File "lib\fonts\myfont.lps"
+ File "lib\fonts\helveticaiso.xfe"
+ File "lib\fonts\helveticaiso5.xfe"
+ File "lib\fonts\helveticaiso5.lps"
+ File "lib\fonts\helveticaiso2.xfe"
+ File "lib\fonts\helveticaiso2.lps"
+ File "lib\fonts\helvetica.xfe"
+ File "lib\fonts\helvetica.lps"
+ File "lib\fonts\courieriso.xfe"
+ File "lib\fonts\courieriso5.xfe"
+ File "lib\fonts\courieriso5.lps"
+ File "lib\fonts\courieriso2.xfe"
+ File "lib\fonts\courieriso2.lps"
+ File "lib\fonts\courier.xfe"
+ File "lib\fonts\courier.lps"
+ SetOutPath "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps"
+ File "lib\pixmaps\z4.gif"
+ File "lib\pixmaps\yp.gif"
+ File "lib\pixmaps\xcircuit.gif"
+ File "lib\pixmaps\w.gif"
+ File "lib\pixmaps\uj.gif"
+ File "lib\pixmaps\tp.gif"
+ File "lib\pixmaps\ti.gif"
+ File "lib\pixmaps\tg.gif"
+ File "lib\pixmaps\t.gif"
+ File "lib\pixmaps\s.gif"
+ File "lib\pixmaps\q.gif"
+ File "lib\pixmaps\pz.gif"
+ File "lib\pixmaps\pu2.gif"
+ File "lib\pixmaps\po2.gif"
+ File "lib\pixmaps\pn.gif"
+ File "lib\pixmaps\pm.gif"
+ File "lib\pixmaps\pl.gif"
+ File "lib\pixmaps\pa.gif"
+ File "lib\pixmaps\mv.gif"
+ File "lib\pixmaps\mk.gif"
+ File "lib\pixmaps\li.gif"
+ File "lib\pixmaps\i.gif"
+ File "lib\pixmaps\fy.gif"
+ File "lib\pixmaps\fx.gif"
+ File "lib\pixmaps\fi.gif"
+ File "lib\pixmaps\e.gif"
+ File "lib\pixmaps\d2.gif"
+ File "lib\pixmaps\cw.gif"
+ File "lib\pixmaps\cp.gif"
+ File "lib\pixmaps\co.gif"
+ File "lib\pixmaps\ccw.gif"
+ File "lib\pixmaps\bd.gif"
+ File "lib\pixmaps\b.gif"
+ File "lib\pixmaps\a.gif"
+ File "lib\pixmaps\z5.gif"
+ File "lib\pixmaps\stip75.xbm"
+ File "lib\pixmaps\stip62.xbm"
+ File "lib\pixmaps\stip50.xbm"
+ File "lib\pixmaps\stip38.xbm"
+ File "lib\pixmaps\stip25.xbm"
+ File "lib\pixmaps\stip12.xbm"
+ File "lib\pixmaps\solid.xbm"
+ File "lib\pixmaps\stip88.xbm"
+SectionEnd
+
+Section "Tcl/Tk" SEC02
+ SetOutPath "$INSTDIR\tcl\bin"
+ SetOverwrite try
+ File "..\..\..\..\..\Software\Tcl\bin\tcl84.dll"
+ File "..\..\..\..\..\Software\Tcl\bin\tclpip84.dll"
+ File "..\..\..\..\..\Software\Tcl\bin\tclsh84.exe"
+ File "..\..\..\..\..\Software\Tcl\bin\tk84.dll"
+ File "..\..\..\..\..\Software\Tcl\bin\wish84.exe"
+ SetOutPath "$INSTDIR\tcl\include"
+ File "..\..\..\..\..\Software\Tcl\include\tcl.h"
+ File "..\..\..\..\..\Software\Tcl\include\tclDecls.h"
+ File "..\..\..\..\..\Software\Tcl\include\tclPlatDecls.h"
+ File "..\..\..\..\..\Software\Tcl\include\tk.h"
+ File "..\..\..\..\..\Software\Tcl\include\tkDecls.h"
+ File "..\..\..\..\..\Software\Tcl\include\tkIntXlibDecls.h"
+ File "..\..\..\..\..\Software\Tcl\include\tkPlatDecls.h"
+ SetOutPath "$INSTDIR\tcl\include\X11"
+ File "..\..\..\..\..\Software\Tcl\include\X11\cursorfont.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\keysym.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\keysymdef.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\X.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\Xatom.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\Xfuncproto.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\Xlib.h"
+ File "..\..\..\..\..\Software\Tcl\include\X11\Xutil.h"
+ SetOutPath "$INSTDIR\tcl\lib\dde1.2"
+ File "..\..\..\..\..\Software\Tcl\lib\dde1.2\pkgIndex.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\dde1.2\tcldde12.dll"
+ SetOutPath "$INSTDIR\tcl\lib\reg1.1"
+ File "..\..\..\..\..\Software\Tcl\lib\reg1.1\pkgIndex.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\reg1.1\tclreg11.dll"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\auto.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\encoding"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\ascii.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\big5.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1250.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1251.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1252.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1253.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1254.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1255.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1256.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1257.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp1258.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp437.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp737.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp775.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp850.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp852.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp855.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp857.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp860.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp861.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp862.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp863.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp864.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp865.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp866.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp869.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp874.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp932.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp936.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp949.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\cp950.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\dingbats.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\ebcdic.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\euc-cn.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\euc-jp.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\euc-kr.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\gb12345.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\gb1988.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\gb2312-raw.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\gb2312.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso2022-jp.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso2022-kr.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso2022.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-1.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-10.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-13.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-14.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-15.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-16.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-2.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-3.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-4.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-5.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-6.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-7.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-8.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\iso8859-9.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\jis0201.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\jis0208.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\jis0212.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\koi8-r.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\koi8-u.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\ksc5601.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macCentEuro.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macCroatian.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macCyrillic.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macDingbats.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macGreek.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macIceland.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macJapan.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macRoman.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macRomania.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macThai.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macTurkish.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\macUkraine.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\shiftjis.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\symbol.enc"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\encoding\tis-620.enc"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\history.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\http1.0"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\http1.0\http.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\http1.0\pkgIndex.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\http2.5"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\http2.5\http.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\http2.5\pkgIndex.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\init.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\ldAout.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\msgcat1.3"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\msgcat1.3\msgcat.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\msgcat1.3\pkgIndex.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\opt0.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\opt0.4\optparse.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\opt0.4\pkgIndex.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\package.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\parray.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\safe.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\tclIndex"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4\tcltest2.2"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\tcltest2.2\pkgIndex.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\tcltest2.2\tcltest.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tcl8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl8.4\word.tcl"
+ SetOutPath "$INSTDIR\tcl\lib"
+ File "..\..\..\..\..\Software\Tcl\lib\tcl84.lib"
+ File "..\..\..\..\..\Software\Tcl\lib\tclstub84.lib"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\bgerror.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\button.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\choosedir.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\clrpick.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\comdlg.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\console.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4\demos"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\arrow.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\bind.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\bitmap.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\browse"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\button.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\check.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\clrpick.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\colors.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\cscroll.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\ctext.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\dialog1.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\dialog2.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\entry1.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\entry2.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\entry3.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\filebox.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\floor.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\form.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\hello"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\hscale.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\icon.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\image1.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\image2.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4\demos\images"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\earth.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\earthris.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\face.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\flagdown.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\flagup.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\gray25.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\letters.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\noletter.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\pattern.bmp"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\tcllogo.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\images\teapot.ppm"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4\demos"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\items.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\ixset"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\label.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\labelframe.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\license.terms"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\menu.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\menubu.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\msgbox.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\paned1.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\paned2.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\plot.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\puzzle.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\radio.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\README"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\rmt"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\rolodex"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\ruler.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\sayings.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\search.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\spin.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\square"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\states.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\style.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\tclIndex"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\tcolor"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\text.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\timer"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\twind.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\unicodeout.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\vscale.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\demos\widget"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\dialog.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\entry.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\focus.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4\images"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\logo.eps"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\logo100.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\logo64.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\logoLarge.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\logoMed.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo.eps"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo100.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo150.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo175.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo200.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\pwrdLogo75.gif"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\README"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\images\tai-ku.gif"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\license.terms"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\listbox.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\menu.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\mkpsenc.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgbox.tcl"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4\msgs"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\cs.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\de.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\el.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\en.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\en_gb.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\eo.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\es.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\fr.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\it.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\nl.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\pl.msg"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\msgs\ru.msg"
+ SetOutPath "$INSTDIR\tcl\lib\tk8.4"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\obsolete.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\optMenu.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\palette.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\panedwindow.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\pkgIndex.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\safetk.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\scale.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\scrlbar.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\spinbox.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\tclIndex"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\tearoff.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\text.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\tk.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\tkfbox.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\unsupported.tcl"
+ File "..\..\..\..\..\Software\Tcl\lib\tk8.4\xmfbox.tcl"
+ SetOutPath "$INSTDIR\tcl\lib"
+ File "..\..\..\..\..\Software\Tcl\lib\tk84.lib"
+ File "..\..\..\..\..\Software\Tcl\lib\tkstub84.lib"
+SectionEnd
+
+Var wish_exe_path
+
+Function WishExePage
+SectionGetFlags ${SEC02} $R0
+IntOp $R0 $R0 & ${SF_SELECTED}
+IntCmp $R0 ${SF_SELECTED} 0 show
+Abort
+show:
+!insertmacro MUI_HEADER_TEXT "Tcl/Tk Location" "Enter the location for the wish (Tcl/Tk) executable"
+!insertmacro MUI_INSTALLOPTIONS_DISPLAY "wishexe.ini"
+FunctionEnd
+
+Function WishExeValidate
+ReadIniStr $wish_exe_path "$PLUGINSDIR\wishexe.ini" "Field 2" "State"
+IfFileExists $wish_exe_path +3 0
+ MessageBox MB_ICONSTOP|MB_OK "The specified location for the wish executable does not exist."
+ Abort
+FunctionEnd
+
+Section -AdditionalIcons
+ SetOutPath $INSTDIR
+ WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
+SectionEnd
+
+Section -Post
+ WriteUninstaller "$INSTDIR\uninst.exe"
+ WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\xcircuit-win32.exe"
+ StrCmp $wish_exe_path "" use_builtin_tcl use_system_tcl
+use_builtin_tcl:
+ WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "WishExe" "$INSTDIR\tcl\bin\wish84.exe"
+ Goto done
+use_system_tcl:
+ WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "WishExe" "$wish_exe_path"
+done:
+ WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "LibPath" "$INSTDIR\xcircuit-${PRODUCT_VERSION}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\xcircuit-win32.exe"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+; Section descriptions
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "XCircuit Application"
+ !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Tcl/Tk Framework (compiled for Win32 platforms)"
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+Function un.onUninstSuccess
+ HideWindow
+ MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
+FunctionEnd
+
+Function un.onInit
+ MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
+ Abort
+FunctionEnd
+
+Section Uninstall
+ Delete "$INSTDIR\${PRODUCT_NAME}.url"
+ Delete "$INSTDIR\uninst.exe"
+ Delete "$INSTDIR\tcl\lib\tkstub84.lib"
+ Delete "$INSTDIR\tcl\lib\tk84.lib"
+ Delete "$INSTDIR\tcl\lib\tk8.4\xmfbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\unsupported.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\tkfbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\tk.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\text.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\tearoff.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\tclIndex"
+ Delete "$INSTDIR\tcl\lib\tk8.4\spinbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\scrlbar.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\scale.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\safetk.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\panedwindow.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\palette.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\optMenu.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\obsolete.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\ru.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\pl.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\nl.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\it.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\fr.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\es.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\eo.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\en_gb.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\en.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\el.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\de.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgs\cs.msg"
+ Delete "$INSTDIR\tcl\lib\tk8.4\msgbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\mkpsenc.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\menu.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\listbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\license.terms"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\tai-ku.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\README"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo75.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo200.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo175.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo150.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo100.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\pwrdLogo.eps"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\logoMed.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\logoLarge.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\logo64.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\logo100.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\images\logo.eps"
+ Delete "$INSTDIR\tcl\lib\tk8.4\focus.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\entry.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\dialog.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\widget"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\vscale.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\unicodeout.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\twind.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\timer"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\text.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\tcolor"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\tclIndex"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\style.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\states.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\square"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\spin.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\search.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\sayings.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\ruler.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\rolodex"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\rmt"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\README"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\radio.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\puzzle.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\plot.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\paned2.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\paned1.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\msgbox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\menubu.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\menu.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\license.terms"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\labelframe.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\label.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\ixset"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\items.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\teapot.ppm"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\tcllogo.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\pattern.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\noletter.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\letters.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\gray25.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\flagup.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\flagdown.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\face.bmp"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\earthris.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\images\earth.gif"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\image2.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\image1.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\icon.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\hscale.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\hello"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\form.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\floor.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\filebox.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\entry3.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\entry2.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\entry1.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\dialog2.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\dialog1.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\ctext.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\cscroll.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\colors.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\clrpick.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\check.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\button.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\browse"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\bitmap.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\bind.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\demos\arrow.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\console.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\comdlg.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\clrpick.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\choosedir.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\button.tcl"
+ Delete "$INSTDIR\tcl\lib\tk8.4\bgerror.tcl"
+ Delete "$INSTDIR\tcl\lib\tclstub84.lib"
+ Delete "$INSTDIR\tcl\lib\tcl84.lib"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\word.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\tcltest2.2\tcltest.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\tcltest2.2\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\tclIndex"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\safe.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\parray.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\package.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\opt0.4\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\opt0.4\optparse.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\msgcat1.3\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\msgcat1.3\msgcat.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\ldAout.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\init.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\http2.5\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\http2.5\http.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\http1.0\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\http1.0\http.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\history.tcl"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\tis-620.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\symbol.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\shiftjis.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macUkraine.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macTurkish.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macThai.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macRomania.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macRoman.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macJapan.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macIceland.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macGreek.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macDingbats.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macCyrillic.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macCroatian.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\macCentEuro.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\ksc5601.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\koi8-u.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\koi8-r.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\jis0212.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\jis0208.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\jis0201.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-9.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-8.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-7.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-6.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-5.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-4.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-3.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-2.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-16.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-15.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-14.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-13.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-10.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso8859-1.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso2022.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso2022-kr.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\iso2022-jp.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\gb2312.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\gb2312-raw.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\gb1988.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\gb12345.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\euc-kr.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\euc-jp.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\euc-cn.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\ebcdic.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\dingbats.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp950.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp949.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp936.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp932.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp874.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp869.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp866.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp865.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp864.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp863.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp862.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp861.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp860.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp857.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp855.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp852.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp850.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp775.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp737.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp437.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1258.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1257.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1256.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1255.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1254.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1253.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1252.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1251.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\cp1250.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\big5.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\encoding\ascii.enc"
+ Delete "$INSTDIR\tcl\lib\tcl8.4\auto.tcl"
+ Delete "$INSTDIR\tcl\lib\reg1.1\tclreg11.dll"
+ Delete "$INSTDIR\tcl\lib\reg1.1\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\lib\dde1.2\tcldde12.dll"
+ Delete "$INSTDIR\tcl\lib\dde1.2\pkgIndex.tcl"
+ Delete "$INSTDIR\tcl\include\X11\Xutil.h"
+ Delete "$INSTDIR\tcl\include\X11\Xlib.h"
+ Delete "$INSTDIR\tcl\include\X11\Xfuncproto.h"
+ Delete "$INSTDIR\tcl\include\X11\Xatom.h"
+ Delete "$INSTDIR\tcl\include\X11\X.h"
+ Delete "$INSTDIR\tcl\include\X11\keysymdef.h"
+ Delete "$INSTDIR\tcl\include\X11\keysym.h"
+ Delete "$INSTDIR\tcl\include\X11\cursorfont.h"
+ Delete "$INSTDIR\tcl\include\tkPlatDecls.h"
+ Delete "$INSTDIR\tcl\include\tkIntXlibDecls.h"
+ Delete "$INSTDIR\tcl\include\tkDecls.h"
+ Delete "$INSTDIR\tcl\include\tk.h"
+ Delete "$INSTDIR\tcl\include\tclPlatDecls.h"
+ Delete "$INSTDIR\tcl\include\tclDecls.h"
+ Delete "$INSTDIR\tcl\include\tcl.h"
+ Delete "$INSTDIR\tcl\bin\wish84.exe"
+ Delete "$INSTDIR\tcl\bin\tk84.dll"
+ Delete "$INSTDIR\tcl\bin\tclsh84.exe"
+ Delete "$INSTDIR\tcl\bin\tclpip84.dll"
+ Delete "$INSTDIR\tcl\bin\tcl84.dll"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip88.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\solid.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip12.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip25.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip38.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip50.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip62.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\stip75.xbm"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\z5.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\a.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\b.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\bd.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\ccw.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\co.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\cp.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\cw.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\d2.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\e.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\fi.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\fx.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\fy.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\i.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\li.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\mk.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\mv.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pa.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pl.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pm.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pn.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\po2.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pu2.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\pz.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\q.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\s.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\t.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\tg.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\ti.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\tp.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\uj.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\w.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\xcircuit.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\yp.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps\z4.gif"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courier.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courier.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courieriso2.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courieriso2.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courieriso5.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courieriso5.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\courieriso.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helvetica.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helvetica.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helveticaiso2.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helveticaiso2.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helveticaiso5.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helveticaiso5.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\helveticaiso.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\myfont.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\myfont.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\symbol.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\symbol.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_roman.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_roman.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_romaniso2.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_romaniso2.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_romaniso5.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_romaniso5.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts\times_romaniso.xfe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xcircps2.pro"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\analog.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\analoglib2.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\analoglib3.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\asg_spice.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\avlsi.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\digital.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\generic.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\ic_templates.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\lgf.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\musiclib.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pcb.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pcb_layout.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\quadparts.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\series74xx.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\signal.lps"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xcircexec.exe"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xcircuit.dll"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xcstartup.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\panzoom.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pcbout.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\resource.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\sue_xc.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\tkcon.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\wrapper.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xcircuit.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\ngspice.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\library.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\console.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\bparams.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\autoincr.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\files.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\mousehint.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\symbol.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\sinusoid.tcl"
+ Delete "$INSTDIR\xcircuit-${PRODUCT_VERSION}\xchelp.tcl"
+ Delete "$INSTDIR\bin\xcircuit.bat"
+ Delete "$INSTDIR\bin\xcircuit-win32.exe"
+
+ Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
+ Delete "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk"
+ Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
+ Delete "$SMPROGRAMS\${PRODUCT_NAME}\XCircuit.lnk"
+
+ RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
+ RMDir "$INSTDIR\xcircuit-${PRODUCT_VERSION}\pixmaps"
+ RMDir "$INSTDIR\xcircuit-${PRODUCT_VERSION}\fonts"
+ RMDir "$INSTDIR\xcircuit-${PRODUCT_VERSION}"
+ RMDir "$INSTDIR\tcl\lib\tk8.4\msgs"
+ RMDir "$INSTDIR\tcl\lib\tk8.4\images"
+ RMDir "$INSTDIR\tcl\lib\tk8.4\demos\images"
+ RMDir "$INSTDIR\tcl\lib\tk8.4\demos"
+ RMDir "$INSTDIR\tcl\lib\tk8.4"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\tcltest2.2"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\opt0.4"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\msgcat1.3"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\http2.5"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\http1.0"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4\encoding"
+ RMDir "$INSTDIR\tcl\lib\tcl8.4"
+ RMDir "$INSTDIR\tcl\lib\reg1.1"
+ RMDir "$INSTDIR\tcl\lib\dde1.2"
+ RMDir "$INSTDIR\tcl\lib"
+ RMDir "$INSTDIR\tcl\include\X11"
+ RMDir "$INSTDIR\tcl\include"
+ RMDir "$INSTDIR\tcl\bin"
+ RMDir "$INSTDIR\tcl"
+ RMDir "$INSTDIR\bin"
+ RMDir "$INSTDIR"
+
+ DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+ DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
+ SetAutoClose true
+SectionEnd
diff --git a/xcircuit-win32.c b/xcircuit-win32.c
new file mode 100644
index 0000000..737dc61
--- /dev/null
+++ b/xcircuit-win32.c
@@ -0,0 +1,117 @@
+#include <windows.h>
+
+#define CMDLINE_SIZE 4096
+/*
+#define WISH_EXE L"C:/Software/TclTk/bin/wish84.exe"
+#define XCLIBDIR L"C:/Software/xcircuit/xcircuit-3.4"
+*/
+
+wchar_t *parse_args(LPWSTR *wargv, int argc)
+{
+ int i;
+ static wchar_t buffer[1024];
+
+ buffer[0] = L'\0';
+ for (i=1; i<argc; i++) {
+ if (_waccess(wargv[i], 0) == 0) {
+ wchar_t *c;
+ while ((c=wcschr(wargv[i], L'\\')) != NULL)
+ *c = L'/';
+ wcscat(buffer, L"\\\"");
+ wcscat(buffer, wargv[i]);
+ wcscat(buffer, L"\\\" ");
+ } else {
+ /*wcscat(buffer, wargv[i]);
+ wcscat(buffer, L" ");*/
+ }
+ }
+
+ return buffer;
+}
+
+static wchar_t wish_exe[1024] = {0};
+static wchar_t lib_path[1024] = {0};
+
+int look_paths()
+{
+ HKEY hKey;
+ DWORD bufLen = 1024 * sizeof(wchar_t);
+ wchar_t buf[1100];
+ int i;
+
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\xcircuit-dev-win32.exe", &hKey))
+ return -1;
+ if (RegQueryValueExW(
+ hKey,
+ L"WishExe",
+ NULL,
+ NULL,
+ (LPBYTE)wish_exe,
+ &bufLen)) {
+ RegCloseKey(hKey);
+ return -1;
+ }
+ bufLen = 1024 * sizeof(wchar_t);
+ if (RegQueryValueExW(
+ hKey,
+ L"LibPath",
+ NULL,
+ NULL,
+ (LPBYTE)lib_path,
+ &bufLen)) {
+ RegCloseKey(hKey);
+ return -1;
+ }
+ for (i=0; lib_path[i] != 0; i++)
+ if (lib_path[i] == L'\\')
+ lib_path[i] = L'/';
+ _snwprintf(buf, 1100, L"XCIRCUIT_LIB_DIR=%ws", lib_path);
+ _wputenv(buf);
+ RegCloseKey(hKey);
+ return 0;
+}
+
+int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int cmdShow)
+{
+ LPWSTR *wargv;
+ wchar_t *cmdLine, *arg_str;
+ int argc, i;
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+
+ wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (wargv != NULL) {
+ cmdLine = (wchar_t*)malloc(sizeof(wchar_t)*CMDLINE_SIZE);
+ arg_str = parse_args(wargv, argc);
+ if (look_paths())
+ goto error;
+ _snwprintf(cmdLine, CMDLINE_SIZE,
+ L"\"%ws\" \"%ws/tkcon.tcl\" -eval \"source \"\"%ws/console.tcl\"\"\" -slave \"package require Tk; set argv [list %ws]; set argc [llength argv]; source \"\"%ws/xcircuit.tcl\"\"\"",
+ wish_exe, lib_path, lib_path, arg_str, lib_path);
+ /*MessageBoxW(NULL, cmdLine, L"Info", MB_OK);*/
+ ZeroMemory(&si, sizeof(STARTUPINFOW));
+ si.cb = sizeof(STARTUPINFOW);
+ if (!CreateProcessW(NULL,
+ cmdLine,
+ NULL,
+ NULL,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ &si,
+ &pi)) {
+ goto error;
+ }
+ goto success;
+
+error:
+ MessageBox(NULL, "Unable to start xcircuit process", "Error", MB_OK);
+
+success:
+ LocalFree(wargv);
+ free(cmdLine);
+ }
+
+ return 1;
+}
diff --git a/xcircuit.c b/xcircuit.c
new file mode 100644
index 0000000..19ef136
--- /dev/null
+++ b/xcircuit.c
@@ -0,0 +1,1488 @@
+/*----------------------------------------------------------------------*/
+/* xcircuit.c --- An X-windows program for drawing circuit diagrams */
+/* Copyright (c) 2002 R. Timothy Edwards */
+/* */
+/* 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: */
+/* Free Software Foundation, Inc. */
+/* 59 Temple Place, Suite 330 */
+/* Boston, MA 02111-1307 USA */
+/* */
+/* See file ./README for contact information */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Uses the Xw widget set (see directory Xw) */
+/* Xcircuit written by Tim Edwards beginning 8/13/93 */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <ctype.h>
+#ifndef XC_WIN32
+#include <unistd.h> /* for unlink() */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/Xproto.h>
+#include <X11/Xatom.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#else
+#ifndef XC_WIN32
+#include "Xw/Xw.h"
+#include "Xw/Form.h"
+#include "Xw/WorkSpace.h"
+#include "Xw/PButton.h"
+#include "Xw/SText.h"
+#include "Xw/Cascade.h"
+#include "Xw/PopupMgr.h"
+#include "Xw/MenuBtn.h"
+#include "Xw/BBoard.h"
+#include "Xw/TextEdit.h"
+#include "Xw/Toggle.h"
+#endif
+#endif
+
+#if defined(XC_WIN32) && defined(TCL_WRAPPER)
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/Xatom.h>
+#endif
+
+#ifndef P_tmpdir
+#define P_tmpdir TMPDIR
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "cursors.h"
+#include "colordefs.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*----------------------------------------------------------------------*/
+
+char _STR2[250]; /* Specifically for text returned from the popup prompt */
+char _STR[150]; /* Generic multipurpose string */
+int pressmode; /* Whether we are in a press & hold state */
+Display *dpy = NULL; /* Works well to make this globally accessible */
+Colormap cmap;
+Pixmap STIPPLE[STIPPLES]; /* Polygon fill-style stipple patterns */
+Cursor appcursors[NUM_CURSORS];
+ApplicationData appdata;
+XCWindowData *areawin;
+Globaldata xobjs;
+int *appcolors;
+int number_colors;
+colorindex *colorlist;
+short menusize;
+xcIntervalId printtime_id;
+short beeper;
+short fontcount;
+fontinfo *fonts;
+short popups; /* total number of popup widgets on the screen */
+
+/*----------------------------------------------------------------------*/
+/* Externally defined variables */
+/*----------------------------------------------------------------------*/
+
+extern aliasptr aliastop;
+extern float version;
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#else
+extern XtAppContext app;
+#endif
+
+#ifdef DOUBLEBUFFER
+extern Pixmap dbuf;
+#endif
+
+/* Bad hack for problems with the DECstation. . . don't know why */
+#ifdef UniqueContextProblem
+#undef XUniqueContext
+XContext XUniqueContext()
+{
+ return XrmUniqueQuark();
+}
+#endif
+/* End of bad hack. . . */
+
+/*----------------------------------------------------------------------*/
+/* Update the list of colors in the colormap */
+/*----------------------------------------------------------------------*/
+
+void addtocolorlist(xcWidget button, int cvalue)
+{
+ number_colors++;
+ colorlist = (colorindex *)realloc(colorlist, number_colors *
+ sizeof(colorindex));
+ colorlist[number_colors - 1].cbutton = button;
+ colorlist[number_colors - 1].color.pixel = cvalue;
+
+ /* Get and store the RGB values of the new color */
+
+ XQueryColors(dpy, cmap, &(colorlist[number_colors - 1].color), 1);
+}
+
+/*----------------------------------------------------------------------*/
+/* Add a new color button to the color menu */
+/* called if new color button needs to be made */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+int addnewcolorentry(int ccolor)
+{
+ xcWidget newbutton; /* colormenu, (jdk) */
+#ifndef XC_WIN32
+ /* Arg wargs[2]; (jdk) */
+#endif
+ int i; /* , n = 0; (jdk) */
+
+ /* check to see if entry is already in the color list */
+
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == ccolor) break;
+
+ /* make new entry in the menu */
+
+ if (i == number_colors) {
+ addtocolorlist(newbutton, ccolor);
+ sprintf(_STR2,
+ "xcircuit::newcolorbutton %d %d %d %d",
+ colorlist[i].color.red, colorlist[i].color.green,
+ colorlist[i].color.blue, i);
+ Tcl_Eval(xcinterp, _STR2);
+ }
+ return i;
+}
+
+#endif /* TCL_WRAPPER */
+
+/*---------------*/
+/* Quit xcircuit */
+/*---------------*/
+
+void quit(xcWidget w, caddr_t nulldata)
+{
+ int i;
+ Matrixptr curmatrix, dmatrix;
+
+ /* free up CTM Matrix Stack */
+ if (areawin != NULL) {
+ curmatrix = areawin->MatStack;
+ while (curmatrix != NULL) {
+ dmatrix = curmatrix->nextmatrix;
+ free(curmatrix);
+ curmatrix = dmatrix;
+ }
+ areawin->MatStack = NULL;
+ }
+
+ /* free the colormap if a new one has been installed */
+
+ if (dpy != NULL)
+ if (cmap != DefaultColormap(dpy, DefaultScreen(dpy)))
+ XFreeColormap(dpy, cmap);
+
+ /* exit ghostscript if background rendering was enabled */
+
+ exit_gs();
+
+#ifdef TCL_WRAPPER
+ /* exit ngspice if the simulator is still running */
+
+ exit_spice();
+#endif
+
+ /* remove any temporary files created for background rendering */
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst != NULL)
+ if (xobjs.pagelist[i]->background.name != (char *)NULL)
+ if (*(xobjs.pagelist[i]->background.name) == '@')
+ unlink(xobjs.pagelist[i]->background.name + 1);
+ }
+
+ /* remove the temporary file and free the filename memory */
+ /* if w = NULL, quit() was reached from Ctrl-C. Don't */
+ /* remove the temporary file; instead, notify user of the */
+ /* filename. */
+
+ if (xobjs.tempfile != NULL) {
+ if (w != NULL) {
+#ifndef XC_WIN32
+ if (unlink(xobjs.tempfile) < 0)
+ Fprintf(stderr, "Error %d unlinking file \"%s\"\n", errno, xobjs.tempfile);
+#else
+ if (DeleteFile(xobjs.tempfile) != TRUE)
+ Fprintf(stderr, "Error %d unlinking file \"%s\"\n",
+ GetLastError(), xobjs.tempfile);
+#endif
+ }
+ else
+ Fprintf(stderr, "Ctrl-C exit: reload workspace from \"%s\"\n",
+ xobjs.tempfile);
+ }
+ free(xobjs.tempfile);
+
+#if defined(HAVE_PYTHON)
+ /* exit by exiting the Python interpreter, if enabled */
+ exit_interpreter();
+#elif defined(TCL_WRAPPER)
+ exit(0); /* For now, exit. Later, clear all pages and return to interp. */
+#elif defined(XC_WIN32)
+ PostQuitMessage(0);
+#else
+ exit(0);
+#endif
+
+}
+
+/*--------------------------------------------------------------*/
+/* Check for changes in an object and all of its descendents */
+/*--------------------------------------------------------------*/
+
+u_short getchanges(objectptr thisobj)
+{
+ genericptr *pgen;
+ objinstptr pinst;
+ u_short changes = thisobj->changes;
+
+ for (pgen = thisobj->plist; pgen < thisobj->plist + thisobj->parts; pgen++) {
+ if (IS_OBJINST(*pgen)) {
+ pinst = TOOBJINST(pgen);
+ changes += getchanges(pinst->thisobject);
+ }
+ }
+ return changes;
+}
+
+/*--------------------------------------------------------------*/
+/* Check to see if any objects in xcircuit have been modified */
+/* without saving. */
+/*--------------------------------------------------------------*/
+
+u_short countchanges(char **promptstr)
+{
+ int slen = 1, i; /* , j; (jdk) */
+ u_short locchanges, changes = 0, words = 1;
+ objectptr thisobj;
+ char *fname;
+ TechPtr ns;
+
+ if (promptstr != NULL) slen += strlen(*promptstr);
+
+ for (i = 0; i < xobjs.pages; i++) {
+ if (xobjs.pagelist[i]->pageinst != NULL) {
+ thisobj = xobjs.pagelist[i]->pageinst->thisobject;
+ locchanges = getchanges(thisobj);
+ if (locchanges > 0) {
+ if (promptstr != NULL) {
+ slen += strlen(thisobj->name) + 2;
+ *promptstr = (char *)realloc(*promptstr, slen);
+ if ((words % 8) == 0) strcat(*promptstr, ",\n");
+ else if (changes > 0) strcat(*promptstr, ", ");
+ strcat(*promptstr, thisobj->name);
+ words++;
+ }
+ changes += locchanges;
+ }
+ }
+ }
+
+ /* Check all library objects for unsaved changes */
+
+ for (ns = xobjs.technologies; ns != NULL; ns = ns->next) {
+ tech_set_changes(ns);
+ if ((ns->flags & TECH_CHANGED) != 0) {
+ changes++;
+ if (promptstr != NULL) {
+ fname = ns->filename;
+ if (fname != NULL) {
+ slen += strlen(fname) + 2;
+ *promptstr = (char *)realloc(*promptstr, slen);
+ if ((words % 8) == 0) strcat(*promptstr, ",\n");
+ else if (changes > 0) strcat(*promptstr, ", ");
+ strcat(*promptstr, fname);
+ words++;
+ }
+ }
+ }
+ }
+ return changes;
+}
+
+/*----------------------------------------------*/
+/* Check for conditions to approve program exit */
+/*----------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void quitcheck(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ char *promptstr;
+ Boolean doprompt = False;
+
+ /* enable default interrupt signal handler during this time, so that */
+ /* a double Control-C will ALWAYS exit. */
+
+ signal(SIGINT, SIG_DFL);
+
+ promptstr = (char *)malloc(60);
+ strcpy(promptstr, ".query.title.field configure -text \"Unsaved changes in: ");
+
+ /* Check all page objects for unsaved changes */
+
+ doprompt = (countchanges(&promptstr) > 0) ? True : False;
+
+ /* If any changes have not been saved, generate a prompt */
+
+ if (doprompt) {
+ promptstr = (char *)realloc(promptstr, strlen(promptstr) + 15);
+ strcat(promptstr, "\nQuit anyway?");
+
+ strcat(promptstr, "\"");
+ Tcl_Eval(xcinterp, promptstr);
+ Tcl_Eval(xcinterp, ".query.bbar.okay configure -command {quitnocheck}");
+ Tcl_Eval(xcinterp, "wm deiconify .query");
+ Tcl_Eval(xcinterp, "raise .query");
+ free(promptstr);
+ }
+ else {
+ free(promptstr);
+ quit(w, NULL);
+ }
+}
+
+#endif
+
+/*--------------------------------------*/
+/* A gentle Ctrl-C shutdown */
+/*--------------------------------------*/
+
+void dointr(int signum)
+{
+ quitcheck(NULL, NULL, NULL);
+}
+
+/*--------------*/
+/* Null routine */
+/*--------------*/
+
+void DoNothing(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ /* Nothing here! */
+}
+
+/*-----------------------------------------------------------------------*/
+/* Write page scale (overall scale, and X and Y dimensions) into strings */
+/*-----------------------------------------------------------------------*/
+
+void writescalevalues(char *scdest, char *xdest, char *ydest)
+{
+ float oscale, psscale;
+ int width, height;
+ Pagedata *curpage;
+
+ curpage = xobjs.pagelist[areawin->page];
+ oscale = curpage->outscale;
+ psscale = getpsscale(oscale, areawin->page);
+
+ width = toplevelwidth(curpage->pageinst, NULL);
+ height = toplevelheight(curpage->pageinst, NULL);
+
+ sprintf(scdest, "%6.5f", oscale);
+ if (curpage->coordstyle == CM) {
+ sprintf(xdest, "%6.5f", (width * psscale) / IN_CM_CONVERT);
+ sprintf(ydest, "%6.5f", (height * psscale) / IN_CM_CONVERT);
+ }
+ else {
+ sprintf(xdest, "%6.5f", (width * psscale) / 72.0);
+ sprintf(ydest, "%6.5f", (height * psscale) / 72.0);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Destroy an interactive text-editing popup box */
+/*-------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+/* Just pop it down. . . */
+
+void destroypopup(xcWidget button, popupstruct *callstruct, caddr_t calldata)
+{
+ Tk_UnmapWindow(callstruct->popup);
+ popups--;
+
+ /* free the allocated structure space */
+
+ free(callstruct->buttonptr);
+ if (callstruct->filter != NULL) free(callstruct->filter);
+ free(callstruct);
+
+ /* in the case of "quitcheck", we want to make sure that the signal */
+ /* handler is reset to default behavior if the quit command is */
+ /* canceled from inside the popup prompt window. */
+
+ signal(SIGINT, dointr);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Create a popup window with "OK" and "Cancel" buttons, */
+/* and text and label fields. */
+/*-------------------------------------------------------------------------*/
+
+void popupprompt(xcWidget button, char *request, char *current, void (*function)(),
+ buttonsave *datastruct, const char *filter)
+{
+ Tk_Window popup;
+
+ popup = Tk_NameToWindow(xcinterp, ".dialog", Tk_MainWindow(xcinterp));
+ Tk_MapWindow(popup);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Create a popup window for property changes */
+/*-------------------------------------------------------------------------*/
+
+void outputpopup(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ Tcl_Eval(xcinterp, "wm deiconify .output");
+}
+
+/*-------------------------------------------------*/
+/* Print a string to the message widget. */
+/* Note: Widget message must be a global variable. */
+/* For formatted strings, format first into _STR */
+/*-------------------------------------------------*/
+
+/* XXX it looks like this routine is an orphan */
+void clrmessage(caddr_t clientdata)
+{
+ char buf1[50], buf2[50];
+
+ /* Don't write over the report of the edit string contents, */
+ /* if we're in one of the label edit modes */
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE)
+ charreport(TOLABEL(EDITPART));
+ else {
+ measurestr(xobjs.pagelist[areawin->page]->gridspace, buf1);
+ measurestr(xobjs.pagelist[areawin->page]->snapspace, buf2);
+ Wprintf("Grid %.50s : Snap %.50s", buf1, buf2);
+ }
+}
+
+#endif /* TCL_WRAPPER */
+
+/*------------------------------------------------------------------------------*/
+/* diagnostic tool for translating the event mode into a string and printing */
+/* to stderr (for debugging only). */
+/*------------------------------------------------------------------------------*/
+
+void printeventmode() {
+ Fprintf(stderr, "eventmode is \'");
+ switch(eventmode) {
+ case NORMAL_MODE:
+ Fprintf(stderr, "NORMAL");
+ break;
+ case MOVE_MODE:
+ Fprintf(stderr, "MOVE");
+ break;
+ case COPY_MODE:
+ Fprintf(stderr, "COPY");
+ break;
+ case SELAREA_MODE:
+ Fprintf(stderr, "SELAREA");
+ break;
+ case CATALOG_MODE:
+ Fprintf(stderr, "CATALOG");
+ break;
+ case CATTEXT_MODE:
+ Fprintf(stderr, "CATTEXT");
+ break;
+ case CATMOVE_MODE:
+ Fprintf(stderr, "CATMOVE");
+ break;
+ case FONTCAT_MODE:
+ Fprintf(stderr, "FONTCAT");
+ break;
+ case EFONTCAT_MODE:
+ Fprintf(stderr, "EFONTCAT");
+ break;
+ case TEXT_MODE:
+ Fprintf(stderr, "TEXT");
+ break;
+ case ETEXT_MODE:
+ Fprintf(stderr, "ETEXT");
+ break;
+ case WIRE_MODE:
+ Fprintf(stderr, "WIRE");
+ break;
+ case BOX_MODE:
+ Fprintf(stderr, "BOX");
+ break;
+ case EPOLY_MODE:
+ Fprintf(stderr, "EPOLY");
+ break;
+ case ARC_MODE:
+ Fprintf(stderr, "ARC");
+ break;
+ case EARC_MODE:
+ Fprintf(stderr, "EARC");
+ break;
+ case SPLINE_MODE:
+ Fprintf(stderr, "SPLINE");
+ break;
+ case ESPLINE_MODE:
+ Fprintf(stderr, "ESPLINE");
+ break;
+ case EPATH_MODE:
+ Fprintf(stderr, "EPATH");
+ break;
+ case EINST_MODE:
+ Fprintf(stderr, "EINST");
+ break;
+ case ASSOC_MODE:
+ Fprintf(stderr, "ASSOC");
+ break;
+ case RESCALE_MODE:
+ Fprintf(stderr, "RESCALE");
+ break;
+ case PAN_MODE:
+ Fprintf(stderr, "PAN");
+ break;
+ default:
+ Fprintf(stderr, "(unknown)");
+ break;
+ }
+ Fprintf(stderr, "_MODE\'\n");
+}
+
+/*------------------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+/*------------------------------------------------------------------------------*/
+/* "docommand" de-iconifies the TCL console. */
+/*------------------------------------------------------------------------------*/
+
+void docommand()
+{
+ Tcl_Eval(xcinterp, "catch xcircuit::raiseconsole");
+}
+
+/*------------------------------------------------------------------------------*/
+/* When all else fails, install your own colormap */
+/*------------------------------------------------------------------------------*/
+
+int installowncmap()
+{
+ Colormap newcmap;
+
+ Fprintf(stdout, "Installing my own colormap\n");
+
+ /* allocate a new colormap */
+
+ newcmap = XCopyColormapAndFree(dpy, cmap);
+ if (newcmap == (Colormap)NULL) return (-1);
+ cmap = newcmap;
+ return(1);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*------------------------------------------------------------------------------*/
+/* Find the nearest color in the colormap to cvexact and return its pixel value */
+/*------------------------------------------------------------------------------*/
+
+#if defined(TCL_WRAPPER) || !defined(XC_WIN32)
+
+int findnearcolor(XColor *cvexact)
+{
+ /* find the nearest-matching color in the colormap */
+
+ int i, ncolors = DisplayCells(dpy, DefaultScreen(dpy));
+ XColor *cmcolors;
+ long rdist, bdist, gdist;
+ u_long dist, mindist;
+ int minidx;
+
+ cmcolors = (XColor *)malloc(ncolors * sizeof(XColor));
+
+ for (i = 0; i < ncolors; i++) {
+ cmcolors[i].pixel = i;
+ cmcolors[i].flags = DoRed | DoGreen | DoBlue;
+ }
+ XQueryColors(dpy, cmap, cmcolors, ncolors);
+
+ mindist = ULONG_MAX;
+ for (i = 0; i < ncolors; i++) {
+ rdist = (cmcolors[i].red - cvexact->red);
+ bdist = (cmcolors[i].blue - cvexact->blue);
+ gdist = (cmcolors[i].green - cvexact->green);
+ dist = rdist * rdist + bdist * bdist + gdist * gdist;
+ if (dist < mindist) {
+ mindist = dist;
+ minidx = i;
+ }
+ }
+ free(cmcolors);
+
+ /* if we can't get the right color or something reasonably close, */
+ /* then allocate our own colormap. If we've allocated so many */
+ /* colors that the new colormap is full, then we give up and use */
+ /* whatever color was closest, no matter how far away it was. */
+
+ /* findnearcolor already used 512 per component, so to match that, */
+ /* 3 * (512 * 512) = 786432 ~= 750000 */
+
+ if (dist > 750000) {
+ if (installowncmap() > 0) {
+ if (XAllocColor(dpy, cmap, cvexact) != 0)
+ minidx = cvexact->pixel;
+ }
+ }
+
+ return minidx;
+}
+
+#endif
+
+/*------------------------------------------------------------------------------*/
+/* Layout colors which are defined from the Xdefaults (BBOXCOLOR, schematic */
+/* label colors) may be duplicated in the colormap. This routine takes a color */
+/* index of a color and returns the index of any color in the layout colormap */
+/* which matches it within the tolerance used by "rgb_alloccolor". This will */
+/* be used to remap the Xdefault-supplied colors to the layout color table, so */
+/* we don't get duplicate entries. */
+/*------------------------------------------------------------------------------*/
+
+int xc_getlayoutcolor(int cidx)
+{
+ XColor loccolor;
+ int locidx; /* i, (jdk) */
+
+ loccolor.pixel = cidx;
+ loccolor.flags = DoRed | DoGreen | DoBlue;
+
+ XQueryColors(dpy, cmap, &loccolor, 1);
+
+ locidx = rgb_alloccolor(loccolor.red, loccolor.green, loccolor.blue);
+ return locidx;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Hack on the resource database Color allocation */
+/* */
+/* This overrides the built-in routine. The difference is that if a */
+/* color cell cannot be allocated (colormap is full), then the color */
+/* map is searched for the closest RGB value to the named color. */
+/* */
+/* This code depends on Display *dpy being set: Do not install the */
+/* converter until after XtInitialize(), when using the Xt (not Tcl) GUI. */
+/*-------------------------------------------------------------------------*/
+
+#if defined(TCL_WRAPPER) || !defined(XC_WIN32)
+
+caddr_t CvtStringToPixel(XrmValuePtr args, int *nargs, XrmValuePtr fromVal,
+ XrmValuePtr toVal)
+{
+ static XColor cvcolor;
+ XColor cvexact;
+
+ if (dpy == NULL) return NULL;
+
+ if (*nargs != 0)
+ Fprintf(stderr, "String to Pixel conversion takes no arguments");
+
+ /* Color defaults to black if name is not found */
+
+ if (XAllocNamedColor(dpy, cmap, (char *)fromVal->addr, &cvcolor, &cvexact)
+ == 0) {
+ if (XLookupColor(dpy, cmap, (char *)fromVal->addr, &cvexact, &cvcolor) == 0)
+ cvcolor.pixel = BlackPixel(dpy, DefaultScreen(dpy));
+ else
+ cvcolor.pixel = findnearcolor(&cvexact);
+ }
+
+ toVal->size = sizeof(u_long);
+ toVal->addr = (caddr_t) &(cvcolor.pixel);
+ return NULL;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Allocate new color using the CvtStringToPixel routine */
+/*-------------------------------------------------------------------------*/
+
+#if defined(XC_WIN32) && !defined(TCL_WRAPPER)
+
+int xc_alloccolor(char *name)
+{
+ return WinNamedColor(name);
+}
+
+#else
+
+int xc_alloccolor(char *name)
+{
+ XrmValue fromC, toC;
+ int zval = 0, pixval;
+
+ fromC.size = strlen(name);
+ fromC.addr = name;
+
+ CvtStringToPixel(NULL, &zval, &fromC, &toC);
+ pixval = (int)(*((u_long *)toC.addr));
+
+ return pixval;
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Check if color within RGB roundoff error exists in xcircuit's color */
+/* table. Assume 24-bit color, in which resolution can be no less than */
+/* 256 for each color component. Visual acuity is a bit less than 24- */
+/* bit color, so assume difference should be no less than 512 per */
+/* component for colors to be considered "different". Psychologically, */
+/* we should really find the just-noticable-difference for each color */
+/* component separately! But that's too complicated for this simple */
+/* routine. */
+/* */
+/* Return the table entry of the color, if it is in xcircuit's color */
+/* table, or ERRORCOLOR if not. If it is in the color table, then */
+/* return the actual pixel value from the table in the "pixval" pointer */
+/*----------------------------------------------------------------------*/
+
+int rgb_querycolor(int red, int green, int blue, int *pixval)
+{
+ int i;
+
+ for (i = 0; i < number_colors; i++) {
+ if (abs(colorlist[i].color.red - red) < 512 &&
+ abs(colorlist[i].color.green - green) < 512 &&
+ abs(colorlist[i].color.blue - blue) < 512) {
+ if (pixval)
+ *pixval = colorlist[i].color.pixel;
+ return i;
+ break;
+ }
+ }
+ return ERRORCOLOR;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Allocate new color from RGB values (e.g., from PS file "scb" command) */
+/*-----------------------------------------------------------------------*/
+
+#if defined(XC_WIN32) && !defined(TCL_WRAPPER)
+
+int rgb_alloccolor(int red, int green, int blue)
+{
+ return RGB(red >> 8, green >> 8, blue >> 8);
+}
+
+#else
+
+int rgb_alloccolor(int red, int green, int blue)
+{
+ XColor newcolor;
+ int pixval, tableidx; /* i, (jdk) */
+
+ /* if color is not already in list, try to allocate it; if allocation */
+ /* fails, grab the closest match in the colormap. */
+
+ tableidx = rgb_querycolor(red, green, blue, &pixval);
+
+ if (tableidx < 0) {
+ newcolor.red = red;
+ newcolor.green = green;
+ newcolor.blue = blue;
+ newcolor.flags = DoRed | DoGreen | DoBlue;
+ if (XAllocColor(dpy, cmap, &newcolor) == 0)
+ pixval = findnearcolor(&newcolor);
+ else
+ pixval = newcolor.pixel;
+ }
+ return pixval;
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Query a color by name to see if it is in the color table. */
+/* Return the table index (NOT the pixel value) of the entry, */
+/* ERRORCOLOR if the color is not in the table, and BADCOLOR if the */
+/* color name could not be parsed by XLookupColor(). */
+/*----------------------------------------------------------------------*/
+
+int query_named_color(char *cname)
+{
+ XColor cvcolor, cvexact;
+ int tableidx, result;
+
+ result = XLookupColor(dpy, cmap, cname, &cvexact, &cvcolor);
+ if (result == 0) return BADCOLOR;
+
+ tableidx = rgb_querycolor(cvcolor.red, cvcolor.green, cvcolor.blue, NULL);
+ return tableidx;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Make the cursors from the cursor bit data */
+/*-------------------------------------------------------------------------*/
+
+void makecursors()
+{
+ XColor fgcolor, bgcolor;
+ Window win = areawin->window;
+#ifdef TCL_WRAPPER
+ Tk_Uid fg_uid, bg_uid;
+#endif
+
+ bgcolor.pixel = BACKGROUND;
+ fgcolor.pixel = FOREGROUND;
+ XQueryColors(dpy, cmap, &fgcolor, 1);
+ XQueryColors(dpy, cmap, &bgcolor, 1);
+
+#ifdef TCL_WRAPPER
+
+#ifdef XC_WIN32
+#define Tk_GetCursorFromData CreateW32Cursor
+#endif
+
+ fg_uid = Tk_GetUid(Tk_NameOfColor(&fgcolor));
+ bg_uid = Tk_GetUid(Tk_NameOfColor(&bgcolor));
+
+ ARROW = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ arrow_bits, arrowmask_bits, arrow_width, arrow_height, arrow_x_hot, arrow_y_hot,
+ fg_uid, bg_uid);
+ CROSS = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ cross_bits, crossmask_bits, cross_width, cross_height, cross_x_hot, cross_y_hot,
+ fg_uid, bg_uid);
+ SCISSORS = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ scissors_bits, scissorsmask_bits, scissors_width, scissors_height,
+ scissors_x_hot, scissors_y_hot, fg_uid, bg_uid);
+ EDCURSOR = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ exx_bits, exxmask_bits, exx_width, exx_height, exx_x_hot, exx_y_hot,
+ fg_uid, bg_uid);
+ COPYCURSOR = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ copy_bits, copymask_bits, copy_width, copy_height, copy_x_hot, copy_y_hot,
+ fg_uid, bg_uid);
+ ROTATECURSOR = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ rot_bits, rotmask_bits, rot_width, rot_height, circle_x_hot, circle_y_hot,
+ fg_uid, bg_uid);
+ QUESTION = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ question_bits, questionmask_bits, question_width, question_height,
+ question_x_hot, question_y_hot, fg_uid, bg_uid);
+ CIRCLE = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ circle_bits, circlemask_bits, circle_width, circle_height, circle_x_hot,
+ circle_y_hot, fg_uid, bg_uid);
+ HAND = (Cursor)Tk_GetCursorFromData(xcinterp, Tk_IdToWindow(dpy, win),
+ hand_bits, handmask_bits, hand_width, hand_height, hand_x_hot, hand_y_hot,
+ fg_uid, bg_uid);
+
+#ifdef XC_WIN32
+#undef Tk_GetCursorFromData
+#endif
+
+#else
+ ARROW = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, arrow_bits,
+ arrow_width, arrow_height), XCreateBitmapFromData(dpy, win, arrowmask_bits,
+ arrow_width, arrow_height), &fgcolor, &bgcolor, arrow_x_hot, arrow_y_hot);
+ CROSS = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, cross_bits,
+ cross_width, cross_height), XCreateBitmapFromData(dpy, win, crossmask_bits,
+ cross_width, cross_height), &fgcolor, &bgcolor, cross_x_hot, cross_y_hot);
+ SCISSORS = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, scissors_bits,
+ scissors_width, scissors_height), XCreateBitmapFromData(dpy, win,
+ scissorsmask_bits, scissors_width, scissors_height), &fgcolor,
+ &bgcolor, scissors_x_hot, scissors_y_hot);
+ EDCURSOR = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, exx_bits,
+ exx_width, exx_height), XCreateBitmapFromData(dpy, win, exxmask_bits,
+ exx_width, exx_height), &fgcolor, &bgcolor, exx_x_hot, exx_y_hot);
+ COPYCURSOR = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, copy_bits,
+ copy_width, copy_height), XCreateBitmapFromData(dpy, win, copymask_bits,
+ copy_width, copy_height), &fgcolor, &bgcolor, copy_x_hot, copy_y_hot);
+ ROTATECURSOR = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, rot_bits,
+ rot_width, rot_height), XCreateBitmapFromData(dpy, win, rotmask_bits,
+ rot_width, rot_height), &fgcolor, &bgcolor, circle_x_hot, circle_y_hot);
+ QUESTION = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, question_bits,
+ question_width, question_height), XCreateBitmapFromData(dpy, win,
+ questionmask_bits, question_width, question_height),
+ &fgcolor, &bgcolor, question_x_hot, question_y_hot);
+ CIRCLE = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, circle_bits,
+ circle_width, circle_height), XCreateBitmapFromData(dpy, win, circlemask_bits,
+ circle_width, circle_height), &fgcolor, &bgcolor, circle_x_hot, circle_y_hot);
+ HAND = XCreatePixmapCursor(dpy, XCreateBitmapFromData(dpy, win, hand_bits,
+ hand_width, hand_height), XCreateBitmapFromData(dpy, win, handmask_bits,
+ hand_width, hand_height), &fgcolor, &bgcolor, hand_x_hot, hand_y_hot);
+#endif
+
+ TEXTPTR = XCreateFontCursor(dpy, XC_xterm);
+ WAITFOR = XCreateFontCursor(dpy, XC_watch);
+
+ XRecolorCursor(dpy, TEXTPTR, &fgcolor, &bgcolor);
+}
+
+/*----------------------------------------------------------------------*/
+/* Remove a window structure and deallocate all memory used by it. */
+/* If it is the last window, this is equivalent to calling "quit". */
+/*----------------------------------------------------------------------*/
+
+void delete_window(XCWindowData *window)
+{
+ XCWindowData *searchwin, *lastwin = NULL;
+
+ if (xobjs.windowlist->next == NULL) {
+ quitcheck((window == NULL) ? NULL : window->area, NULL, NULL);
+ return;
+ }
+
+ for (searchwin = xobjs.windowlist; searchwin != NULL; searchwin =
+ searchwin->next) {
+ if (searchwin == window) {
+ Matrixptr thismat;
+
+ /* Free any select list */
+ if (searchwin->selects > 0) free(searchwin->selectlist);
+
+ /* Free the matrix and pushlist stacks */
+
+ while (searchwin->MatStack != NULL) {
+ thismat = searchwin->MatStack;
+ searchwin->MatStack = searchwin->MatStack->nextmatrix;
+ free(thismat);
+ }
+ free_stack(&searchwin->hierstack);
+ free_stack(&searchwin->stack);
+
+ /* Free the GC */
+ XFreeGC(dpy, searchwin->gc);
+
+ if (lastwin != NULL)
+ lastwin->next = searchwin->next;
+ else
+ xobjs.windowlist = searchwin->next;
+ break;
+ }
+ lastwin = searchwin;
+ }
+
+ if (searchwin == NULL) {
+ Wprintf("No such window in list!\n");
+ }
+ else {
+ if (areawin == searchwin) areawin = xobjs.windowlist;
+ free(searchwin);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Create a new window structure and initialize it. */
+/* Return a pointer to the new window. */
+/*----------------------------------------------------------------------*/
+
+XCWindowData *create_new_window()
+{
+ XCWindowData *newwindow;
+
+ newwindow = (XCWindowData *)malloc(sizeof(XCWindowData));
+
+#ifndef TCL_WRAPPER
+#ifdef HAVE_XPM
+ newwindow->toolbar_on = True;
+#endif
+#endif
+
+ newwindow->area = (xcWidget)NULL;
+ newwindow->mapped = False;
+ newwindow->psfont = 0;
+ newwindow->justify = FLIPINV;
+ newwindow->page = 0;
+ newwindow->MatStack = NULL;
+ newwindow->textscale = 1.0;
+ newwindow->linewidth = 1.0;
+ newwindow->zoomfactor = SCALEFAC;
+ newwindow->style = UNCLOSED;
+ newwindow->invert = False;
+ newwindow->axeson = True;
+ newwindow->snapto = True;
+ newwindow->gridon = True;
+ newwindow->center = True;
+ newwindow->bboxon = False;
+ newwindow->filter = ALL_TYPES;
+ newwindow->editinplace = True;
+ newwindow->selects = 0;
+ newwindow->selectlist = NULL;
+ newwindow->lastlibrary = 0;
+ newwindow->manhatn = False;
+ newwindow->boxedit = MANHATTAN;
+ newwindow->pathedit = TANGENTS;
+ newwindow->lastbackground = NULL;
+ newwindow->editstack = (objectptr) malloc(sizeof(object));
+ newwindow->stack = NULL; /* at the top of the hierarchy */
+ newwindow->hierstack = NULL;
+ initmem(newwindow->editstack);
+ newwindow->pinpointon = False;
+ newwindow->showclipmasks = True;
+ newwindow->pinattach = False;
+ newwindow->buschar = '('; /* Vector notation for buses */
+ newwindow->defaultcursor = &CROSS;
+ newwindow->event_mode = NORMAL_MODE;
+ newwindow->attachto = -1;
+ newwindow->color = DEFAULTCOLOR;
+ newwindow->gccolor = 0;
+ newwindow->gctype = 0;
+ newwindow->time_id = 0;
+ newwindow->clipmask = (Pixmap)NULL;
+ newwindow->pbuf = (Pixmap)NULL;
+ newwindow->cmgc = (GC)NULL;
+ newwindow->clipped = 0;
+ newwindow->vscale = 1;
+ newwindow->pcorner.x = newwindow->pcorner.y = 0;
+ newwindow->topinstance = (objinstptr)NULL;
+
+ /* Prepend to linked window list in global data (xobjs) */
+ newwindow->next = xobjs.windowlist;
+ xobjs.windowlist = newwindow;
+
+ return newwindow;
+}
+
+/*----------------------------------------------------------------------*/
+/* Preparatory initialization (to be run before setting up the GUI) */
+/*----------------------------------------------------------------------*/
+
+void pre_initialize()
+{
+ short i, page;
+
+ /*-------------------------------------------------------------*/
+ /* Force LC_NUMERIC locale to en_US for decimal point = period */
+ /* notation. The environment variable LC_NUMERIC overrides if */
+ /* it is set explicitly, so it has to be unset first to allow */
+ /* setlocale() to work. */
+ /*-------------------------------------------------------------*/
+
+#ifdef HAVE_PUTENV
+ putenv("LC_ALL=en_US");
+ putenv("LC_NUMERIC=en_US");
+ putenv("LANG=POSIX");
+#else
+ unsetenv("LC_ALL");
+ unsetenv("LC_NUMERIC");
+ setenv("LANG", "POSIX", 1);
+#endif
+ setlocale(LC_ALL, "en_US");
+
+ /*---------------------------*/
+ /* initialize user variables */
+ /*---------------------------*/
+
+ version = PROG_VERSION;
+ aliastop = NULL;
+ xobjs.pagelist = (Pagedata **) malloc(PAGES * sizeof(Pagedata *));
+ for (page = 0; page < PAGES; page++) {
+ xobjs.pagelist[page] = (Pagedata *) malloc(sizeof(Pagedata));
+ xobjs.pagelist[page]->pageinst = NULL;
+ xobjs.pagelist[page]->filename = NULL;
+ }
+ /* Set values for the first page */
+ xobjs.pagelist[0]->wirewidth = 2.0;
+ xobjs.pagelist[0]->outscale = 1.0;
+ xobjs.pagelist[0]->background.name = (char *)NULL;
+ xobjs.pagelist[0]->pmode = 2; /* set auto-fit ON by default */
+ xobjs.pagelist[0]->orient = 0;
+ xobjs.pagelist[0]->gridspace = DEFAULTGRIDSPACE;
+ xobjs.pagelist[0]->snapspace = DEFAULTSNAPSPACE;
+ xobjs.pagelist[0]->drawingscale.x = xobjs.pagelist[0]->drawingscale.y = 1;
+ xobjs.pagelist[0]->coordstyle = INTERNAL;
+ xobjs.pagelist[0]->pagesize.x = 612;
+ xobjs.pagelist[0]->pagesize.y = 792;
+ xobjs.pagelist[0]->margins.x = 72;
+ xobjs.pagelist[0]->margins.y = 72;
+
+ xobjs.hold = TRUE;
+ xobjs.showtech = FALSE;
+ xobjs.suspend = (char)0; /* Suspend graphics until finished with startup */
+ xobjs.new_changes = 0;
+ xobjs.filefilter = TRUE;
+ xobjs.tempfile = NULL;
+ xobjs.retain_backup = False; /* default: remove backup after file write */
+ signal(SIGINT, dointr);
+ printtime_id = 0;
+
+ xobjs.technologies = NULL;
+ xobjs.undostack = NULL;
+ xobjs.redostack = NULL;
+
+ /* Set the temporary directory name as compiled, unless overridden by */
+ /* environment variable "TMPDIR". */
+
+ xobjs.tempdir = getenv("TMPDIR");
+ if (xobjs.tempdir == NULL) xobjs.tempdir = strdup(TEMP_DIR);
+
+ xobjs.windowlist = (XCWindowDataPtr)NULL;
+ areawin = NULL;
+
+ xobjs.numlibs = LIBS - LIBRARY - 1;
+ xobjs.fontlib.number = 0;
+ xobjs.userlibs = (Library *) malloc(xobjs.numlibs * sizeof(Library));
+ for (i = 0; i < xobjs.numlibs; i++) {
+ xobjs.userlibs[i].library = (objectptr *) malloc(sizeof(objectptr));
+ xobjs.userlibs[i].instlist = NULL;
+ xobjs.userlibs[i].number = 0;
+ }
+ xobjs.imagelist = NULL;
+ xobjs.images = 0;
+ xobjs.pages = PAGES;
+
+ xobjs.libsearchpath = (char *)NULL;
+ xobjs.filesearchpath = (char *)NULL;
+
+ fontcount = 0;
+ fonts = (fontinfo *) malloc(sizeof(fontinfo));
+ fonts[0].encoding = NULL; /* To prevent segfaults */
+ fonts[0].psname = NULL;
+ fonts[0].family = NULL;
+
+ /* Initialization of objects requires values for the window width and height, */
+ /* so set up the widgets and realize them first. */
+
+ popups = 0; /* no popup windows yet */
+ beeper = 1; /* Ring bell on certain warnings or errors */
+ pressmode = 0; /* not in a button press & hold mode yet */
+ initsplines(); /* create lookup table of spline parameters */
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------------------------------*/
+/* Create a new Handle object in Tcl */
+/*----------------------------------------------------------------------*/
+
+static void UpdateStringOfHandle _ANSI_ARGS_((Tcl_Obj *objPtr));
+static int SetHandleFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr));
+
+static Tcl_ObjType tclHandleType = {
+ "handle", /* name */
+ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
+ (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ UpdateStringOfHandle, /* updateStringProc */
+ SetHandleFromAny /* setFromAnyProc */
+};
+
+/*----------------------------------------------------------------------*/
+
+static void
+UpdateStringOfHandle(objPtr)
+ Tcl_Obj *objPtr; /* Int object whose string rep to update. */
+{
+ char buffer[TCL_INTEGER_SPACE];
+ int len;
+
+ sprintf(buffer, "H%08lX", objPtr->internalRep.longValue);
+ len = strlen(buffer);
+
+ objPtr->bytes = Tcl_Alloc((u_int)len + 1);
+ strcpy(objPtr->bytes, buffer);
+ objPtr->length = len;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int
+SetHandleFromAny(interp, objPtr)
+ Tcl_Interp *interp; /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+ char *string, *end;
+ int length;
+ char *p;
+ long newLong;
+ pushlistptr newstack = NULL;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ errno = 0;
+ for (p = string; isspace((u_char)(*p)); p++);
+
+nexthier:
+
+ if (*p++ != 'H') {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "handle is identified by leading H and hexidecimal value only", -1);
+ }
+ free_stack(&newstack);
+ return TCL_ERROR;
+ } else {
+ newLong = strtoul(p, &end, 16);
+ }
+ if (end == p) {
+ badHandle:
+ if (interp != NULL) {
+ /*
+ * Must copy string before resetting the result in case a caller
+ * is trying to convert the interpreter's result to an int.
+ */
+
+ char buf[100];
+ sprintf(buf, "expected handle but got \"%.50s\"", string);
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+ }
+ free_stack(&newstack);
+ return TCL_ERROR;
+ }
+ if (errno == ERANGE) {
+ if (interp != NULL) {
+ char *s = "handle value too large to represent";
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
+ }
+ free_stack(&newstack);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure that the string has no garbage after the end of the handle.
+ */
+
+ while ((end < (string+length)) && isspace((u_char)(*end))) end++;
+ if (end != (string+length)) {
+ /* Check for handles separated by slashes. If present, */
+ /* then generate a hierstack. */
+
+ if ((end != NULL) && (*end == '/')) {
+ objinstptr refinst, chkinst;
+ genericptr *rgen;
+
+ *end = '\0';
+ newLong = strtoul(p, &end, 16);
+ p = end + 1;
+ *end = '/';
+ refinst = (newstack == NULL) ? areawin->topinstance : newstack->thisinst;
+ chkinst = (objinstptr)((pointertype)(newLong));
+ /* Ensure that chkinst is in the plist of */
+ /* refinst->thisobject, and that it is type objinst. */
+ for (rgen = refinst->thisobject->plist; rgen < refinst->thisobject->plist
+ + refinst->thisobject->parts; rgen++) {
+ if ((objinstptr)(*rgen) == chkinst) {
+ if (ELEMENTTYPE(*rgen) != OBJINST) {
+ free_stack(&newstack);
+ Tcl_SetResult(interp, "Hierarchical element handle "
+ "component is not an object instance.", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ }
+ }
+ if (rgen == refinst->thisobject->plist + refinst->thisobject->parts) {
+ Tcl_SetResult(interp, "Bad component in hierarchical "
+ "element handle.", NULL);
+ free_stack(&newstack);
+ return TCL_ERROR;
+ }
+ push_stack(&newstack, chkinst, NULL);
+ goto nexthier;
+ }
+ else
+ goto badHandle;
+ }
+
+ /* Note that this check won't prevent a hierarchical selection from */
+ /* being added to a non-hierarchical selection. */
+
+ if (areawin->hierstack != NULL) {
+ if ((newstack == NULL) || (newstack->thisinst !=
+ areawin->hierstack->thisinst)) {
+ Tcl_SetResult(interp, "Attempt to select components in different "
+ "objects.", NULL);
+ free_stack(&newstack);
+ return TCL_ERROR;
+ }
+ }
+ free_stack(&areawin->hierstack);
+ areawin->hierstack = newstack;
+
+ /*
+ * The conversion to handle succeeded. Free the old internalRep before
+ * setting the new one. We do this as late as possible to allow the
+ * conversion code, in particular Tcl_GetStringFromObj, to use that old
+ * internalRep.
+ */
+
+ if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+ oldTypePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->internalRep.longValue = newLong;
+ objPtr->typePtr = &tclHandleType;
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+
+Tcl_Obj *
+Tcl_NewHandleObj(optr)
+ void *optr; /* Int used to initialize the new object. */
+{
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewObj();
+ objPtr->bytes = NULL;
+
+ objPtr->internalRep.longValue = (long)(optr);
+ objPtr->typePtr = &tclHandleType;
+ return objPtr;
+}
+
+/*----------------------------------------------------------------------*/
+
+int
+Tcl_GetHandleFromObj(interp, objPtr, handlePtr)
+ Tcl_Interp *interp; /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr; /* The object from which to get a int. */
+ void **handlePtr; /* Place to store resulting int. */
+{
+ long l;
+ int result;
+
+ if (objPtr->typePtr != &tclHandleType) {
+ result = SetHandleFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+ l = objPtr->internalRep.longValue;
+ if (((long)((int)l)) == l) {
+ *handlePtr = (void *)objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "value too large to represent as handle", -1);
+ }
+ return TCL_ERROR;
+}
+
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Routine to initialize variables after the GUI has been set up */
+/*----------------------------------------------------------------------*/
+
+void post_initialize()
+{
+ short i;
+
+ /*--------------------------------------------------*/
+ /* Setup the (simple) colormap and make the cursors */
+ /*--------------------------------------------------*/
+
+ setcolorscheme(True);
+ makecursors();
+
+ /* Now that we have values for the window width and height, we can initialize */
+ /* the page objects. */
+
+ xobjs.libtop = (objinstptr *)malloc(LIBS * sizeof(objinstptr));
+ for (i = 0; i < LIBS; i++) {
+ objectptr newlibobj = (objectptr) malloc(sizeof(object));
+ initmem(newlibobj);
+ xobjs.libtop[i] = newpageinst(newlibobj);
+ }
+
+ /* Give names to the five default libraries */
+ strcpy(xobjs.libtop[FONTLIB]->thisobject->name, "Font Character List");
+ strcpy(xobjs.libtop[PAGELIB]->thisobject->name, "Page Directory");
+ strcpy(xobjs.libtop[LIBLIB]->thisobject->name, "Library Directory");
+ strcpy(xobjs.libtop[USERLIB]->thisobject->name, "User Library");
+ renamelib(USERLIB);
+
+ changepage(0);
+
+ /* Centering the view is not required here because the default values */
+ /* set in initmem() should correctly position the empty page in the */
+ /* middle of the viewing window. */
+
+#ifdef DOUBLEBUFFER
+ if (dbuf == (Pixmap)NULL)
+ dbuf = XCreatePixmap(dpy, areawin->window, areawin->width,
+ areawin->height, DefaultDepthOfScreen(xcScreen(areawin->area)));
+#endif
+
+#ifdef TCL_WRAPPER
+
+ /* Set up fundamentally necessary colors black and white */
+
+ addnewcolorentry(xc_alloccolor("Black"));
+ addnewcolorentry(xc_alloccolor("White"));
+
+ /* Set up new Tcl type "handle" for element handles */
+
+ Tcl_RegisterObjType(&tclHandleType);
+
+#endif
+
+ /*-----------------------------------------------------*/
+ /* Set the cursor as a crosshair for the area widget. */
+ /*-----------------------------------------------------*/
+
+ XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
+
+ /*---------------------------------------------------*/
+ /* Set up a timeout for automatic save to a tempfile */
+ /*---------------------------------------------------*/
+
+ xobjs.save_interval = appdata.timeout;
+ xobjs.timeout_id = xcAddTimeOut(app, 60000 * xobjs.save_interval,
+ savetemp, NULL);
+}
+
+/*----------------------------------------------------------------------*/
diff --git a/xcircuit.h b/xcircuit.h
new file mode 100644
index 0000000..72d67b8
--- /dev/null
+++ b/xcircuit.h
@@ -0,0 +1,1564 @@
+/*----------------------------------------------------------------------*/
+/* xcircuit.h */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* written by Tim Edwards, 8/20/93 */
+/*----------------------------------------------------------------------*/
+
+#ifndef HAVE_U_CHAR
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+typedef unsigned long long u_long;
+#endif
+
+#ifdef XC_WIN32
+#ifdef TCL_WRAPPER
+#include "tkwin32.h"
+#else
+#include "xcwin32.h"
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Graphics functions defined for X11 (i.e., not OpenGL) */
+/*----------------------------------------------------------------------*/
+
+#ifndef OPENGL
+
+#define DrawLine XDrawLine
+#define DrawLines XDrawLines
+#define DrawPoint XDrawPoint
+#define FillPolygon XFillPolygon
+
+#define SetForeground XSetForeground
+#define SetBackground XSetBackground
+#define SetFunction XSetFunction
+#define SetThinLineAttributes XSetLineAttributes
+#define SetLineAttributes(a, b, c, d, e, f) \
+ XSetLineAttributes(a, b, ((c) >= 1.55 ? (int)(c + 0.45) : 0), d, e, f)
+#define SetDashes XSetDashes
+#define SetFillStyle XSetFillStyle
+#define SetStipple(a,b,c) XSetStipple(a,b,STIPPLE[c])
+#define flusharea()
+
+#else
+
+#define SetThinLineAttributes SetLineAttributes
+#define flusharea glFlush
+
+#endif /* !OPENGL */
+
+/*----------------------------------------------------------------------*/
+/* Redefinition of fprintf() allows redirection of output to a console */
+/* in the Tcl interpreter-based version. */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+ #define Fprintf tcl_printf
+ #define Flush tcl_stdflush
+#else
+ #define Fprintf fprintf
+ #define Flush fflush
+#endif
+
+#ifdef TCL_WRAPPER
+ #define malloc Tcl_Alloc
+ /* (see definition of my_calloc in the asg subdirectory) */
+ // #define calloc(a,b) Tcl_Alloc(a * b)
+ #define free(a) Tcl_Free((char *)(a))
+ #define realloc(a,b) Tcl_Realloc((char *)(a), b)
+ #undef strdup
+ #define strdup Tcl_Strdup
+ extern char *Tcl_Strdup(const char *);
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Deal with 32/64 bit processors based on autoconf results. */
+/*----------------------------------------------------------------------*/
+
+#ifndef SIZEOF_VOID_P
+#error "SIZEOF_VOID_P undefined!"
+#endif
+#ifndef SIZEOF_UNSIGNED_INT
+#error "SIZEOF_UNSIGNED_INT undefined!"
+#endif
+#ifndef SIZEOF_UNSIGNED_LONG
+#error "SIZEOF_UNSIGNED_LONG undefined!"
+#endif
+#ifndef SIZEOF_UNSIGNED_LONG_LONG
+#error "SIZEOF_UNSIGNED_LONG_LONG undefined!"
+#endif
+
+#if SIZEOF_VOID_P == SIZEOF_UNSIGNED_INT
+#define Number(a) (void *)((u_int) a)
+typedef u_int pointertype;
+#elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG
+#define Number(a) (void *)((u_long) a)
+typedef u_long pointertype;
+#elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG_LONG
+#define Number(a) (void *)((u_long_long) a)
+typedef u_long_long pointertype;
+#else
+ERROR: Cannot compile without knowing the size of a pointer. See xcircuit.h.
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Basic element types */
+/* */
+/* These values determine how a genericptr should be cast into one of */
+/* labelptr, polyptr, etc. To query the element type, use the macros */
+/* ELEMENTTYPE(), IS_LABEL(), IS_POLYGON(), etc. These macros mask the */
+/* bit field. Note that an element marked with REMOVE_TAG will not be */
+/* recognized as any valid element, but otherwise, querying the type is */
+/* transparent to other bit settings (such as NETLIST_INVALID). */
+/*----------------------------------------------------------------------*/
+
+/* Single-bit flags */
+#define OBJINST 0x01
+#define LABEL 0x02
+#define POLYGON 0x04
+#define ARC 0x08
+#define SPLINE 0x10
+#define PATH 0x20
+#define GRAPHIC 0x40
+#define ARRAY 0x80 /* reserved; unused, for now. */
+
+#define REMOVE_TAG 0x100 /* element to be removed from netlist */
+#define NETLIST_INVALID 0x200 /* this element invalidates the netlist */
+#define SELECT_HIDE 0x400 /* this element cannot be selected */
+#define DRAW_HIDE 0x800 /* this element is not drawn. */
+
+/* Bit fields */
+#define ALL_TYPES (OBJINST | LABEL | POLYGON | ARC | SPLINE | PATH \
+ | GRAPHIC | ARRAY)
+#define VALID_TYPES (REMOVE_TAG | ALL_TYPES)
+
+/*----------------------------------------------------------------------*/
+/* Definition shortcuts */
+/*----------------------------------------------------------------------*/
+
+#define XtnSetArg(a,b) XtSetArg(wargs[n], a, b); n++
+#define abs(a) ((a) < 0 ? -(a) : (a))
+#define sign(a) ((a) <= 0 ? -1 : 1)
+#ifndef min
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Lengthier define constructs */
+/*----------------------------------------------------------------------*/
+
+/* Names used for convenience throughout the source code */
+
+#define eventmode areawin->event_mode
+#define topobject areawin->topinstance->thisobject
+#define hierobject areawin->hierstack->thisinst->thisobject
+
+#define PLIST_INCR(a) \
+ (a)->plist = (genericptr *) realloc ((a)->plist, \
+ ((a)->parts + 1) * sizeof(genericptr))
+
+#define ENDPART topobject->plist + topobject->parts - 1
+#define EDITPART topobject->plist + *areawin->selectlist
+
+/* Type checks (argument "a" is type genericptr) */
+
+#define ELEMENTTYPE(a) ((a)->type & VALID_TYPES)
+
+#define IS_POLYGON(a) (ELEMENTTYPE(a) == POLYGON)
+#define IS_LABEL(a) (ELEMENTTYPE(a) == LABEL)
+#define IS_OBJINST(a) (ELEMENTTYPE(a) == OBJINST)
+#define IS_ARC(a) (ELEMENTTYPE(a) == ARC)
+#define IS_SPLINE(a) (ELEMENTTYPE(a) == SPLINE)
+#define IS_PATH(a) (ELEMENTTYPE(a) == PATH)
+#define IS_GRAPHIC(a) (ELEMENTTYPE(a) == GRAPHIC)
+#define IS_ARRAY(a) (ELEMENTTYPE(a) == ARRAY)
+
+/* Conversions from generic to specific types */
+/* specifically, from type (genericptr *) to type (polyptr), etc. */
+
+#define TOPOLY(a) (*((polyptr *)(a)))
+#define TOLABEL(a) (*((labelptr *)(a)))
+#define TOOBJINST(a) (*((objinstptr *)(a)))
+#define TOARC(a) (*((arcptr *)(a)))
+#define TOSPLINE(a) (*((splineptr *)(a)))
+#define TOPATH(a) (*((pathptr *)(a)))
+#define TOGRAPHIC(a) (*((graphicptr *)(a)))
+#define TOGENERIC(a) (*((genericptr *)(a)))
+
+/* conversions from a selection to a specific type */
+
+#define SELTOGENERICPTR(a) ((areawin->hierstack == NULL) ? \
+ (topobject->plist + *(a)) : \
+ (hierobject->plist + *(a)))
+
+#define SELTOPOLY(a) TOPOLY(SELTOGENERICPTR(a))
+#define SELTOLABEL(a) TOLABEL(SELTOGENERICPTR(a))
+#define SELTOOBJINST(a) TOOBJINST(SELTOGENERICPTR(a))
+#define SELTOARC(a) TOARC(SELTOGENERICPTR(a))
+#define SELTOSPLINE(a) TOSPLINE(SELTOGENERICPTR(a))
+#define SELTOPATH(a) TOPATH(SELTOGENERICPTR(a))
+#define SELTOGRAPHIC(a) TOGRAPHIC(SELTOGENERICPTR(a))
+#define SELTOGENERIC(a) TOGENERIC(SELTOGENERICPTR(a))
+
+#define SELECTTYPE(a) ((SELTOGENERIC(a))->type & ALL_TYPES)
+#define SELTOCOLOR(a) ((SELTOGENERIC(a))->color)
+
+
+/* creation of new elements */
+
+#define NEW_POLY(a,b) \
+ PLIST_INCR(b); \
+ a = (polyptr *)b->plist + b->parts; \
+ *a = (polyptr) malloc(sizeof(polygon)); \
+ b->parts++; \
+ (*a)->type = POLYGON
+#define NEW_LABEL(a,b) \
+ PLIST_INCR(b); \
+ a = (labelptr *)b->plist + b->parts; \
+ *a = (labelptr) malloc(sizeof(label)); \
+ b->parts++; \
+ (*a)->type = LABEL
+#define NEW_OBJINST(a,b) \
+ PLIST_INCR(b); \
+ a = (objinstptr *)b->plist + b->parts; \
+ *a = (objinstptr) malloc(sizeof(objinst)); \
+ b->parts++; \
+ (*a)->type = OBJINST
+#define NEW_ARC(a,b) \
+ PLIST_INCR(b); \
+ a = (arcptr *)b->plist + b->parts; \
+ *a = (arcptr) malloc(sizeof(arc)); \
+ b->parts++; \
+ (*a)->type = ARC
+#define NEW_SPLINE(a,b) \
+ PLIST_INCR(b); \
+ a = (splineptr *)b->plist + b->parts; \
+ *a = (splineptr) malloc(sizeof(spline)); \
+ b->parts++; \
+ (*a)->type = SPLINE
+#define NEW_PATH(a,b) \
+ PLIST_INCR(b); \
+ a = (pathptr *)b->plist + b->parts; \
+ *a = (pathptr) malloc(sizeof(path)); \
+ b->parts++; \
+ (*a)->type = PATH
+#define NEW_GRAPHIC(a,b) \
+ PLIST_INCR(b); \
+ a = (graphicptr *)b->plist + b->parts; \
+ *a = (graphicptr) malloc(sizeof(graphic)); \
+ b->parts++; \
+ (*a)->type = GRAPHIC
+
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ float x, y;
+} XfPoint;
+
+typedef struct {
+ long x, y;
+} XlPoint;
+
+typedef struct {
+ short width, maxwidth, ascent, descent, base;
+} TextExtents;
+
+/*----------------------------------------------------------------------*/
+/* Implementation-specific definitions */
+/*----------------------------------------------------------------------*/
+
+#define LIBS 5 /* initial number of library pages */
+#define PAGES 10 /* default number of top-level pages */
+#define SCALEFAC 1.5 /* zoom in/out scaling multiplier */
+#define SUBSCALE 0.67 /* ratio of subscript size to normal script size */
+#define SBARSIZE 13 /* Pixel size of the scrollbar */
+#define RSTEPS 72 /* Number of points defining a circle approx. */
+#define SPLINESEGS 20 /* Number of points per spline approximation */
+#define DELBUFSIZE 10 /* Number of delete events to save for undeleting */
+#define MINAUTOSCALE 0.75 /* Won't automatically scale closer than this */
+#define MAXCHANGES 20 /* Number of changes to induce a temp file save */
+#define STIPPLES 8 /* Number of predefined stipple patterns */
+#define PADSPACE 10 /* Spacing of pinlabels from their origins */
+
+#ifdef HAVE_XPM
+#define TBBORDER 1 /* border around toolbar buttons */
+#endif
+
+#define TOPLEVEL 0
+#define SINGLE 1
+
+#define INTSEGS (SPLINESEGS - 2)
+#define LASTSEG (SPLINESEGS - 3)
+
+#define NOFILENAME (char *)(-1)
+
+#define FONTHEIGHT(y) (y->ascent + y->descent + 6)
+#define ROWHEIGHT FONTHEIGHT(appdata.xcfont)
+#define FILECHARASCENT (appdata.filefont->ascent)
+#define FILECHARHEIGHT (FILECHARASCENT + appdata.filefont->descent)
+#define LISTHEIGHT 200
+#define TEXTHEIGHT 28 /* Height of xcircuit vectored font at nominal size */
+#define BASELINE 40 /* Height of baseline */
+#define DEFAULTGRIDSPACE 32
+#define DEFAULTSNAPSPACE 16
+
+/*----------------------------------------------------------------------*/
+
+#define RADFAC 0.0174532925199 /* (pi / 180) */
+#define INVRFAC 57.295779 /* (180 / pi) */
+
+/*----------------------------------------------------------------------*/
+
+#define INCHSCALE 0.375 /* Scale of .25 inches to PostScript units */
+#define CMSCALE 0.35433071 /* Scale of .5 cm to PostScript units */
+#define IN_CM_CONVERT 28.3464567 /* 72 (in) / 2.54 (cm/in) */
+
+/*----------------------------------------------------------------------*/
+/* Event mode definitions (state of drawing area) */
+/* NOTE: changes to this list must be reflected in xctcl_eventmode(). */
+/*----------------------------------------------------------------------*/
+
+enum editmode {
+ NORMAL_MODE = 0, /* On the drawing page, none of the situations below */
+ UNDO_MODE, /* In the process of an undo/redo operation */
+ MOVE_MODE, /* In the process of moving elements */
+ COPY_MODE, /* In the process of copying elements */
+ PAN_MODE, /* In the process of panning to follow the cursor */
+ SELAREA_MODE, /* Area selection box */
+ PENDING_MODE, /* Temporary mode to select without drawing selection */
+ RESCALE_MODE, /* Interactive element rescaling box */
+ CATALOG_MODE, /* On a library page, library directory, or page directory */
+ CATTEXT_MODE, /* Editing an existing object name in the library */
+ FONTCAT_MODE, /* Accessing the font character page from TEXT_MODE */
+ EFONTCAT_MODE, /* Accessing the font character page from ETEXT_MODE */
+ TEXT_MODE, /* Creating a new label */
+ WIRE_MODE, /* Creating a new polygon (wire) */
+ BOX_MODE, /* Creating a new box */
+ ARC_MODE, /* Creating a new arc */
+ SPLINE_MODE, /* Creating a new spline */
+ ETEXT_MODE, /* Editing an exiting label */
+ EPOLY_MODE, /* Editing an existing polygon */
+ EARC_MODE, /* Editing an existing arc */
+ ESPLINE_MODE, /* Editing an existing spline */
+ EPATH_MODE, /* Editing an existing path */
+ EINST_MODE, /* Editing an instance (from the level above) */
+ ASSOC_MODE, /* Choosing an associated schematic or symbol */
+ CATMOVE_MODE /* Moving objects in or between libraries */
+};
+
+/*----------------------------------------------------------------------*/
+/* File loading modes */
+/*----------------------------------------------------------------------*/
+
+enum loadmodes {IMPORT = 1, PSBKGROUND, SCRIPT, RECOVER,
+#ifdef ASG
+ IMPORTSPICE,
+#endif
+ LOAD_MODES
+};
+
+/*----------------------------------------------------------------------*/
+/* Text justification styles and other parameters (bitmask) */
+/*----------------------------------------------------------------------*/
+
+#define NOTLEFT 1
+#define RIGHT 2
+#define NOTBOTTOM 4
+#define TOP 8
+#define FLIPINV 16 /* 1 if text is flip-invariant */
+#define PINVISIBLE 32 /* 1 if pin visible outside of object */
+#define PINNOOFFSET 64 /* 0 if pin label offset from position */
+#define LATEXLABEL 128
+
+#define RLJUSTFIELD 3 /* right-left justification bit field */
+#define TBJUSTFIELD 12 /* top-bottom justification bit field */
+#define NONJUSTFIELD 240 /* everything but justification fields */
+
+/*----------------------------------------------------------------------*/
+/* Text string part: types */
+/*----------------------------------------------------------------------*/
+
+#define TEXT_STRING 0 /* data is a text string */
+#define SUBSCRIPT 1 /* start subscript; no data */
+#define SUPERSCRIPT 2 /* start superscript; no data */
+#define NORMALSCRIPT 3 /* stop super-/subscript; no data */
+#define UNDERLINE 4 /* start underline; no data */
+#define OVERLINE 5 /* start overline; no data */
+#define NOLINE 6 /* stop over-/underline; no data */
+#define TABSTOP 7 /* insert tab stop position */
+#define TABFORWARD 8 /* insert tab stop position */
+#define TABBACKWARD 9 /* insert tab stop position */
+#define HALFSPACE 10 /* insert half-space; no data */
+#define QTRSPACE 11 /* insert quarter space; no data */
+#define RETURN 12 /* carriage-return character; no data */
+#define FONT_NAME 13 /* inline font designator; data = font name */
+#define FONT_SCALE 14 /* font scale change; data = scale */
+#define FONT_COLOR 15 /* font color change; data = color */
+#define MARGINSTOP 16 /* declare a width limit for the text */
+#define KERN 17 /* set new kern values; data = kern x, y */
+#define PARAM_START 18 /* bounds a parameter; data = param key */
+#define PARAM_END 19 /* bounds a parameter; no data */
+
+/* Actions translated to keystates (numbering continues from above) */
+
+#define TEXT_RETURN 20
+#define TEXT_HOME 21
+#define TEXT_END 22
+#define TEXT_SPLIT 23
+#define TEXT_DOWN 24
+#define TEXT_UP 25
+#define TEXT_LEFT 26
+#define TEXT_RIGHT 27
+#define TEXT_DELETE 28
+#define TEXT_DEL_PARAM 29
+
+#define SPECIAL 63 /* used only when called from menu */
+#define NULL_TYPE 255 /* used as a placeholder */
+
+/*----------------------------------------------------------------------*/
+/* Reset modes */
+/*----------------------------------------------------------------------*/
+
+#define SAVE 1
+#define DESTROY 2
+
+/*----------------------------------------------------------------------*/
+/* Coordinate display types */
+/*----------------------------------------------------------------------*/
+
+#define DEC_INCH 0
+#define FRAC_INCH 1
+#define CM 2
+#define INTERNAL 3
+
+/*----------------------------------------------------------------------*/
+/* Library types */
+/*----------------------------------------------------------------------*/
+
+#define FONTENCODING -1 /* Used only by libopen() */
+#define FONTLIB 0
+#define PAGELIB 1
+#define LIBLIB 2
+#define LIBRARY 3
+#define USERLIB (xobjs.numlibs + LIBRARY - 1)
+
+/*----------------------------------------------------------------------*/
+/* Object instance styles */
+/*----------------------------------------------------------------------*/
+
+#define LINE_INVARIANT 1 /* Linewidth is invariant w.r.t. scale */
+
+/*----------------------------------------------------------------------*/
+/* Box styles */
+/*----------------------------------------------------------------------*/
+
+#define NORMAL 0
+#define UNCLOSED 1
+#define DASHED 2
+#define DOTTED 4
+#define NOBORDER 8
+#define FILLED 16
+#define STIP0 32
+#define STIP1 64
+#define STIP2 128
+#define FILLSOLID 224 /* = 32 + 64 + 128 */
+#ifdef OPAQUE
+#undef OPAQUE
+#endif
+#define OPAQUE 256
+#define BBOX 512
+#define SQUARECAP 1024
+#define CLIPMASK 2048
+
+/*----------------------------------------------------------------------*/
+/* Box edit styles */
+/*----------------------------------------------------------------------*/
+
+#define NONE 0
+#define MANHATTAN 1
+#define RHOMBOIDX 2
+#define RHOMBOIDY 4
+#define RHOMBOIDA 8
+
+/*----------------------------------------------------------------------*/
+/* Path edit styles */
+/*----------------------------------------------------------------------*/
+
+#define TANGENTS 1 /* (NORMAL = 0) */
+
+/*----------------------------------------------------------------------*/
+/* Cycle points (selected points) (flag bits, can be OR'd together) */
+/*----------------------------------------------------------------------*/
+
+#define EDITX 0x01
+#define EDITY 0x02
+#define LASTENTRY 0x04
+#define PROCESS 0x08
+#define REFERENCE 0x10
+#define ANTIXY 0x20 /* For matched-tangent curves */
+
+/*----------------------------------------------------------------------*/
+/* Arc creation and edit styles */
+/*----------------------------------------------------------------------*/
+
+#define CENTER 1
+#define RADIAL 2
+
+/*----------------------------------------------------------------------*/
+/* Delete/undelete draw-mode styles */
+/*----------------------------------------------------------------------*/
+
+#define ERASE 1
+#define DRAW 1
+
+/*----------------------------------------------------------------------*/
+/* Schematic object types and pin label types */
+/*----------------------------------------------------------------------*/
+
+#define PRIMARY 0 /* Primary (master) schematic page */
+#define SECONDARY 1 /* Secondary (slave) schematic page */
+#define TRIVIAL 2 /* Symbol as non-schematic element */
+#define SYMBOL 3 /* Symbol associated with a schematic */
+#define FUNDAMENTAL 4 /* Standalone symbol */
+#define NONETWORK 5 /* Do not netlist this object */
+#define GLYPH 6 /* Symbol is a font glyph */
+
+#define LOCAL 1
+#define GLOBAL 2
+#define INFO 3
+
+#define HIERARCHY_LIMIT 256 /* Stop if recursion goes this deep */
+
+/*----------------------------------------------------------------------*/
+/* Save types. This list incorporates "ALL_PAGES", below. */
+/*----------------------------------------------------------------------*/
+
+#define CURRENT_PAGE 0 /* Current page + all associated pages */
+#define NO_SUBCIRCUITS 1 /* Current page w/o subcircuit pages */
+
+/*----------------------------------------------------------------------*/
+/* Modes used when ennumerating page totals. */
+/*----------------------------------------------------------------------*/
+
+#define INDEPENDENT 0
+#define DEPENDENT 1
+#define TOTAL_PAGES 2
+#define LINKED_PAGES 3
+#define PAGE_DEPEND 4
+#define ALL_PAGES 5
+
+/*----------------------------------------------------------------------*/
+/* Color scheme styles (other than NORMAL) */
+/*----------------------------------------------------------------------*/
+
+#define INVERSE 1
+
+/*----------------------------------------------------------------------*/
+/* Cursor definitions */
+/*----------------------------------------------------------------------*/
+
+#define NUM_CURSORS 11
+
+#define ARROW appcursors[0]
+#define CROSS appcursors[1]
+#define SCISSORS appcursors[2]
+#define COPYCURSOR appcursors[3]
+#define ROTATECURSOR appcursors[4]
+#define EDCURSOR appcursors[5]
+#define TEXTPTR appcursors[6]
+#define CIRCLE appcursors[7]
+#define QUESTION appcursors[8]
+#define WAITFOR appcursors[9]
+#define HAND appcursors[10]
+
+#define DEFAULTCURSOR (*areawin->defaultcursor)
+
+/*----------------------------------------------------------------------*/
+/* integer and floating-point coordinate list structures */
+/*----------------------------------------------------------------------*/
+
+typedef XPoint* pointlist;
+typedef XfPoint* fpointlist;
+
+/*----------------------------------------------------------------------*/
+/* Allowed parameterization types */
+/*----------------------------------------------------------------------*/
+
+enum paramwhich {
+ P_NUMERIC = 0, /* uncommitted numeric parameter */
+ P_SUBSTRING,
+ P_POSITION_X,
+ P_POSITION_Y,
+ P_STYLE,
+ P_JUSTIFY,
+ P_ANGLE1,
+ P_ANGLE2,
+ P_RADIUS,
+ P_MINOR_AXIS,
+ P_ROTATION,
+ P_SCALE,
+ P_LINEWIDTH,
+ P_COLOR,
+ P_EXPRESSION,
+ P_POSITION, /* mode only, not a real parameter */
+ NUM_PARAM_TYPES
+};
+
+/*----------------------------------------------------------------------*/
+/* Labels are constructed of strings and executables */
+/*----------------------------------------------------------------------*/
+
+typedef struct _stringpart *stringptr;
+
+typedef struct _stringpart {
+ stringptr nextpart;
+ u_char type;
+ union {
+ u_char *string;
+ int color;
+ int font;
+ int width;
+ int flags;
+ float scale;
+ short kern[2];
+ } data;
+} stringpart;
+
+/*----------------------------------------------------------------------*/
+/* structures of all main elements which can be displayed & manipulated */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Object & object instance parameter structure */
+/* (Add types as necessary) */
+/*----------------------------------------------------------------------*/
+
+enum paramtypes {XC_INT = 0, XC_FLOAT, XC_STRING, XC_EXPR};
+
+/* Object parameters: general key:value parameter model */
+/* Note that this really should be a hash table, not a linked list. . . */
+
+typedef struct _oparam *oparamptr;
+
+typedef struct _oparam {
+ char * key; /* name of the parameter */
+ u_char type; /* type is from paramtypes list above */
+ u_char which; /* what the parameter represents (P_*) */
+ union {
+ stringpart *string; /* xcircuit label type */
+ char *expr; /* TCL (string) expression */
+ int ivalue; /* also covers type short int by typecasting */
+ float fvalue;
+ } parameter; /* default or substitution value */
+ oparamptr next; /* next parameter in linked list */
+} oparam;
+
+/* Element parameters: reference back to the object's parameters */
+/* These parameters are forward-substituted when descending into */
+/* an object instance. */
+/* Note that this really should be a hash table, not a linked list. . . */
+
+typedef struct _eparam *eparamptr;
+
+typedef struct _eparam {
+ char * key; /* name of the parameter */
+ u_char flags; /* namely, bit declaring an indirect parameter */
+ union {
+ int pointno; /* point number in point array, for polygons */
+ short pathpt[2]; /* element number and point number, for paths */
+ char *refkey; /* parameter reference key, for instances */
+ } pdata;
+ eparamptr next; /* next parameter in linked list */
+} eparam;
+
+#define P_INDIRECT 0x01 /* indirect parameter indicator */
+
+/*----------------------------------------------------------------------*/
+/* Generic element type is a superset of all elements. */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type; /* type is LABEL, POLYGON, etc., from below */
+ int color;
+ eparamptr passed;
+} generic, *genericptr; /* (convenience function for retypecasting) */
+
+/*----------------------------------------------------------------------*/
+/* selection-mechanism structures */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ short number;
+ genericptr *element;
+ short *idx;
+} uselection;
+
+typedef struct {
+ short number;
+ u_char flags;
+} pointselect;
+
+/*----------------------------------------------------------------------*/
+/* Bounding box */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ XPoint lowerleft;
+ Dimension width, height;
+} BBox;
+
+/*----------------------------------------------------------------------*/
+/* Object instance type */
+/*----------------------------------------------------------------------*/
+
+typedef struct _xcobject *objectptr;
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ u_short style;
+ XPoint position;
+ short rotation;
+ float scale;
+ objectptr thisobject;
+ oparamptr params; /* parameter substitutions for this instance */
+ BBox bbox; /* per-instance bounding box information */
+ BBox *schembbox; /* Extra bounding box for pin labels */
+} objinst, *objinstptr;
+
+/* Linked-list for objects */
+
+typedef struct _objlist *objlistptr;
+
+typedef struct _objlist {
+ int libno; /* library in which object appears */
+ objectptr thisobject; /* pointer to the object */
+ objlistptr next;
+} objlist;
+
+/* Linked-list for object instances */
+
+typedef struct _pushlist *pushlistptr;
+
+typedef struct _pushlist {
+ objinstptr thisinst;
+ char *clientdata; /* general-purpose record */
+ pushlistptr next;
+} pushlist;
+
+/* Same as above, but for the list of instances in a library, so it */
+/* needs an additional record showing whether or not the instance is */
+/* "virtual" (not the primary library instance of the object) */
+
+typedef struct _liblist *liblistptr;
+
+typedef struct _liblist {
+ objinstptr thisinst;
+ u_char virtual;
+ liblistptr next;
+} liblist;
+
+/*----------------------------------------------------------------------*/
+/* Generalized graphic object (Tcl/Tk only) */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color; /* foreground, for bitmaps only */
+ eparamptr passed; /* numerical parameters passed from above */
+ XPoint position;
+ short rotation;
+ float scale;
+ XImage *source; /* source data */
+ XImage *target; /* target (scaled) data */
+ short trot; /* target rotation */
+ float tscale; /* target scale (0 = uninitialized) */
+ Pixmap clipmask; /* clipmask for non-manhattan rotations */
+ Boolean valid; /* does target need to be regenerated? */
+} graphic, *graphicptr;
+
+/*----------------------------------------------------------------------*/
+/* Label */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ pointselect *cycle; /* Edit position(s), or NULL */
+ XPoint position;
+ short rotation;
+ float scale;
+ short justify;
+ u_char pin;
+ stringpart *string;
+} label, *labelptr;
+
+/*----------------------------------------------------------------------*/
+/* Polygon */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ u_short style;
+ float width;
+ pointselect *cycle; /* Edit position(s), or NULL */
+ short number;
+ pointlist points;
+} polygon, *polyptr;
+
+/*----------------------------------------------------------------------*/
+/* Bezier Curve */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ u_short style;
+ float width;
+ pointselect *cycle; /* Edit position(s), or NULL */
+ XPoint ctrl[4];
+ /* the following are for rendering only */
+ XfPoint points[INTSEGS];
+} spline, *splineptr;
+
+/*----------------------------------------------------------------------*/
+/* Arc */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ u_short style;
+ float width;
+ pointselect *cycle; /* Edit position(s), or NULL */
+ short radius; /* x-axis radius */
+ short yaxis; /* y-axis radius */
+ float angle1; /* endpoint angles, in degrees */
+ float angle2;
+ XPoint position;
+ /* the following are for rendering only */
+ short number;
+ XfPoint points[RSTEPS + 1];
+} arc, *arcptr;
+
+/*----------------------------------------------------------------------*/
+/* Path */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ u_short type;
+ int color;
+ eparamptr passed; /* numerical parameters passed from above */
+ u_short style;
+ float width;
+ short parts;
+ genericptr *plist; /* to be retypecast to polygon, arc, or spline */
+} path, *pathptr;
+
+/*----------------------------------------------------------------------*/
+/* selection from top-level object */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* Undo mechanism definitions */
+/*----------------------------------------------------------------------*/
+
+enum UNDO_MODES {UNDO_DONE = 0, UNDO_MORE, MODE_CONNECT, MODE_RECURSE_WIDE,
+ MODE_RECURSE_NARROW};
+
+typedef struct _selection *selectionptr;
+
+typedef struct _selection {
+ int selects;
+ short *selectlist;
+ objinstptr thisinst;
+ selectionptr next;
+} selection;
+
+#define select_element(a) recurse_select_element(a, UNDO_MORE)
+#define select_add_element(a) recurse_select_element(a, UNDO_DONE)
+
+#define easydraw(a, b) geneasydraw(a, b, topobject, areawin->topinstance)
+
+/*----------------------------------------------------------------------*/
+/* Netlist structures for schematic capture */
+/*----------------------------------------------------------------------*/
+
+/* Structure to hold net and subnet IDs for a bus */
+
+typedef struct {
+ int netid;
+ int subnetid;
+} buslist;
+
+/* Structure mimicking the top part of a Polylist or Labellist */
+/* when we just want the netlist information and don't care */
+/* which one we're looking at. */
+
+typedef struct {
+ union {
+ int id;
+ buslist *list;
+ } net;
+ int subnets;
+} Genericlist;
+
+/* Linked polygon list */
+
+typedef struct _Polylist *PolylistPtr;
+typedef struct _Polylist
+{
+ union {
+ int id; /* A single net ID, if subnets == 0 */
+ buslist *list; /* List of net and subnet IDs for a bus */
+ } net;
+ int subnets; /* Number of subnets; 0 if no subnets */
+ objectptr cschem; /* Schematic containing the polygon */
+ polyptr poly;
+ PolylistPtr next; /* Next polygon in the linked list */
+} Polylist;
+
+/* Linked label list */
+
+typedef struct _Labellist *LabellistPtr;
+typedef struct _Labellist
+{
+ union {
+ int id; /* A single net ID, if subnets == 0 */
+ buslist *list; /* List of net and subnet IDs for a bus */
+ } net;
+ int subnets; /* Number of subnets; 0 if no subnets */
+ objectptr cschem; /* Schematic containing the label */
+ objinstptr cinst; /* Specific label instance, if applicable */
+ labelptr label;
+ LabellistPtr next;
+} Labellist;
+
+/* List of object's networks by (flattened) name */
+
+typedef struct _Netname *NetnamePtr;
+typedef struct _Netname
+{
+ int netid;
+ stringpart *localpin;
+ NetnamePtr next;
+} Netname;
+
+/* List of object's I/O ports */
+
+typedef struct _Portlist *PortlistPtr;
+typedef struct _Portlist
+{
+ int portid;
+ int netid;
+ PortlistPtr next;
+} Portlist;
+
+/* List of calls to instances of objects */
+/* or subcircuit objects. */
+
+typedef struct _Calllist *CalllistPtr;
+typedef struct _Calllist
+{
+ objectptr cschem; /* Schematic containing the instance called */
+ objinstptr callinst; /* Instance called */
+ objectptr callobj; /* Object of instance called */
+ char *devname; /* if non-null, name of device in netlist */
+ int devindex; /* if non-negative, index of device in netlist */
+ PortlistPtr ports;
+ CalllistPtr next;
+} Calllist;
+
+/* PCB netlist structures */
+
+struct Pnet {
+ int numnets;
+ int *netidx;
+ struct Pnet *next;
+};
+
+struct Pstr {
+ stringpart *string;
+ struct Pstr *next;
+};
+
+struct Ptab {
+ objectptr cschem;
+ struct Pnet *nets;
+ struct Pstr *pins;
+ struct Ptab *next;
+};
+
+/*----------------------------------------------------------------------*/
+/* Information needed to highlight a net */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ Genericlist *netlist;
+ objinstptr thisinst;
+} Highlight;
+
+/*----------------------------------------------------------------------*/
+/* Main object structure */
+/*----------------------------------------------------------------------*/
+
+typedef struct _xcobject {
+ char name[80];
+ u_short changes; /* Number of unsaved changes to object */
+ Boolean hidden;
+ float viewscale;
+ XPoint pcorner; /* position relative to window */
+ BBox bbox; /* bounding box information (excluding */
+ /* parameterized elements) */
+ short parts;
+ genericptr *plist; /* to be retypecast to label, polygon, etc. */
+ oparamptr params; /* list of parameters, with default values */
+
+ Highlight highlight; /* net to be highlighted on redraw */
+ u_char schemtype;
+ objectptr symschem; /* schematic page support */
+ Boolean valid; /* Is current netlist valid? */
+ Boolean traversed; /* Flag to indicate object was processed */
+ LabellistPtr labels; /* Netlist pins */
+ PolylistPtr polygons; /* Netlist wires */
+ PortlistPtr ports; /* Netlist ports */
+ CalllistPtr calls; /* Netlist subcircuits and connections */
+ NetnamePtr netnames; /* Local names for flattening */
+ /* (this probably shouldn't be here. . .) */
+} object;
+
+/*----------------------------------------------------------------------*/
+/* Transformation matrices */
+/* Works like this (see also PostScript reference manual): */
+/* [x' y' 1] = [x y 1] * | a d 0 | */
+/* | b e 0 | */
+/* | c f 1 | */
+/*----------------------------------------------------------------------*/
+
+typedef struct _matrix *Matrixptr;
+
+typedef struct _matrix {
+ float a, b, c, d, e, f;
+ Matrixptr nextmatrix;
+} Matrix;
+
+/*----------------------------------------------------------------------*/
+/* Some convenience functions for matrix manipulation */
+/*----------------------------------------------------------------------*/
+
+#define DCTM areawin->MatStack
+
+/*----------------------------------------------------------------------*/
+/* button tap/press definitions */
+/*----------------------------------------------------------------------*/
+
+#define PRESSTIME 200 /* milliseconds of push to be a "press" */
+
+/*----------------------------------------------------------------------*/
+/* object name alias structures */
+/*----------------------------------------------------------------------*/
+
+typedef struct _stringlist *slistptr;
+
+typedef struct _stringlist {
+ char *alias;
+ slistptr next;
+} stringlist;
+
+typedef struct _alias *aliasptr;
+
+typedef struct _alias {
+ objectptr baseobj; /* pointer to object (actual name) */
+ slistptr aliases; /* linked list of alias names */
+ aliasptr next;
+} alias;
+
+/*----------------------------------------------------------------------*/
+/* To facilitate compiling the Tcl/Tk version, we make some convenient */
+/* definitions for types "xc..." and "Xc..." which can be mapped both */
+/* to X and Xt or to Tk functions and types. */
+/*----------------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+#define xcWidget Tk_Window
+#define xcWidgetList Tk_Window *
+#define xcAddEventHandler(a,b,c,d,e) Tk_CreateEventHandler(a,b,d,e)
+#define xcRemoveEventHandler(a,b,c,d,e) Tk_DeleteEventHandler(a,b,d,e)
+#define xcEventHandler Tk_EventProc *
+#define xcWindow Tk_WindowId
+#define xcIsRealized Tk_IsMapped /* not sure this is right */
+#define xcScreen Tk_Screen
+#define xcParent Tk_Parent
+#define xcDispatchEvent(a) Tk_HandleEvent(a)
+#define xcAddTimeOut(a, b, c, d) Tcl_CreateTimerHandler((int)(b), c, d)
+#define xcRemoveTimeOut Tcl_DeleteTimerHandler
+#define xcTimeOutProc Tcl_TimerProc *
+#define xcIntervalId Tcl_TimerToken
+
+#else
+
+#define xcWidget Widget
+#define xcWidgetList WidgetList
+#define xcAddEventHandler XtAddEventHandler
+#define xcRemoveEventHandler XtRemoveEventHandler
+#define xcEventHandler XtEventHandler
+#define xcWindow XtWindow
+#define xcIsRealized XtIsRealized
+#define xcScreen XtScreen
+#define xcParent XtParent
+#define xcDispatchEvent(a) XtDispatchEvent(a)
+#define xcAddTimeOut XtAppAddTimeOut
+#define xcRemoveTimeOut XtRemoveTimeOut
+#define xcTimeOutProc XtTimerCallbackProc
+#define xcIntervalId XtIntervalId
+#ifndef ClientData
+ #define ClientData XtPointer
+#endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/* structures for managing the popup prompt widgets */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ xcWidget button;
+ int foreground;
+ void (*buttoncall)();
+ void *dataptr;
+} buttonsave;
+
+typedef struct {
+ xcWidget popup; /* Popup widget */
+ xcWidget textw; /* Text entry widget */
+ xcWidget filew; /* File list window */
+ xcWidget scroll; /* Scrollbar widget */
+ void (*setvalue)(); /* Callback function */
+ buttonsave *buttonptr; /* Button widget calling popup */
+ char *filter; /* Extension filter for highlighting */
+ /* files. NULL for no file window. */
+ /* NULL-string for no highlights. */
+} popupstruct;
+
+typedef struct {
+ xcWidget textw;
+ xcWidget buttonw;
+ void (*setvalue)();
+ void *dataptr;
+} propstruct;
+
+typedef struct {
+ char *filename;
+ int filetype;
+} fileliststruct;
+
+enum {DIRECTORY = 0, MATCH, NONMATCH}; /* file types */
+
+/*----------------------------------------------------------------------*/
+/* Initial Resource Management */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ /* schematic layout colors */
+ Pixel globalcolor, localcolor, infocolor, ratsnestcolor;
+
+ /* non-schematic layout color(s) */
+ Pixel bboxpix, clipcolor;
+
+ /* color scheme 1 */
+ Pixel fg, bg;
+ Pixel gridpix, snappix, selectpix, axespix;
+ Pixel buttonpix, filterpix, auxpix, barpix, parampix;
+
+ /* color scheme 2 */
+ Pixel fg2, bg2;
+ Pixel gridpix2, snappix2, selectpix2, axespix2;
+ Pixel buttonpix2, auxpix2, parampix2;
+
+ int width, height, timeout;
+ XFontStruct *filefont;
+
+#ifndef TCL_WRAPPER
+ XFontStruct *xcfont, *textfont, *titlefont, *helpfont;
+#endif
+
+} ApplicationData, *ApplicationDataPtr;
+
+/*----------------------------------------------------------------------*/
+/* Macros for GC color and function handling */
+/*----------------------------------------------------------------------*/
+
+#define XTopSetForeground(a) if (a == DEFAULTCOLOR) SetForeground(dpy, \
+ areawin->gc, FOREGROUND); else SetForeground(dpy, areawin->gc, a)
+
+#define XSetXORFg(a,b) if (a == DEFAULTCOLOR) SetForeground(dpy, \
+ areawin->gc, FOREGROUND ^ b); else SetForeground(dpy, areawin->gc,\
+ a ^ b)
+
+#define XcSetFunction(z) SetFunction(dpy, areawin->gc, z); \
+ areawin->gctype = z
+
+#define XcTopSetForeground(z) XTopSetForeground(z); areawin->gccolor = \
+ ((z) == DEFAULTCOLOR) ? FOREGROUND : (z)
+
+#define XcSetForeground(z) SetForeground(dpy, areawin->gc, z); \
+ areawin->gccolor = z
+
+#define XcSetXORFg(y,z) XSetXORFg(y,z); areawin->gccolor = \
+ ((y) == DEFAULTCOLOR) ? (FOREGROUND ^ z) : (y ^ z)
+
+/*----------------------------------------------------------------------*/
+/* Structure for maintaining list of colors */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ xcWidget cbutton;
+ XColor color;
+} colorindex;
+
+/*----------------------------------------------------------------------*/
+/* Font information structure */
+/*----------------------------------------------------------------------*/
+/* Flags: bit description */
+/* 0 bold = 1, normal = 0 */
+/* 1 italic = 1, normal = 0 */
+/* 2 <reserved, possibly for narrow font type> */
+/* 3 drawn = 1, PostScript = 0 */
+/* 4 <reserved, possibly for LaTeX font type> */
+/* 5 special encoding = 1, Standard Encoding = 0 */
+/* 6 ISOLatin1 = 2, ISOLatin2 = 3 */
+/* 7 <reserved for other encoding schemes> */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ char *psname;
+ char *family;
+ float scale;
+ u_short flags;
+ objectptr *encoding;
+} fontinfo;
+
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ char *name;
+ BBox bbox;
+} psbkground;
+
+/*----------------------------------------------------------------------*/
+/* Key macro information */
+/*----------------------------------------------------------------------*/
+
+typedef struct _keybinding *keybindingptr;
+
+typedef struct _keybinding {
+ xcWidget window; /* per-window function, or NULL */
+ int keywstate;
+ int function;
+ short value;
+ keybindingptr nextbinding;
+} keybinding;
+
+/*----------------------------------------------------------------------*/
+/* Enumeration of functions available for binding to keys/buttons */
+/* IMPORTANT! Do not alter this list without also fixing the text */
+/* in keybindings.c! */
+/*----------------------------------------------------------------------*/
+
+enum {
+ XCF_ENDDATA = -2, XCF_SPACER /* -1 */,
+ XCF_Page /* 0 */, XCF_Justify /* 1 */,
+ XCF_Superscript /* 2 */, XCF_Subscript /* 3 */,
+ XCF_Normalscript /* 4 */, XCF_Font /* 5 */,
+ XCF_Boldfont /* 6 */, XCF_Italicfont /* 7 */,
+ XCF_Normalfont /* 8 */, XCF_Underline /* 9 */,
+ XCF_Overline /* 10 */, XCF_ISO_Encoding /* 11 */,
+ XCF_Halfspace /* 12 */, XCF_Quarterspace /* 13 */,
+ XCF_Special /* 14 */, XCF_TabStop /* 15 */,
+ XCF_TabForward /* 16 */, XCF_TabBackward /* 17 */,
+ XCF_Text_Return /* 18 */, XCF_Text_Delete /* 19 */,
+ XCF_Text_Right /* 20 */, XCF_Text_Left /* 21 */,
+ XCF_Text_Up /* 22 */, XCF_Text_Down /* 23 */,
+ XCF_Text_Split /* 24 */, XCF_Text_Home /* 25 */,
+ XCF_Text_End /* 26 */, XCF_Linebreak /* 27 */,
+ XCF_Parameter /* 28 */, XCF_Edit_Param /* 29 */,
+ XCF_ChangeStyle /* 30 */, XCF_Edit_Delete /* 31 */,
+ XCF_Edit_Insert /* 32 */, XCF_Edit_Append /* 33 */,
+ XCF_Edit_Next /* 34 */, XCF_Attach /* 35 */,
+ XCF_Next_Library /* 36 */, XCF_Library_Directory /* 37 */,
+ XCF_Library_Move /* 38 */, XCF_Library_Copy /* 39 */,
+ XCF_Library_Edit /* 40 */, XCF_Library_Delete /* 41 */,
+ XCF_Library_Duplicate /* 42 */, XCF_Library_Hide /* 43 */,
+ XCF_Library_Virtual /* 44 */, XCF_Page_Directory /* 45 */,
+ XCF_Library_Pop /* 46 */, XCF_Virtual /* 47 */,
+ XCF_Help /* 48 */, XCF_Redraw /* 49 */,
+ XCF_View /* 50 */, XCF_Zoom_In /* 51 */,
+ XCF_Zoom_Out /* 52 */, XCF_Pan /* 53 */,
+ XCF_Double_Snap /* 54 */, XCF_Halve_Snap /* 55 */,
+ XCF_Write /* 56 */, XCF_Rotate /* 57 */,
+ XCF_Flip_X /* 58 */, XCF_Flip_Y /* 59 */,
+ XCF_Snap /* 60 */, XCF_SnapTo /* 61 */,
+ XCF_Pop /* 62 */, XCF_Push /* 63 */,
+ XCF_Delete /* 64 */, XCF_Select /* 65 */,
+ XCF_Box /* 66 */, XCF_Arc /* 67 */,
+ XCF_Text /* 68 */, XCF_Exchange /* 69 */,
+ XCF_Copy /* 70 */, XCF_Move /* 71 */,
+ XCF_Join /* 72 */, XCF_Unjoin /* 73 */,
+ XCF_Spline /* 74 */, XCF_Edit /* 75 */,
+ XCF_Undo /* 76 */, XCF_Redo /* 77 */,
+ XCF_Select_Save /* 78 */, XCF_Unselect /* 79 */,
+ XCF_Dashed /* 80 */, XCF_Dotted /* 81 */,
+ XCF_Solid /* 82 */, XCF_Prompt /* 83 */,
+ XCF_Dot /* 84 */, XCF_Wire /* 85 */,
+ XCF_Cancel /* 86 */, XCF_Nothing /* 87 */,
+ XCF_Exit /* 88 */, XCF_Netlist /* 89 */,
+ XCF_Swap /* 90 */, XCF_Pin_Label /* 91 */,
+ XCF_Pin_Global /* 92 */, XCF_Info_Label /* 93 */,
+ XCF_Graphic /* 94 */, XCF_SelectBox /* 95 */,
+ XCF_Connectivity /* 96 */, XCF_Continue_Element /* 97 */,
+ XCF_Finish_Element /* 98 */, XCF_Continue_Copy /* 99 */,
+ XCF_Finish_Copy /* 100 */, XCF_Finish /* 101 */,
+ XCF_Cancel_Last /* 102 */, XCF_Sim /* 103 */,
+ XCF_SPICE /* 104 */, XCF_PCB /* 105 */,
+ XCF_SPICEflat /* 106 */, XCF_Rescale /* 107 */,
+ XCF_Reorder /* 108 */, XCF_Color /* 109 */,
+ XCF_Margin_Stop /* 110 */, XCF_Text_Delete_Param /* 111 */,
+ NUM_FUNCTIONS
+};
+
+/*----------------------------------------------------------------------*/
+/* Per-drawing-page parameters */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ /* per-drawing-page parameters */
+ objinstptr pageinst;
+ char *filename; /* file to save as */
+ u_char idx; /* page index */
+ psbkground background; /* background rendered file info */
+ float wirewidth;
+ float outscale;
+ float gridspace;
+ float snapspace;
+ short orient;
+ short pmode;
+ short coordstyle;
+ XPoint drawingscale;
+ XPoint pagesize; /* size of page to print on */
+ XPoint margins;
+} Pagedata;
+
+/*----------------------------------------------------------------------*/
+/* Structure holding information about graphic images used. These hold */
+/* the original data for the images, and may be shared. */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ XImage *image;
+ int refcount;
+ char *filename;
+} Imagedata;
+
+/*----------------------------------------------------------------------*/
+/* The main globally-accessible data structure. This structure holds */
+/* all the critical data needed by the drawing window */
+/*----------------------------------------------------------------------*/
+
+typedef struct _windowdata *XCWindowDataPtr;
+
+typedef struct _windowdata {
+
+ XCWindowDataPtr next; /* next window in list */
+
+ /* widgets and X11 parameters */
+ xcWidget area;
+ xcWidget scrollbarh, scrollbarv;
+ Window window;
+ GC gc;
+ Pixmap clipmask;
+ Pixmap pbuf; /* clipmask buffer for hierarchical clipping */
+ char clipped;
+ GC cmgc;
+ int gccolor, gctype;
+ xcIntervalId time_id;
+
+ /* global page parameters */
+ short width, height;
+ short page;
+ float vscale; /* proper scale */
+ XPoint pcorner; /* page position */
+
+ /* global option defaults */
+ float textscale;
+ float linewidth;
+ float zoomfactor;
+ short psfont;
+ short justify;
+ u_short style;
+ int color;
+ short filter; /* selection filter */
+ Boolean manhatn;
+ Boolean boxedit;
+ Boolean pathedit;
+ Boolean snapto;
+ Boolean bboxon;
+ Boolean center;
+ Boolean gridon;
+ Boolean axeson;
+ Boolean invert;
+ Boolean mapped; /* indicates if window is drawable */
+ char buschar; /* Character indicating vector notation */
+ Boolean editinplace;
+ Boolean pinpointon;
+ Boolean pinattach; /* keep wires attached to pins when moving objinsts */
+ Boolean showclipmasks; /* draw clipmask shape outlines */
+#ifndef TCL_WRAPPER
+#ifdef HAVE_XPM
+ Boolean toolbar_on;
+#endif
+#endif
+
+ /* buffers and associated variables */
+ XPoint save, origin;
+ short selects;
+ short *selectlist;
+ short attachto;
+ short lastlibrary;
+ short textpos;
+ short textend;
+ objinstptr topinstance;
+ objectptr editstack;
+ Matrixptr MatStack;
+ pushlistptr stack;
+ pushlistptr hierstack;
+ short event_mode;
+ char *lastbackground;
+ Cursor *defaultcursor;
+} XCWindowData;
+
+/* Record for undo function */
+
+typedef struct _undostack *Undoptr;
+
+typedef struct _undostack {
+ Undoptr next; /* next record in undo stack */
+ Undoptr last; /* double-linked for "redo" function */
+ u_int type; /* type of event */
+ short idx; /* counter for undo event */
+ objinstptr thisinst; /* instance of object in which event occurred */
+ XCWindowData *window;/* window in which event occurred */
+ int idata; /* simple undedicated integer datum */
+ char *undodata; /* free space to be malloc'd */
+ /* (size dependent on "type") */
+} Undostack;
+
+/* This whole thing needs to be cleaned up. . . now I've got objects in */
+/* "library" which are repeated both in the "instlist" pair and the */
+/* "thisobject" pointer in each instance. The instance is repeated on */
+/* the library page. Ideally, the instance list should only exist on */
+/* the library page, and not be destroyed on every call to "composelib" */
+
+typedef struct {
+ short number;
+ objectptr *library;
+ liblistptr instlist; /* List of instances */
+} Library;
+
+typedef struct _Technology *TechPtr;
+
+typedef struct _Technology {
+ u_char flags; /* Flags for library page (changed, read-only) */
+ char *technology; /* Namespace name (without the "::") */
+ char *filename; /* Library file associated with technology */
+ TechPtr next; /* Linked list */
+} Technology;
+
+/* Known flags for library pages */
+
+#define TECH_CHANGED 0x01
+#define TECH_READONLY 0x02 /* Technology file not writable */
+#define TECH_IMPORTED 0x04 /* Loaded only part of file */
+#define TECH_REPLACE 0x08 /* Replace instances when reading */
+#define TECH_REPLACE_TEMP 0x10 /* Temporary store */
+#define TECH_USED 0x20 /* Temporary marker flag */
+
+/*----------------------------------------------------------------------*/
+/* A convenient structure for holding all the object lists */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ char *libsearchpath; /* list of directories to search */
+ char *filesearchpath; /* list of directories to search */
+ char *tempfile;
+ char *tempdir;
+ Boolean retain_backup;
+ xcIntervalId timeout_id;
+ int save_interval;
+ Boolean filefilter; /* Is the file list filtered? */
+ Boolean hold; /* allow HOLD modifiers on buttons */
+ Boolean showtech; /* Write technology names in library */
+ u_short new_changes;
+ char suspend; /* suspend graphics updates if TRUE */
+ short numlibs;
+ short pages;
+ Pagedata **pagelist;
+ Undoptr undostack; /* actions to undo */
+ Undoptr redostack; /* actions to redo */
+ Library fontlib;
+ Library *userlibs;
+ TechPtr technologies;
+ objinstptr *libtop;
+ Imagedata *imagelist;
+ short images;
+ XCWindowData *windowlist; /* linked list of known windows */
+} Globaldata;
+
+/*----------------------------------------------------------------------*/
+/* structures previously defined in menudefs.h */
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+/* Menu Definitions for hierarchical pulldown menus */
+/*----------------------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+typedef struct _menustruct *menuptr;
+
+typedef struct _menustruct {
+ char *name;
+ menuptr submenu;
+ short size;
+ XtCallbackProc func;
+ void *passeddata;
+} menustruct;
+
+/*----------------------------------------------------------------------*/
+/* Structure for calling routines from the Toolbar icons */
+/*----------------------------------------------------------------------*/
+
+typedef struct _toolbarstruct *toolbarptr;
+
+typedef struct _toolbarstruct {
+ char *name;
+ char **icon_data;
+ XtCallbackProc func;
+ void *passeddata;
+ char *hint;
+} toolbarstruct;
+
+#endif
+/* Menus and Toolbars are taken care of entirely by scripts in the Tcl/ */
+/* Tk version of xcircuit. */
+/*----------------------------------------------------------------------*/
diff --git a/xcircuit.spec.in b/xcircuit.spec.in
new file mode 100644
index 0000000..9c80d26
--- /dev/null
+++ b/xcircuit.spec.in
@@ -0,0 +1,43 @@
+Name: xcircuit
+Version: %VERSION%
+Release: 1
+Summary: Electronic circuit schematic drawing program
+Group: Applications/Engineering
+License: GPL
+URL: http://opencircuitdesign.com/xcircuit/index.html
+Source: http://opencircuitdesign.com/xcircuit/archive/%{name}-%{version}.tgz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: libX11-devel, libXt-devel, tcl-devel, tk-devel
+Requires: libX11, libXt, tcl, tk
+
+%description
+Xcircuit is a general-purpose drawing program and also a specific-purpose
+CAD program for circuit schematic drawing and schematic capture. The output
+format is PostScript.
+
+%prep
+%setup -q
+
+%build
+%configure \
+ --with-tcl=%{_libdir} \
+ --with-tk=%{_libdir} \
+ --with-tclincls=%{_includedir} \
+ --with-tkincls=%{_includedir} \
+ --with-tcllibs=%{_libdir} \
+ --with-tklibs=%{_libdir}
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+%doc CHANGES COPYRIGHT README README.* TODO VERSION
+%{_bindir}/xcircuit
+/usr/lib/xcircuit-3.7/*
+
diff --git a/xcwin32-colors.h b/xcwin32-colors.h
new file mode 100644
index 0000000..340fa15
--- /dev/null
+++ b/xcwin32-colors.h
@@ -0,0 +1,755 @@
+static struct { char *name; int red, green, blue; } X11Colors[] = {
+{"snow", 255, 250, 250},
+{"ghost white", 248, 248, 255},
+{"GhostWhite", 248, 248, 255},
+{"white smoke", 245, 245, 245},
+{"WhiteSmoke", 245, 245, 245},
+{"gainsboro", 220, 220, 220},
+{"floral white", 255, 250, 240},
+{"FloralWhite", 255, 250, 240},
+{"old lace", 253, 245, 230},
+{"OldLace", 253, 245, 230},
+{"linen", 250, 240, 230},
+{"antique white", 250, 235, 215},
+{"AntiqueWhite", 250, 235, 215},
+{"papaya whip", 255, 239, 213},
+{"PapayaWhip", 255, 239, 213},
+{"blanched almond", 255, 235, 205},
+{"BlanchedAlmond", 255, 235, 205},
+{"bisque", 255, 228, 196},
+{"peach puff", 255, 218, 185},
+{"PeachPuff", 255, 218, 185},
+{"navajo white", 255, 222, 173},
+{"NavajoWhite", 255, 222, 173},
+{"moccasin", 255, 228, 181},
+{"cornsilk", 255, 248, 220},
+{"ivory", 255, 255, 240},
+{"lemon chiffon", 255, 250, 205},
+{"LemonChiffon", 255, 250, 205},
+{"seashell", 255, 245, 238},
+{"honeydew", 240, 255, 240},
+{"mint cream", 245, 255, 250},
+{"MintCream", 245, 255, 250},
+{"azure", 240, 255, 255},
+{"alice blue", 240, 248, 255},
+{"AliceBlue", 240, 248, 255},
+{"lavender", 230, 230, 250},
+{"lavender blush", 255, 240, 245},
+{"LavenderBlush", 255, 240, 245},
+{"misty rose", 255, 228, 225},
+{"MistyRose", 255, 228, 225},
+{"white", 255, 255, 255},
+{"black", 0, 0, 0},
+{"dark slate", 47, 79, 79},
+{"DarkSlateGray", 47, 79, 79},
+{"dark slate", 47, 79, 79},
+{"DarkSlateGrey", 47, 79, 79},
+{"dim gray", 105, 105, 105},
+{"DimGray", 105, 105, 105},
+{"dim grey", 105, 105, 105},
+{"DimGrey", 105, 105, 105},
+{"slate gray", 112, 128, 144},
+{"SlateGray", 112, 128, 144},
+{"slate grey", 112, 128, 144},
+{"SlateGrey", 112, 128, 144},
+{"light slate", 119, 136, 153},
+{"LightSlateGray", 119, 136, 153},
+{"light slate", 119, 136, 153},
+{"LightSlateGrey", 119, 136, 153},
+{"gray", 190, 190, 190},
+{"grey", 190, 190, 190},
+{"light grey", 211, 211, 211},
+{"LightGrey", 211, 211, 211},
+{"light gray", 211, 211, 211},
+{"LightGray", 211, 211, 211},
+{"midnight blue", 25, 25, 112},
+{"MidnightBlue", 25, 25, 112},
+{"navy", 0, 0, 128},
+{"navy blue", 0, 0, 128},
+{"NavyBlue", 0, 0, 128},
+{"cornflower blue", 100, 149, 237},
+{"CornflowerBlue", 100, 149, 237},
+{"dark slate", 72, 61, 139},
+{"DarkSlateBlue", 72, 61, 139},
+{"slate blue", 106, 90, 205},
+{"SlateBlue", 106, 90, 205},
+{"medium slate", 123, 104, 238},
+{"MediumSlateBlue", 123, 104, 238},
+{"light slate", 132, 112, 255},
+{"LightSlateBlue", 132, 112, 255},
+{"medium blue", 0, 0, 205},
+{"MediumBlue", 0, 0, 205},
+{"royal blue", 65, 105, 225},
+{"RoyalBlue", 65, 105, 225},
+{"blue", 0, 0, 255},
+{"dodger blue", 30, 144, 255},
+{"DodgerBlue", 30, 144, 255},
+{"deep sky", 0, 191, 255},
+{"DeepSkyBlue", 0, 191, 255},
+{"sky blue", 135, 206, 235},
+{"SkyBlue", 135, 206, 235},
+{"light sky", 135, 206, 250},
+{"LightSkyBlue", 135, 206, 250},
+{"steel blue", 70, 130, 180},
+{"SteelBlue", 70, 130, 180},
+{"light steel", 176, 196, 222},
+{"LightSteelBlue", 176, 196, 222},
+{"light blue", 173, 216, 230},
+{"LightBlue", 173, 216, 230},
+{"powder blue", 176, 224, 230},
+{"PowderBlue", 176, 224, 230},
+{"pale turquoise", 175, 238, 238},
+{"PaleTurquoise", 175, 238, 238},
+{"dark turquoise", 0, 206, 209},
+{"DarkTurquoise", 0, 206, 209},
+{"medium turquoise", 72, 209, 204},
+{"MediumTurquoise", 72, 209, 204},
+{"turquoise", 64, 224, 208},
+{"cyan", 0, 255, 255},
+{"light cyan", 224, 255, 255},
+{"LightCyan", 224, 255, 255},
+{"cadet blue", 95, 158, 160},
+{"CadetBlue", 95, 158, 160},
+{"medium aquamarine", 102, 205, 170},
+{"MediumAquamarine", 102, 205, 170},
+{"aquamarine", 127, 255, 212},
+{"dark green", 0, 100, 0},
+{"DarkGreen", 0, 100, 0},
+{"dark olive", 85, 107, 47},
+{"DarkOliveGreen", 85, 107, 47},
+{"dark sea", 143, 188, 143},
+{"DarkSeaGreen", 143, 188, 143},
+{"sea green", 46, 139, 87},
+{"SeaGreen", 46, 139, 87},
+{"medium sea", 60, 179, 113},
+{"MediumSeaGreen", 60, 179, 113},
+{"light sea", 32, 178, 170},
+{"LightSeaGreen", 32, 178, 170},
+{"pale green", 152, 251, 152},
+{"PaleGreen", 152, 251, 152},
+{"spring green", 0, 255, 127},
+{"SpringGreen", 0, 255, 127},
+{"lawn green", 124, 252, 0},
+{"LawnGreen", 124, 252, 0},
+{"green", 0, 255, 0},
+{"chartreuse", 127, 255, 0},
+{"medium spring", 0, 250, 154},
+{"MediumSpringGreen", 0, 250, 154},
+{"green yellow", 173, 255, 47},
+{"GreenYellow", 173, 255, 47},
+{"lime green", 50, 205, 50},
+{"LimeGreen", 50, 205, 50},
+{"yellow green", 154, 205, 50},
+{"YellowGreen", 154, 205, 50},
+{"forest green", 34, 139, 34},
+{"ForestGreen", 34, 139, 34},
+{"olive drab", 107, 142, 35},
+{"OliveDrab", 107, 142, 35},
+{"dark khaki", 189, 183, 107},
+{"DarkKhaki", 189, 183, 107},
+{"khaki", 240, 230, 140},
+{"pale goldenrod", 238, 232, 170},
+{"PaleGoldenrod", 238, 232, 170},
+{"light goldenrod", 250, 250, 210},
+{"LightGoldenrodYellow", 250, 250, 210},
+{"light yellow", 255, 255, 224},
+{"LightYellow", 255, 255, 224},
+{"yellow", 255, 255, 0},
+{"gold", 255, 215, 0},
+{"light goldenrod", 238, 221, 130},
+{"LightGoldenrod", 238, 221, 130},
+{"goldenrod", 218, 165, 32},
+{"dark goldenrod", 184, 134, 11},
+{"DarkGoldenrod", 184, 134, 11},
+{"rosy brown", 188, 143, 143},
+{"RosyBrown", 188, 143, 143},
+{"indian red", 205, 92, 92},
+{"IndianRed", 205, 92, 92},
+{"saddle brown", 139, 69, 19},
+{"SaddleBrown", 139, 69, 19},
+{"sienna", 160, 82, 45},
+{"peru", 205, 133, 63},
+{"burlywood", 222, 184, 135},
+{"beige", 245, 245, 220},
+{"wheat", 245, 222, 179},
+{"sandy brown", 244, 164, 96},
+{"SandyBrown", 244, 164, 96},
+{"tan", 210, 180, 140},
+{"chocolate", 210, 105, 30},
+{"firebrick", 178, 34, 34},
+{"brown", 165, 42, 42},
+{"dark salmon", 233, 150, 122},
+{"DarkSalmon", 233, 150, 122},
+{"salmon", 250, 128, 114},
+{"light salmon", 255, 160, 122},
+{"LightSalmon", 255, 160, 122},
+{"orange", 255, 165, 0},
+{"dark orange", 255, 140, 0},
+{"DarkOrange", 255, 140, 0},
+{"coral", 255, 127, 80},
+{"light coral", 240, 128, 128},
+{"LightCoral", 240, 128, 128},
+{"tomato", 255, 99, 71},
+{"orange red", 255, 69, 0},
+{"OrangeRed", 255, 69, 0},
+{"red", 255, 0, 0},
+{"hot pink", 255, 105, 180},
+{"HotPink", 255, 105, 180},
+{"deep pink", 255, 20, 147},
+{"DeepPink", 255, 20, 147},
+{"pink", 255, 192, 203},
+{"light pink", 255, 182, 193},
+{"LightPink", 255, 182, 193},
+{"pale violet", 219, 112, 147},
+{"PaleVioletRed", 219, 112, 147},
+{"maroon", 176, 48, 96},
+{"medium violet", 199, 21, 133},
+{"MediumVioletRed", 199, 21, 133},
+{"violet red", 208, 32, 144},
+{"VioletRed", 208, 32, 144},
+{"magenta", 255, 0, 255},
+{"violet", 238, 130, 238},
+{"plum", 221, 160, 221},
+{"orchid", 218, 112, 214},
+{"medium orchid", 186, 85, 211},
+{"MediumOrchid", 186, 85, 211},
+{"dark orchid", 153, 50, 204},
+{"DarkOrchid", 153, 50, 204},
+{"dark violet", 148, 0, 211},
+{"DarkViolet", 148, 0, 211},
+{"blue violet", 138, 43, 226},
+{"BlueViolet", 138, 43, 226},
+{"purple", 160, 32, 240},
+{"medium purple", 147, 112, 219},
+{"MediumPurple", 147, 112, 219},
+{"thistle", 216, 191, 216},
+{"snow1", 255, 250, 250},
+{"snow2", 238, 233, 233},
+{"snow3", 205, 201, 201},
+{"snow4", 139, 137, 137},
+{"seashell1", 255, 245, 238},
+{"seashell2", 238, 229, 222},
+{"seashell3", 205, 197, 191},
+{"seashell4", 139, 134, 130},
+{"AntiqueWhite1", 255, 239, 219},
+{"AntiqueWhite2", 238, 223, 204},
+{"AntiqueWhite3", 205, 192, 176},
+{"AntiqueWhite4", 139, 131, 120},
+{"bisque1", 255, 228, 196},
+{"bisque2", 238, 213, 183},
+{"bisque3", 205, 183, 158},
+{"bisque4", 139, 125, 107},
+{"PeachPuff1", 255, 218, 185},
+{"PeachPuff2", 238, 203, 173},
+{"PeachPuff3", 205, 175, 149},
+{"PeachPuff4", 139, 119, 101},
+{"NavajoWhite1", 255, 222, 173},
+{"NavajoWhite2", 238, 207, 161},
+{"NavajoWhite3", 205, 179, 139},
+{"NavajoWhite4", 139, 121, 94},
+{"LemonChiffon1", 255, 250, 205},
+{"LemonChiffon2", 238, 233, 191},
+{"LemonChiffon3", 205, 201, 165},
+{"LemonChiffon4", 139, 137, 112},
+{"cornsilk1", 255, 248, 220},
+{"cornsilk2", 238, 232, 205},
+{"cornsilk3", 205, 200, 177},
+{"cornsilk4", 139, 136, 120},
+{"ivory1", 255, 255, 240},
+{"ivory2", 238, 238, 224},
+{"ivory3", 205, 205, 193},
+{"ivory4", 139, 139, 131},
+{"honeydew1", 240, 255, 240},
+{"honeydew2", 224, 238, 224},
+{"honeydew3", 193, 205, 193},
+{"honeydew4", 131, 139, 131},
+{"LavenderBlush1", 255, 240, 245},
+{"LavenderBlush2", 238, 224, 229},
+{"LavenderBlush3", 205, 193, 197},
+{"LavenderBlush4", 139, 131, 134},
+{"MistyRose1", 255, 228, 225},
+{"MistyRose2", 238, 213, 210},
+{"MistyRose3", 205, 183, 181},
+{"MistyRose4", 139, 125, 123},
+{"azure1", 240, 255, 255},
+{"azure2", 224, 238, 238},
+{"azure3", 193, 205, 205},
+{"azure4", 131, 139, 139},
+{"SlateBlue1", 131, 111, 255},
+{"SlateBlue2", 122, 103, 238},
+{"SlateBlue3", 105, 89, 205},
+{"SlateBlue4", 71, 60, 139},
+{"RoyalBlue1", 72, 118, 255},
+{"RoyalBlue2", 67, 110, 238},
+{"RoyalBlue3", 58, 95, 205},
+{"RoyalBlue4", 39, 64, 139},
+{"blue1", 0, 0, 255},
+{"blue2", 0, 0, 238},
+{"blue3", 0, 0, 205},
+{"blue4", 0, 0, 139},
+{"DodgerBlue1", 30, 144, 255},
+{"DodgerBlue2", 28, 134, 238},
+{"DodgerBlue3", 24, 116, 205},
+{"DodgerBlue4", 16, 78, 139},
+{"SteelBlue1", 99, 184, 255},
+{"SteelBlue2", 92, 172, 238},
+{"SteelBlue3", 79, 148, 205},
+{"SteelBlue4", 54, 100, 139},
+{"DeepSkyBlue1", 0, 191, 255},
+{"DeepSkyBlue2", 0, 178, 238},
+{"DeepSkyBlue3", 0, 154, 205},
+{"DeepSkyBlue4", 0, 104, 139},
+{"SkyBlue1", 135, 206, 255},
+{"SkyBlue2", 126, 192, 238},
+{"SkyBlue3", 108, 166, 205},
+{"SkyBlue4", 74, 112, 139},
+{"LightSkyBlue1", 176, 226, 255},
+{"LightSkyBlue2", 164, 211, 238},
+{"LightSkyBlue3", 141, 182, 205},
+{"LightSkyBlue4", 96, 123, 139},
+{"SlateGray1", 198, 226, 255},
+{"SlateGray2", 185, 211, 238},
+{"SlateGray3", 159, 182, 205},
+{"SlateGray4", 108, 123, 139},
+{"LightSteelBlue1", 202, 225, 255},
+{"LightSteelBlue2", 188, 210, 238},
+{"LightSteelBlue3", 162, 181, 205},
+{"LightSteelBlue4", 110, 123, 139},
+{"LightBlue1", 191, 239, 255},
+{"LightBlue2", 178, 223, 238},
+{"LightBlue3", 154, 192, 205},
+{"LightBlue4", 104, 131, 139},
+{"LightCyan1", 224, 255, 255},
+{"LightCyan2", 209, 238, 238},
+{"LightCyan3", 180, 205, 205},
+{"LightCyan4", 122, 139, 139},
+{"PaleTurquoise1", 187, 255, 255},
+{"PaleTurquoise2", 174, 238, 238},
+{"PaleTurquoise3", 150, 205, 205},
+{"PaleTurquoise4", 102, 139, 139},
+{"CadetBlue1", 152, 245, 255},
+{"CadetBlue2", 142, 229, 238},
+{"CadetBlue3", 122, 197, 205},
+{"CadetBlue4", 83, 134, 139},
+{"turquoise1", 0, 245, 255},
+{"turquoise2", 0, 229, 238},
+{"turquoise3", 0, 197, 205},
+{"turquoise4", 0, 134, 139},
+{"cyan1", 0, 255, 255},
+{"cyan2", 0, 238, 238},
+{"cyan3", 0, 205, 205},
+{"cyan4", 0, 139, 139},
+{"DarkSlateGray1", 151, 255, 255},
+{"DarkSlateGray2", 141, 238, 238},
+{"DarkSlateGray3", 121, 205, 205},
+{"DarkSlateGray4", 82, 139, 139},
+{"aquamarine1", 127, 255, 212},
+{"aquamarine2", 118, 238, 198},
+{"aquamarine3", 102, 205, 170},
+{"aquamarine4", 69, 139, 116},
+{"DarkSeaGreen1", 193, 255, 193},
+{"DarkSeaGreen2", 180, 238, 180},
+{"DarkSeaGreen3", 155, 205, 155},
+{"DarkSeaGreen4", 105, 139, 105},
+{"SeaGreen1", 84, 255, 159},
+{"SeaGreen2", 78, 238, 148},
+{"SeaGreen3", 67, 205, 128},
+{"SeaGreen4", 46, 139, 87},
+{"PaleGreen1", 154, 255, 154},
+{"PaleGreen2", 144, 238, 144},
+{"PaleGreen3", 124, 205, 124},
+{"PaleGreen4", 84, 139, 84},
+{"SpringGreen1", 0, 255, 127},
+{"SpringGreen2", 0, 238, 118},
+{"SpringGreen3", 0, 205, 102},
+{"SpringGreen4", 0, 139, 69},
+{"green1", 0, 255, 0},
+{"green2", 0, 238, 0},
+{"green3", 0, 205, 0},
+{"green4", 0, 139, 0},
+{"chartreuse1", 127, 255, 0},
+{"chartreuse2", 118, 238, 0},
+{"chartreuse3", 102, 205, 0},
+{"chartreuse4", 69, 139, 0},
+{"OliveDrab1", 192, 255, 62},
+{"OliveDrab2", 179, 238, 58},
+{"OliveDrab3", 154, 205, 50},
+{"OliveDrab4", 105, 139, 34},
+{"DarkOliveGreen1", 202, 255, 112},
+{"DarkOliveGreen2", 188, 238, 104},
+{"DarkOliveGreen3", 162, 205, 90},
+{"DarkOliveGreen4", 110, 139, 61},
+{"khaki1", 255, 246, 143},
+{"khaki2", 238, 230, 133},
+{"khaki3", 205, 198, 115},
+{"khaki4", 139, 134, 78},
+{"LightGoldenrod1", 255, 236, 139},
+{"LightGoldenrod2", 238, 220, 130},
+{"LightGoldenrod3", 205, 190, 112},
+{"LightGoldenrod4", 139, 129, 76},
+{"LightYellow1", 255, 255, 224},
+{"LightYellow2", 238, 238, 209},
+{"LightYellow3", 205, 205, 180},
+{"LightYellow4", 139, 139, 122},
+{"yellow1", 255, 255, 0},
+{"yellow2", 238, 238, 0},
+{"yellow3", 205, 205, 0},
+{"yellow4", 139, 139, 0},
+{"gold1", 255, 215, 0},
+{"gold2", 238, 201, 0},
+{"gold3", 205, 173, 0},
+{"gold4", 139, 117, 0},
+{"goldenrod1", 255, 193, 37},
+{"goldenrod2", 238, 180, 34},
+{"goldenrod3", 205, 155, 29},
+{"goldenrod4", 139, 105, 20},
+{"DarkGoldenrod1", 255, 185, 15},
+{"DarkGoldenrod2", 238, 173, 14},
+{"DarkGoldenrod3", 205, 149, 12},
+{"DarkGoldenrod4", 139, 101, 8},
+{"RosyBrown1", 255, 193, 193},
+{"RosyBrown2", 238, 180, 180},
+{"RosyBrown3", 205, 155, 155},
+{"RosyBrown4", 139, 105, 105},
+{"IndianRed1", 255, 106, 106},
+{"IndianRed2", 238, 99, 99},
+{"IndianRed3", 205, 85, 85},
+{"IndianRed4", 139, 58, 58},
+{"sienna1", 255, 130, 71},
+{"sienna2", 238, 121, 66},
+{"sienna3", 205, 104, 57},
+{"sienna4", 139, 71, 38},
+{"burlywood1", 255, 211, 155},
+{"burlywood2", 238, 197, 145},
+{"burlywood3", 205, 170, 125},
+{"burlywood4", 139, 115, 85},
+{"wheat1", 255, 231, 186},
+{"wheat2", 238, 216, 174},
+{"wheat3", 205, 186, 150},
+{"wheat4", 139, 126, 102},
+{"tan1", 255, 165, 79},
+{"tan2", 238, 154, 73},
+{"tan3", 205, 133, 63},
+{"tan4", 139, 90, 43},
+{"chocolate1", 255, 127, 36},
+{"chocolate2", 238, 118, 33},
+{"chocolate3", 205, 102, 29},
+{"chocolate4", 139, 69, 19},
+{"firebrick1", 255, 48, 48},
+{"firebrick2", 238, 44, 44},
+{"firebrick3", 205, 38, 38},
+{"firebrick4", 139, 26, 26},
+{"brown1", 255, 64, 64},
+{"brown2", 238, 59, 59},
+{"brown3", 205, 51, 51},
+{"brown4", 139, 35, 35},
+{"salmon1", 255, 140, 105},
+{"salmon2", 238, 130, 98},
+{"salmon3", 205, 112, 84},
+{"salmon4", 139, 76, 57},
+{"LightSalmon1", 255, 160, 122},
+{"LightSalmon2", 238, 149, 114},
+{"LightSalmon3", 205, 129, 98},
+{"LightSalmon4", 139, 87, 66},
+{"orange1", 255, 165, 0},
+{"orange2", 238, 154, 0},
+{"orange3", 205, 133, 0},
+{"orange4", 139, 90, 0},
+{"DarkOrange1", 255, 127, 0},
+{"DarkOrange2", 238, 118, 0},
+{"DarkOrange3", 205, 102, 0},
+{"DarkOrange4", 139, 69, 0},
+{"coral1", 255, 114, 86},
+{"coral2", 238, 106, 80},
+{"coral3", 205, 91, 69},
+{"coral4", 139, 62, 47},
+{"tomato1", 255, 99, 71},
+{"tomato2", 238, 92, 66},
+{"tomato3", 205, 79, 57},
+{"tomato4", 139, 54, 38},
+{"OrangeRed1", 255, 69, 0},
+{"OrangeRed2", 238, 64, 0},
+{"OrangeRed3", 205, 55, 0},
+{"OrangeRed4", 139, 37, 0},
+{"red1", 255, 0, 0},
+{"red2", 238, 0, 0},
+{"red3", 205, 0, 0},
+{"red4", 139, 0, 0},
+{"DeepPink1", 255, 20, 147},
+{"DeepPink2", 238, 18, 137},
+{"DeepPink3", 205, 16, 118},
+{"DeepPink4", 139, 10, 80},
+{"HotPink1", 255, 110, 180},
+{"HotPink2", 238, 106, 167},
+{"HotPink3", 205, 96, 144},
+{"HotPink4", 139, 58, 98},
+{"pink1", 255, 181, 197},
+{"pink2", 238, 169, 184},
+{"pink3", 205, 145, 158},
+{"pink4", 139, 99, 108},
+{"LightPink1", 255, 174, 185},
+{"LightPink2", 238, 162, 173},
+{"LightPink3", 205, 140, 149},
+{"LightPink4", 139, 95, 101},
+{"PaleVioletRed1", 255, 130, 171},
+{"PaleVioletRed2", 238, 121, 159},
+{"PaleVioletRed3", 205, 104, 137},
+{"PaleVioletRed4", 139, 71, 93},
+{"maroon1", 255, 52, 179},
+{"maroon2", 238, 48, 167},
+{"maroon3", 205, 41, 144},
+{"maroon4", 139, 28, 98},
+{"VioletRed1", 255, 62, 150},
+{"VioletRed2", 238, 58, 140},
+{"VioletRed3", 205, 50, 120},
+{"VioletRed4", 139, 34, 82},
+{"magenta1", 255, 0, 255},
+{"magenta2", 238, 0, 238},
+{"magenta3", 205, 0, 205},
+{"magenta4", 139, 0, 139},
+{"orchid1", 255, 131, 250},
+{"orchid2", 238, 122, 233},
+{"orchid3", 205, 105, 201},
+{"orchid4", 139, 71, 137},
+{"plum1", 255, 187, 255},
+{"plum2", 238, 174, 238},
+{"plum3", 205, 150, 205},
+{"plum4", 139, 102, 139},
+{"MediumOrchid1", 224, 102, 255},
+{"MediumOrchid2", 209, 95, 238},
+{"MediumOrchid3", 180, 82, 205},
+{"MediumOrchid4", 122, 55, 139},
+{"DarkOrchid1", 191, 62, 255},
+{"DarkOrchid2", 178, 58, 238},
+{"DarkOrchid3", 154, 50, 205},
+{"DarkOrchid4", 104, 34, 139},
+{"purple1", 155, 48, 255},
+{"purple2", 145, 44, 238},
+{"purple3", 125, 38, 205},
+{"purple4", 85, 26, 139},
+{"MediumPurple1", 171, 130, 255},
+{"MediumPurple2", 159, 121, 238},
+{"MediumPurple3", 137, 104, 205},
+{"MediumPurple4", 93, 71, 139},
+{"thistle1", 255, 225, 255},
+{"thistle2", 238, 210, 238},
+{"thistle3", 205, 181, 205},
+{"thistle4", 139, 123, 139},
+{"gray0", 0, 0, 0},
+{"grey0", 0, 0, 0},
+{"gray1", 3, 3, 3},
+{"grey1", 3, 3, 3},
+{"gray2", 5, 5, 5},
+{"grey2", 5, 5, 5},
+{"gray3", 8, 8, 8},
+{"grey3", 8, 8, 8},
+{"gray4", 10, 10, 10},
+{"grey4", 10, 10, 10},
+{"gray5", 13, 13, 13},
+{"grey5", 13, 13, 13},
+{"gray6", 15, 15, 15},
+{"grey6", 15, 15, 15},
+{"gray7", 18, 18, 18},
+{"grey7", 18, 18, 18},
+{"gray8", 20, 20, 20},
+{"grey8", 20, 20, 20},
+{"gray9", 23, 23, 23},
+{"grey9", 23, 23, 23},
+{"gray10", 26, 26, 26},
+{"grey10", 26, 26, 26},
+{"gray11", 28, 28, 28},
+{"grey11", 28, 28, 28},
+{"gray12", 31, 31, 31},
+{"grey12", 31, 31, 31},
+{"gray13", 33, 33, 33},
+{"grey13", 33, 33, 33},
+{"gray14", 36, 36, 36},
+{"grey14", 36, 36, 36},
+{"gray15", 38, 38, 38},
+{"grey15", 38, 38, 38},
+{"gray16", 41, 41, 41},
+{"grey16", 41, 41, 41},
+{"gray17", 43, 43, 43},
+{"grey17", 43, 43, 43},
+{"gray18", 46, 46, 46},
+{"grey18", 46, 46, 46},
+{"gray19", 48, 48, 48},
+{"grey19", 48, 48, 48},
+{"gray20", 51, 51, 51},
+{"grey20", 51, 51, 51},
+{"gray21", 54, 54, 54},
+{"grey21", 54, 54, 54},
+{"gray22", 56, 56, 56},
+{"grey22", 56, 56, 56},
+{"gray23", 59, 59, 59},
+{"grey23", 59, 59, 59},
+{"gray24", 61, 61, 61},
+{"grey24", 61, 61, 61},
+{"gray25", 64, 64, 64},
+{"grey25", 64, 64, 64},
+{"gray26", 66, 66, 66},
+{"grey26", 66, 66, 66},
+{"gray27", 69, 69, 69},
+{"grey27", 69, 69, 69},
+{"gray28", 71, 71, 71},
+{"grey28", 71, 71, 71},
+{"gray29", 74, 74, 74},
+{"grey29", 74, 74, 74},
+{"gray30", 77, 77, 77},
+{"grey30", 77, 77, 77},
+{"gray31", 79, 79, 79},
+{"grey31", 79, 79, 79},
+{"gray32", 82, 82, 82},
+{"grey32", 82, 82, 82},
+{"gray33", 84, 84, 84},
+{"grey33", 84, 84, 84},
+{"gray34", 87, 87, 87},
+{"grey34", 87, 87, 87},
+{"gray35", 89, 89, 89},
+{"grey35", 89, 89, 89},
+{"gray36", 92, 92, 92},
+{"grey36", 92, 92, 92},
+{"gray37", 94, 94, 94},
+{"grey37", 94, 94, 94},
+{"gray38", 97, 97, 97},
+{"grey38", 97, 97, 97},
+{"gray39", 99, 99, 99},
+{"grey39", 99, 99, 99},
+{"gray40", 102, 102, 102},
+{"grey40", 102, 102, 102},
+{"gray41", 105, 105, 105},
+{"grey41", 105, 105, 105},
+{"gray42", 107, 107, 107},
+{"grey42", 107, 107, 107},
+{"gray43", 110, 110, 110},
+{"grey43", 110, 110, 110},
+{"gray44", 112, 112, 112},
+{"grey44", 112, 112, 112},
+{"gray45", 115, 115, 115},
+{"grey45", 115, 115, 115},
+{"gray46", 117, 117, 117},
+{"grey46", 117, 117, 117},
+{"gray47", 120, 120, 120},
+{"grey47", 120, 120, 120},
+{"gray48", 122, 122, 122},
+{"grey48", 122, 122, 122},
+{"gray49", 125, 125, 125},
+{"grey49", 125, 125, 125},
+{"gray50", 127, 127, 127},
+{"grey50", 127, 127, 127},
+{"gray51", 130, 130, 130},
+{"grey51", 130, 130, 130},
+{"gray52", 133, 133, 133},
+{"grey52", 133, 133, 133},
+{"gray53", 135, 135, 135},
+{"grey53", 135, 135, 135},
+{"gray54", 138, 138, 138},
+{"grey54", 138, 138, 138},
+{"gray55", 140, 140, 140},
+{"grey55", 140, 140, 140},
+{"gray56", 143, 143, 143},
+{"grey56", 143, 143, 143},
+{"gray57", 145, 145, 145},
+{"grey57", 145, 145, 145},
+{"gray58", 148, 148, 148},
+{"grey58", 148, 148, 148},
+{"gray59", 150, 150, 150},
+{"grey59", 150, 150, 150},
+{"gray60", 153, 153, 153},
+{"grey60", 153, 153, 153},
+{"gray61", 156, 156, 156},
+{"grey61", 156, 156, 156},
+{"gray62", 158, 158, 158},
+{"grey62", 158, 158, 158},
+{"gray63", 161, 161, 161},
+{"grey63", 161, 161, 161},
+{"gray64", 163, 163, 163},
+{"grey64", 163, 163, 163},
+{"gray65", 166, 166, 166},
+{"grey65", 166, 166, 166},
+{"gray66", 168, 168, 168},
+{"grey66", 168, 168, 168},
+{"gray67", 171, 171, 171},
+{"grey67", 171, 171, 171},
+{"gray68", 173, 173, 173},
+{"grey68", 173, 173, 173},
+{"gray69", 176, 176, 176},
+{"grey69", 176, 176, 176},
+{"gray70", 179, 179, 179},
+{"grey70", 179, 179, 179},
+{"gray71", 181, 181, 181},
+{"grey71", 181, 181, 181},
+{"gray72", 184, 184, 184},
+{"grey72", 184, 184, 184},
+{"gray73", 186, 186, 186},
+{"grey73", 186, 186, 186},
+{"gray74", 189, 189, 189},
+{"grey74", 189, 189, 189},
+{"gray75", 191, 191, 191},
+{"grey75", 191, 191, 191},
+{"gray76", 194, 194, 194},
+{"grey76", 194, 194, 194},
+{"gray77", 196, 196, 196},
+{"grey77", 196, 196, 196},
+{"gray78", 199, 199, 199},
+{"grey78", 199, 199, 199},
+{"gray79", 201, 201, 201},
+{"grey79", 201, 201, 201},
+{"gray80", 204, 204, 204},
+{"grey80", 204, 204, 204},
+{"gray81", 207, 207, 207},
+{"grey81", 207, 207, 207},
+{"gray82", 209, 209, 209},
+{"grey82", 209, 209, 209},
+{"gray83", 212, 212, 212},
+{"grey83", 212, 212, 212},
+{"gray84", 214, 214, 214},
+{"grey84", 214, 214, 214},
+{"gray85", 217, 217, 217},
+{"grey85", 217, 217, 217},
+{"gray86", 219, 219, 219},
+{"grey86", 219, 219, 219},
+{"gray87", 222, 222, 222},
+{"grey87", 222, 222, 222},
+{"gray88", 224, 224, 224},
+{"grey88", 224, 224, 224},
+{"gray89", 227, 227, 227},
+{"grey89", 227, 227, 227},
+{"gray90", 229, 229, 229},
+{"grey90", 229, 229, 229},
+{"gray91", 232, 232, 232},
+{"grey91", 232, 232, 232},
+{"gray92", 235, 235, 235},
+{"grey92", 235, 235, 235},
+{"gray93", 237, 237, 237},
+{"grey93", 237, 237, 237},
+{"gray94", 240, 240, 240},
+{"grey94", 240, 240, 240},
+{"gray95", 242, 242, 242},
+{"grey95", 242, 242, 242},
+{"gray96", 245, 245, 245},
+{"grey96", 245, 245, 245},
+{"gray97", 247, 247, 247},
+{"grey97", 247, 247, 247},
+{"gray98", 250, 250, 250},
+{"grey98", 250, 250, 250},
+{"gray99", 252, 252, 252},
+{"grey99", 252, 252, 252},
+{"gray100", 255, 255, 255},
+{"grey100", 255, 255, 255},
+{"dark grey", 169, 169, 169},
+{"DarkGrey", 169, 169, 169},
+{"dark gray", 169, 169, 169},
+{"DarkGray", 169, 169, 169},
+{"dark blue", 0, 0, 139},
+{"DarkBlue", 0, 0, 139},
+{"dark cyan", 0, 139, 139},
+{"DarkCyan", 0, 139, 139},
+{"dark magenta", 139, 0, 139},
+{"DarkMagenta", 139, 0, 139},
+{"dark red", 139, 0, 0},
+{"DarkRed", 139, 0, 0},
+{"light green", 144, 238, 144},
+{"LightGreen", 144, 238, 144},
+{NULL, 0, 0, 0}
+};
diff --git a/xcwin32.c b/xcwin32.c
new file mode 100644
index 0000000..bf1fd75
--- /dev/null
+++ b/xcwin32.c
@@ -0,0 +1,3366 @@
+#define WINVER 0x0500
+#define _WIN32_WINNT 0x0500
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "xcwin32.h"
+#include "xcircuit.h"
+#include "colordefs.h"
+#include "resource.h"
+#include "menudep.h"
+#include "prototypes.h"
+#include "tool_bar.h"
+
+#include "xcwin32-colors.h"
+
+#ifndef MK_XBUTTON1
+#define MK_XBUTTON1 32
+#define MK_XBUTTON2 64
+#endif
+
+#if 0
+#define W32DEBUG(x) printf##x
+#else
+#define W32DEBUG(x)
+#endif
+
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern char _STR2[250];
+extern Pixmap STIPPLE[STIPPLES]; /* Polygon fill-style stipple patterns */
+static char STIPDATA[STIPPLES][4] = {
+ "\000\004\000\001",
+ "\000\005\000\012",
+ "\001\012\005\010",
+ "\005\012\005\012",
+ "\016\005\012\007",
+ "\017\012\017\005",
+ "\017\012\017\016",
+ "\000\000\000\000"
+};
+extern xcWidget top, message2, message3;
+extern ApplicationData appdata;
+extern int* appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern menustruct TopButtons[];
+extern short maxbuttons;
+extern xcWidget menuwidgets[MaxMenuWidgets];
+extern Display *dpy;
+extern toolbarstruct ToolBar[];
+extern short toolbuttons;
+extern Pixmap dbuf, helppix;
+extern Dimension helpwidth, helpheight;
+extern int helptop;
+extern GC hgc;
+#define MAXPROPS 7
+extern propstruct okstruct[MAXPROPS], fpokstruct;
+
+static HWND corner = NULL, statusBar = NULL;
+static Widget toolBar = NULL;
+static int statusBarWidth[2] = { 100, -1 };
+
+HWND topwin = NULL;
+
+/*
+LRESULT CALLBACK XcStaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK XcEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK XcButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK XcToggleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK XcPopupProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+*/
+
+INT_PTR CALLBACK OutputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+void updatename(xcWidget button, xcWidgetList callstruct, caddr_t calldata);
+void linkset(xcWidget button, propstruct *callstruct, caddr_t calldata);
+extern int COM_initialize();
+extern int COM_terminate();
+
+#define WIN_WIDGET 0
+#define WIN_MENUITEM 1
+#define WIN_MENU 2
+#define WIN_STATUS 3
+#define WIN_TOOLITEM 4
+
+#define IS_WIDGET(w) (w->type == WIN_WIDGET)
+#define IS_MENU(w) (w->type == WIN_MENU)
+#define IS_MENUITEM(w) (w->type == WIN_MENUITEM)
+#define IS_STATUS(w) (w->type == WIN_STATUS)
+#define IS_TOOLITEM(w) (w->type == WIN_TOOLITEM)
+
+#define TOWIDGET(w) ((Widget)w)
+#define TOMENU(w) ((Menu)w)
+#define TOMENUITEM(w) ((MenuItem)w)
+#define TOSTATUS(w) ((StatusItem)w)
+#define TOTOOLITEM(w) ((ToolItem)w)
+
+#define STATUSBAR_ID 10000
+#define TOOLBAR_ID 10001
+
+typedef struct __WinCallback {
+ int action;
+ void(*proc)();
+ void* data;
+ struct __WinCallback *next;
+} WinCallback;
+typedef WinCallback WinEventHandler;
+
+struct __WinWidget {
+ int type;
+ HWND handle;
+ char *name;
+ WinCallback *callbacks;
+ WinEventHandler *handlers;
+ int handler_mask;
+ HBITMAP buffer;
+ HDC bufhdc;
+ WNDPROC wndproc;
+};
+#define HAS_HANDLER(win,themask) (win->handler_mask & themask)
+#define WM_BITBLT (WM_USER+1)
+
+struct __WinMenu {
+ int type;
+ HMENU handle;
+};
+
+struct __WinMenuItem {
+ int type;
+ struct __WinMenu *parentMenu;
+ struct __WinMenu *popup;
+ int ID;
+ int position;
+ char *name;
+ WinCallback *callbacks;
+ int menudata;
+ int toolbar_idx;
+};
+
+struct __WinStatusItem {
+ int type;
+ HWND handle;
+ int position;
+};
+
+struct __WinToolItem {
+ int type;
+ struct __WinWidget *toolbar;
+ int ID;
+ char *name;
+ WinCallback *callbacks;
+};
+
+typedef struct __WinMenu* Menu;
+typedef struct __WinMenuItem* MenuItem;
+typedef struct __WinStatusItem* StatusItem;
+typedef struct __WinToolItem* ToolItem;
+
+void execute_callback(int action, Widget w, void *calldata)
+{
+ WinCallback *cb;
+
+ switch (w->type) {
+ case WIN_WIDGET:
+ cb = w->callbacks;
+ break;
+ case WIN_MENUITEM:
+ cb = ((MenuItem)w)->callbacks;
+ break;
+ case WIN_TOOLITEM:
+ cb = ((ToolItem)w)->callbacks;
+ break;
+ default:
+ return;
+ }
+ while (cb != NULL) {
+ if (cb->action == action) {
+ (*cb->proc)(w, cb->data, calldata);
+ }
+ cb = cb->next;
+ }
+}
+
+void execute_handler(int mask, Widget w, void *calldata)
+{
+ WinCallback *h = w->handlers;
+ if (!HAS_HANDLER(w,mask))
+ return;
+ while (h != NULL) {
+ if (h->action & mask)
+ (*h->proc)(w, h->data, calldata);
+ h = h->next;
+ }
+}
+
+void update_event_mask(Widget win)
+{
+ WinEventHandler *h = win->handlers;
+ win->handler_mask = 0;
+ for (; h!= NULL; h=h->next)
+ win->handler_mask |= h->action;
+}
+
+Widget get_widget(HWND win)
+{
+ /*
+ int nbytes = GetClassLong(win, GCL_CBWNDEXTRA);
+ if (nbytes >= sizeof(Widget))
+ return (Widget)GetWindowLong(win, nbytes-sizeof(Widget));
+ else
+ return NULL;
+ */
+ return (Widget)GetWindowLong(win, GWL_USERDATA);
+}
+
+static void get_value(Widget w, Arg *a)
+{
+ RECT rect;
+
+ switch (a->type) {
+ case XtNwidth:
+ if (w->type == WIN_STATUS) {
+ StatusItem item = (StatusItem)w;
+ if (item->position < 1)
+ *(int*)(a->data) = statusBarWidth[item->position];
+ else {
+ GetClientRect(w->handle, &rect);
+ *(int*)(a->data) = rect.right - rect.left - statusBarWidth[0];
+ }
+ } else {
+ if (GetClientRect(w->handle, &rect))
+ *(int*)(a->data) = rect.right - rect.left;
+ }
+ break;
+ case XtNheight:
+ if (GetClientRect(w->handle, &rect))
+ *(int*)(a->data) = rect.bottom - rect.top;
+ break;
+ case XtNrectColor:
+ case XtNrectStipple:
+ if (w->type == WIN_MENUITEM) {
+ *(int*)(a->data) = ((MenuItem)w)->menudata;
+ break;
+ }
+ goto GETDEFAULT;
+GETDEFAULT:
+ default:
+ W32DEBUG(("Unsupported get value: %d\n", a->type));
+ break;
+ }
+}
+
+static void set_value(Widget w, Arg *a)
+{
+ switch (a->type) {
+ case XtNstring:
+ switch (w->type) {
+ case WIN_STATUS:
+ SendMessage(TOSTATUS(w)->handle, SB_SETTEXT, TOSTATUS(w)->position, (LPARAM)(char*)a->data);
+ break;
+ case WIN_WIDGET:
+ SetWindowText(w->handle, (char*)a->data);
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+ case XtNsetMark:
+ switch (w->type) {
+ case WIN_MENUITEM:
+ CheckMenuItem(TOMENUITEM(w)->parentMenu->handle, TOMENUITEM(w)->position,
+ MF_BYPOSITION|(a->data == NULL ? MF_UNCHECKED : MF_CHECKED));
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+ case XtNlabel:
+ switch (w->type) {
+ case WIN_MENUITEM:
+ {
+ MENUITEMINFO mi_info;
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_STRING;
+ mi_info.dwTypeData = a->data;
+ SetMenuItemInfo(TOMENUITEM(w)->parentMenu->handle, TOMENUITEM(w)->position, MF_BYPOSITION, &mi_info);
+ break;
+ }
+ case WIN_WIDGET:
+ SetWindowText(w->handle, (char*)a->data);
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+ case XtNfont:
+ switch (w->type) {
+ case WIN_WIDGET:
+ SendMessage(w->handle, WM_SETFONT, (WPARAM)((XFontStruct*)a->data)->fid, MAKELONG(TRUE, 0));
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+ case XtNset:
+ switch (w->type) {
+ case WIN_WIDGET:
+ SendMessage(w->handle, BM_SETCHECK, ((int)a->data == True ? BST_CHECKED : BST_UNCHECKED), 0);
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+ case XtNborderColor:
+ switch (w->type) {
+ case WIN_TOOLITEM:
+ if ((int)a->data == RATSNESTCOLOR) {
+ W32DEBUG(("Check button: %s\n", ((ToolItem)w)->name));
+ SendMessage(TOTOOLITEM(w)->toolbar->handle, TB_CHECKBUTTON, TOTOOLITEM(w)->ID, MAKELONG(TRUE, 0));
+ }
+ else {
+ W32DEBUG(("Uncheck button: %s\n", ((ToolItem)w)->name));
+ SendMessage(TOTOOLITEM(w)->toolbar->handle, TB_CHECKBUTTON, TOTOOLITEM(w)->ID, MAKELONG(FALSE, 0));
+ }
+ break;
+ default:
+ goto SETDEFAULT;
+ }
+ break;
+SETDEFAULT:
+ default:
+ W32DEBUG(("Unsupported set value: %d\n", a->type));
+ /*exit(-1);*/
+ break;
+ }
+}
+
+void WinGetValues(Widget w, Arg *args, int n)
+{
+ int i;
+
+ if (w != NULL)
+ for (i=0; i<n; i++)
+ get_value(w, args+i);
+}
+
+void WinSetValues(Widget w, Arg *args, int n)
+{
+ int i;
+
+ if (w != NULL)
+ for (i=0; i<n; i++)
+ set_value(w, args+i);
+}
+
+HBITMAP WinCreatePixmap(HWND w, int width, int height)
+{
+ HDC hdc;
+ HBITMAP hBitmap;
+
+ hdc = GetDC(w);
+ hBitmap = CreateCompatibleBitmap(hdc, width, height);
+ ReleaseDC(w, hdc);
+ return hBitmap;
+}
+
+Widget WinParent(Widget child)
+{
+ if (child)
+ switch (child->type) {
+ case WIN_WIDGET:
+ return (Widget)get_widget(GetParent(child->handle));
+ case WIN_MENUITEM:
+ return (Widget)((MenuItem)child)->parentMenu;
+ case WIN_TOOLITEM:
+ return (Widget)((ToolItem)child)->toolbar;
+ }
+ return NULL;
+}
+
+void WinFreePixmap(Pixmap pix)
+{
+ DeleteObject(pix);
+}
+
+void WinDestroyImage(XImage *img)
+{
+ if (img->handle != NULL)
+ DeleteObject(img->handle);
+ free(img->data);
+ free(img);
+}
+
+XImage* WinCreateImage(int width, int height)
+{
+ HWND h = GetDesktopWindow();
+ HDC hdc = GetDC(h);
+ XImage *img = (XImage*)malloc(sizeof(XImage));
+
+ img->bits_per_pixel = GetDeviceCaps(hdc, BITSPIXEL);
+ img->bytes_per_line = width * img->bits_per_pixel / 8;
+ img->width = width;
+ img->height = height;
+ img->data = NULL;
+ ReleaseDC(h, hdc);
+
+ return img;
+}
+
+int WinGetPixel(XImage *img, int x, int y)
+{
+ unsigned char *src;
+ if (img->bits_per_pixel != 32) {
+ W32DEBUG(("WinGetPixel only supported on 32bpp\n"));
+ return -1;
+ }
+ src = img->data + (y * img->bytes_per_line) + (x * img->bits_per_pixel) / 8;
+ return RGB(src[0], src[1], src[2]);
+}
+
+void WinPutPixel(XImage *img, int x, int y, Pixel pix)
+{
+ unsigned char *src;
+ if (img->bits_per_pixel != 32) {
+ W32DEBUG(("WinPutPixel only supported on 32bpp\n"));
+ return;
+ }
+ src = img->data + (y * img->bytes_per_line) + (x * img->bits_per_pixel) / 8;
+ src[0] = GetRValue(pix);
+ src[1] = GetGValue(pix);
+ src[2] = GetBValue(pix);
+}
+
+DIR* opendir(const char *name)
+{
+ DIR *d = (DIR*)malloc(sizeof(DIR));
+ static char buffer[MAX_PATH];
+
+ strncpy(buffer, name, MAX_PATH);
+ strncat(buffer, "\\*", MAX_PATH);
+ d->hnd = FindFirstFile(buffer, &(d->fd));
+ if (d->hnd == INVALID_HANDLE_VALUE)
+ return NULL;
+ d->dirty = 1;
+ return d;
+}
+
+void closedir(DIR *d)
+{
+ free(d);
+}
+
+struct direct* readdir(DIR *d)
+{
+ if (!d->dirty)
+ {
+ if (!FindNextFile(d->hnd, &(d->fd)))
+ return NULL;
+ }
+ d->d.d_name = d->fd.cFileName;
+ d->dirty = 0;
+ return &(d->d);
+}
+
+int WinDesktopWidth(void)
+{
+ RECT r;
+ GetWindowRect(GetDesktopWindow(), &r);
+ return r.right-r.left;
+}
+
+int WinDesktopHeight(void)
+{
+ RECT r;
+ GetWindowRect(GetDesktopWindow(), &r);
+ return r.bottom-r.top;
+}
+
+void WinSetCursor(HWND win, HCURSOR cursor)
+{
+ SetClassLong(win, GCL_HCURSOR, (LONG)cursor);
+}
+
+HDC cached_hdc = NULL;
+HWND cached_win = NULL;
+
+static HPEN create_pen(GC gc)
+{
+ HPEN hPen = NULL;
+
+ if (gc->line_style != LineSolid && gc->line_dash_len > 0 && gc->line_dash != NULL) {
+ DWORD *dashes = NULL;
+ DWORD style = 0;
+ LOGBRUSH logBrush;
+ int i;
+
+ logBrush.lbStyle = BS_SOLID;
+ logBrush.lbColor = gc->foreground;
+ logBrush.lbHatch = 0;
+
+ style |= PS_GEOMETRIC | PS_USERSTYLE | gc->line_cap | gc->line_join;
+ dashes = (DWORD*)malloc(sizeof(DWORD)*gc->line_dash_len);
+ for (i=0; i<gc->line_dash_len; i++)
+ dashes[i] = gc->line_dash[i];
+ hPen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE | gc->line_cap | gc->line_join,
+ gc->line_width, &logBrush, gc->line_dash_len, dashes);
+ free(dashes);
+ } else {
+ hPen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
+ }
+
+ return hPen;
+}
+
+static HBRUSH create_brush(GC gc)
+{
+ LOGBRUSH logBrush;
+ logBrush.lbStyle = (gc->fill_style == FillSolid ? BS_SOLID : BS_PATTERN);
+ logBrush.lbColor = gc->foreground;
+ logBrush.lbHatch = (LONG)(gc->fill_style != FillSolid ? gc->fill_stipple : NULL);
+ return CreateBrushIndirect(&logBrush);
+}
+
+static HDC get_hdc(HWND win, GC gc)
+{
+ HDC hdc;
+ if (IsWindow(win)) {
+ Widget winwidget = (Widget)get_widget(win);
+ if (winwidget == NULL || winwidget->buffer == NULL)
+ hdc = GetDC(win);
+ else
+ hdc = winwidget->bufhdc;
+ } else if (win == cached_win && cached_hdc != NULL) {
+ hdc = cached_hdc;
+ } else {
+ hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, win);
+ if (cached_hdc != NULL)
+ DeleteDC(cached_hdc);
+ cached_hdc = hdc;
+ cached_win = win;
+ }
+ if (gc != NULL) {
+ SetROP2(hdc, gc->function);
+ SetBkColor(hdc, gc->background);
+ SetTextColor(hdc, gc->foreground);
+ SetBkMode(hdc, TRANSPARENT);
+ SelectObject(hdc, create_pen(gc));
+ SelectObject(hdc, create_brush(gc));
+ SelectObject(hdc, gc->font);
+ }
+ return hdc;
+}
+
+static release_hdc(HWND win, HDC hdc)
+{
+ DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN)));
+ DeleteObject(SelectObject(hdc, GetStockObject(NULL_BRUSH)));
+ if (IsWindow(win)) {
+ Widget winwidget = (Widget)get_widget(win);
+ if (winwidget == NULL || winwidget->buffer == NULL)
+ ReleaseDC(win, hdc);
+ else
+ PostMessage(win, WM_BITBLT, 0, 0);
+ }
+ else {
+ //DeleteDC(hdc);
+ }
+}
+
+void WinDrawLine(HWND win, GC gc, int x1, int y1, int x2, int y2)
+{
+ HDC hdc = get_hdc(win, gc);
+ MoveToEx(hdc, x1, y1, NULL);
+ LineTo(hdc, x2, y2);
+ release_hdc(win, hdc);
+}
+
+void WinFillPolygon(HWND win, GC gc, XPoint* pathlist, int number)
+{
+ LPPOINT pts = (LPPOINT)malloc(sizeof(POINT)*number);
+ HDC hdc = get_hdc(win, gc);
+ RECT rect = { 0x0000ffff, 0x0000ffff, -0x0000ffff, -0x0000ffff };
+ int i;
+
+ DeleteObject(SelectObject(hdc, CreatePen(PS_NULL, 0, 0)));
+
+ for (i=0; i<number; i++) {
+ pts[i].x = pathlist[i].x;
+ pts[i].y = pathlist[i].y;
+ rect.left = min(rect.left, pts[i].x);
+ rect.top = min(rect.top, pts[i].y);
+ rect.right = max(rect.right, pts[i].x);
+ rect.bottom = max(rect.bottom, pts[i].y);
+ }
+ if (gc->fill_style == FillStippled) {
+ int width = rect.right-rect.left, height = rect.bottom-rect.top;
+ HDC tmphdc = CreateCompatibleDC(hdc);
+ HBITMAP tmpbmp = CreateCompatibleBitmap(hdc, width, height);
+ HBRUSH tmpbrush = CreateSolidBrush(gc->foreground);
+
+ SelectObject(tmphdc, tmpbmp);
+ SelectObject(tmphdc, tmpbrush);
+ SetROP2(tmphdc, gc->function);
+ BitBlt(tmphdc, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
+ for (i=0; i<number; i++) {
+ pts[i].x -= rect.left;
+ pts[i].y -= rect.top;
+ }
+ Polygon(tmphdc, pts, number);
+ BitBlt(hdc, rect.left, rect.top, width, height, tmphdc, 0, 0, 0x00AC0744);
+
+ DeleteDC(tmphdc);
+ DeleteObject(tmpbmp);
+ DeleteObject(tmpbrush);
+ } else {
+ Polygon(hdc, pts, number);
+ }
+
+ release_hdc(win, hdc);
+ free(pts);
+}
+
+void WinDrawArc(HWND win, GC gc, int x, int y, int width, int height, int angle, int span)
+{
+ HDC hdc = get_hdc(win, gc);
+ if (span != (360*64)) {
+ W32DEBUG(("Unimplemented\n"));
+ } else
+ Ellipse(hdc, x, y, width, height);
+ release_hdc(win, hdc);
+}
+
+void WinClearArea(HWND win, int x, int y, int w, int h)
+{
+ HDC hdc = get_hdc(win, NULL);
+ RECT r;
+ r.left = x;
+ r.top = y;
+ r.right = x+w;
+ r.bottom = y+h;
+ FillRect(hdc, &r, (HBRUSH)(COLOR_WINDOW+1));
+ release_hdc(win, hdc);
+}
+
+void WinFillRectangle(HWND win, GC gc, int x, int y, int w, int h)
+{
+ HDC hdc = get_hdc(win, gc);
+ RECT r;
+ r.left = x;
+ r.top = y;
+ r.right = x+w;
+ r.bottom = y+h;
+ FillRect(hdc, &r, (HBRUSH)GetCurrentObject(hdc, OBJ_BRUSH));
+ release_hdc(win, hdc);
+}
+
+void WinSetFunction(GC gc, int op)
+{
+ gc->function = op;
+}
+
+void WinSetForeground(GC gc, int color)
+{
+ gc->foreground = color;
+}
+
+void WinSetBackground(GC gc, int rgb)
+{
+ gc->background = rgb;
+}
+
+void WinCopyArea(Pixmap pix, HWND win, GC gc, int x, int y, int width, int height, int offx, int offy)
+{
+ HDC pixhdc = get_hdc((HWND)pix, gc), hdc = get_hdc(win, gc);
+ BitBlt(hdc, offx, offy, width, height, pixhdc, x, y, SRCCOPY);
+ release_hdc((HWND)pix, pixhdc);
+ release_hdc(win, hdc);
+}
+
+void WinDrawPoint(HWND win, GC gc, int x, int y)
+{
+ HDC hdc = get_hdc(win, gc);
+ SetPixelV(hdc, x, y, gc->foreground);
+ release_hdc(win, hdc);
+}
+
+void WinSetLineAttributes(GC gc, int width, int style, int capstyle, int joinstyle)
+{
+ gc->line_style = style;
+ gc->line_width = width;
+ gc->line_cap = capstyle;
+ gc->line_join = joinstyle;
+}
+
+void WinWarpPointer(HWND w, int x, int y)
+{
+ POINT pt;
+
+ pt.x = x;
+ pt.y = y;
+ ClientToScreen(w, &pt);
+ SetCursorPos(pt.x, pt.y);
+}
+
+void WinDrawLines(HWND win, GC gc, XPoint* pathlist, int number)
+{
+ LPPOINT pts = (LPPOINT)malloc(sizeof(POINT)*number);
+ HDC hdc = get_hdc(win, gc);
+ int i;
+
+ for (i=0; i<number; i++) {
+ pts[i].x = pathlist[i].x;
+ pts[i].y = pathlist[i].y;
+ }
+ Polyline(hdc, pts, number);
+ release_hdc(win, hdc);
+ free(pts);
+}
+
+void WinQueryPointer(HWND win, int *x, int *y)
+{
+ POINT pt;
+
+ if (GetCursorPos(&pt)) {
+ ScreenToClient(win, &pt);
+ *x = pt.x;
+ *y = pt.y;
+ }
+}
+
+void WinDrawRectangle(HWND win, GC gc, int x, int y, int width, int height)
+{
+ HDC hdc = get_hdc(win, gc);
+ Rectangle(hdc, x, y, x+width, y+height);
+ release_hdc(win, hdc);
+}
+
+GC WinCreateGC(HWND win, int mask, XGCValues *values)
+{
+ GC gc = (GC)malloc(sizeof(struct __GC));
+
+ gc->foreground = RGB(0, 0, 0);
+ gc->background = RGB(255, 255, 255);
+ gc->function = R2_COPYPEN;
+ gc->font = NULL;
+ gc->graphics_exposures = False;
+ gc->fill_style = BS_SOLID;
+ gc->fill_stipple = NULL;
+ gc->line_width = 0;
+ gc->line_style = PS_SOLID;
+ gc->line_cap = PS_ENDCAP_ROUND;
+ gc->line_join = PS_JOIN_BEVEL;
+ gc->line_dash_len = 0;
+ gc->line_dash = NULL;
+ gc->clipMask = NULL;
+
+ if (mask & GCForeground)
+ gc->foreground = values->foreground;
+ if (mask & GCBackground)
+ gc->background = values->background;
+ if (mask & GCFont)
+ gc->font = values->font;
+ if (mask & GCFunction)
+ gc->function = values->function;
+ if (mask & GCGraphicsExposures)
+ gc->graphics_exposures = values->graphics_exposures;
+
+ return gc;
+}
+
+void WinFreeGC(GC gc)
+{
+ free(gc);
+}
+
+void WinSetDashes(GC gc, int offset, char *dash, int n)
+{
+ if (gc->line_dash) {
+ free(gc->line_dash);
+ gc->line_dash = NULL;
+ gc->line_dash_len = 0;
+ }
+ if (n > 0 && dash != NULL) {
+ gc->line_dash = (char*)malloc(sizeof(char)*n);
+ memcpy(gc->line_dash, dash+offset, n);
+ gc->line_dash_len = n;
+ }
+}
+
+void WinSetFillStyle(GC gc, int style)
+{
+ gc->fill_style = style;
+}
+
+void WinSetStipple(GC gc, Pixmap pattern)
+{
+ gc->fill_stipple = pattern;
+}
+
+HCURSOR WinCreateStandardCursor(char *cur)
+{
+ return LoadCursor(NULL, cur);
+}
+
+void WinDrawString(HWND win, GC gc, int x, int y, const char *str, int len)
+{
+ HDC hdc = get_hdc(win, gc);
+ SIZE sz;
+ RECT r;
+
+ /*
+ GetTextExtentPoint32(hdc, str, len, &sz);
+ r.left = x;
+ r.right = x+sz.cx;
+ r.top = y-sz.cy;
+ r.bottom = y;
+ TextOut(hdc, r.left, r.top, str, len);
+ */
+ SetTextAlign(hdc, TA_LEFT|TA_BASELINE);
+ TextOut(hdc, x, y, str, len);
+ release_hdc(win, hdc);
+}
+
+int WinTextWidth(XFontStruct *fn, char *s, int len)
+{
+ HWND w = GetDesktopWindow();
+ HDC hdc = GetDC(w);
+ SIZE sz;
+
+ SelectObject(hdc, fn->fid);
+ GetTextExtentPoint32(hdc, s, len, &sz);
+ ReleaseDC(w, hdc);
+
+ return sz.cx;
+}
+
+void WinTextExtents(XFontStruct *fn, char *str, int len, int *width, int *height)
+{
+ HWND w = GetDesktopWindow();
+ HDC hdc = GetDC(w);
+ SIZE sz;
+
+ SelectObject(hdc, fn->fid);
+ GetTextExtentPoint32(hdc, str, len, &sz);
+ ReleaseDC(w, hdc);
+
+ *width = sz.cy;
+ *height = 0;
+}
+
+#define DUPBITS(x) (((x)<<8)|(x))
+
+void WinQueryColors(XColor *colors, int n)
+{
+ int i;
+
+ for (i=0; i<n; i++) {
+ colors[i].red = DUPBITS(GetRValue(colors[i].pixel));
+ colors[i].green = DUPBITS(GetGValue(colors[i].pixel));
+ colors[i].blue = DUPBITS(GetBValue(colors[i].pixel));
+ }
+}
+
+void WinAppMainLoop(void)
+{
+ MSG msg;
+ BOOL bRet;
+
+ DrawMenuBar(top->handle);
+ ShowWindow(top->handle, SW_SHOWNORMAL);
+ while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
+ if (bRet == -1) {
+ W32DEBUG(("Loop error\n"));
+ break;
+ } else {
+ if (GetAncestor(msg.hwnd, GA_ROOT) != topwin) {
+ TranslateMessage(&msg);
+ }
+ DispatchMessage(&msg);
+ }
+ }
+
+#ifdef USE_WIN32_COM
+ COM_terminate();
+#endif
+}
+
+void WinPutImage(HWND win, GC gc, XImage *img, int srcx, int srcy, int destx, int desty, int width, int height)
+{
+ HDC pixhdc, hdc;
+
+ if (img->handle == NULL) {
+ W32DEBUG(("Invalid image handle\n"));
+ return;
+ }
+
+ pixhdc = get_hdc((HWND)img->handle, gc);
+ hdc = get_hdc(win, gc);
+ if (gc->clipMask == NULL)
+ BitBlt(hdc, destx, desty, width, height, pixhdc, srcx, srcy, SRCCOPY);
+ else
+ MaskBlt(hdc, destx, desty, width, height, pixhdc, srcx, srcy, gc->clipMask, 0, 0, SRCCOPY);
+ release_hdc((HWND)img->handle, pixhdc);
+ release_hdc(win, hdc);
+}
+
+void WinSetClipMask(GC gc, Pixmap pix)
+{
+ gc->clipMask = pix;
+}
+
+typedef struct __win32_timer { int ID; void(*proc)(); void *data; struct __win32_timer *next; } win32_timer;
+static win32_timer *timers = NULL;
+
+VOID CALLBACK WinTimerProc(HWND hwnd, UINT umsg, UINT id, DWORD dwtime)
+{
+ win32_timer *t = timers, *prev = NULL;
+
+ for (; t!=NULL && t->ID != id; prev=t, t=t->next);
+ if (t == NULL) {
+ W32DEBUG(("Timer %d not found\n", id));
+ return;
+ }
+ if (prev == NULL)
+ timers = t->next;
+ else
+ prev->next = t->next;
+ KillTimer(NULL, t->ID);
+ (*t->proc)(t->data, &(t->ID));
+ free(t);
+}
+
+int WinAddTimeOut(int delay, void(*proc)(), void *data)
+{
+ win32_timer* t = (win32_timer*)malloc(sizeof(win32_timer));
+
+ t->proc = proc;
+ t->data = data;
+ t->ID = SetTimer(NULL, 0, delay, WinTimerProc);
+
+ if (t->ID == 0) {
+ free(t);
+ return -1;
+ } else {
+ t->next = timers;
+ timers = t;
+ return t->ID;
+ }
+}
+
+void WinRemoveTimeOut(int id)
+{
+ win32_timer *t = timers, *prev = NULL;
+
+ for (; t!=NULL && t->ID != id; prev=t, t=t->next);
+ if (t == NULL) {
+ return;
+ }
+ if (prev == NULL)
+ timers = t->next;
+ else
+ prev->next = t->next;
+ KillTimer(NULL, t->ID);
+ free(t);
+}
+
+void WinTranslateCoords(Widget win, short x, short y, short *rx, short *ry)
+{
+ POINT pt;
+
+ pt.x = x;
+ pt.y = y;
+ ClientToScreen(win->handle, &pt);
+ *rx = pt.x;
+ *ry = pt.y;
+}
+
+typedef struct {
+ char *request;
+ char *current;
+} InputDlgData;
+
+BOOL CALLBACK InputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ RECT r1, r2;
+ int w1, w2, h1, h2;
+
+ SetDlgItemText(hwnd, IDC_EDIT1, ((InputDlgData*)lParam)->current);
+ SetDlgItemText(hwnd, IDC_INFOTEXT, ((InputDlgData*)lParam)->request);
+ GetWindowRect(GetParent(hwnd), &r1);
+ GetWindowRect(hwnd, &r2);
+ w1 = r1.right-r1.left;
+ w2 = r2.right-r2.left;
+ h1 = r1.bottom-r1.top;
+ h2 = r2.bottom-r2.top;
+ SetWindowPos(hwnd, HWND_TOP, r1.left+(w1-w2)/2, r1.top+(h1-h2)/2, 0, 0, SWP_NOSIZE);
+ SendMessage(GetDlgItem(hwnd, IDC_EDIT1), EM_SETSEL, 0, -1);
+ SetFocus(GetDlgItem(hwnd, IDC_EDIT1));
+ return FALSE;
+ }
+ case WM_COMMAND:
+ if (HIWORD(wParam) == BN_CLICKED)
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ GetDlgItemText(hwnd, IDC_EDIT1, _STR2, sizeof(_STR2));
+ EndDialog(hwnd, 1);
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hwnd, 0);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+#define HELP_MARGIN 10
+
+BOOL CALLBACK HelpDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ RECT br, r, cr, pr, pcr;
+ int sbwidth;
+
+ GetWindowRect(hwnd, &r);
+ GetClientRect(hwnd, &cr);
+ GetClientRect(GetDlgItem(hwnd, IDOK), &br);
+ GetWindowRect(GetDlgItem(hwnd, IDC_HELPPIX), &pr);
+ GetClientRect(GetDlgItem(hwnd, IDC_HELPPIX), &pcr);
+ sbwidth = (pr.right-pr.left)-(pcr.right-pcr.left);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, sbwidth+helpwidth+2*HELP_MARGIN+(r.right-r.left)-(cr.right-cr.left),
+ r.bottom-r.top, SWP_NOMOVE);
+ GetClientRect(hwnd, &cr);
+ SetWindowPos(GetDlgItem(hwnd, IDC_HELPPIX), HWND_TOP, HELP_MARGIN, HELP_MARGIN, helpwidth+sbwidth,
+ (cr.bottom-cr.top)-(br.bottom-br.top)-3*HELP_MARGIN, 0);
+ SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_TOP,
+ HELP_MARGIN+((cr.right-cr.left)-(br.right-br.left))/2, cr.bottom-HELP_MARGIN-(br.bottom-br.top),
+ br.right-br.left, br.bottom-br.top, 0);
+ SetFocus(GetDlgItem(hwnd, IDC_HELPPIX));
+ }
+ return FALSE;
+ case WM_COMMAND:
+ if (HIWORD(wParam) == BN_CLICKED)
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwnd, 1);
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+void popupprompt(Widget button, char *request, char *current, void (*function)(), buttonsave *datastruct, const char *filter)
+{
+ if (current != NULL && filter == NULL) {
+ InputDlgData data;
+
+ data.request = request;
+ data.current = current;
+ if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_INPUTDIALOG), areawin->window, InputDlgProc, (LPARAM)&data))
+ (*function)(button, (datastruct != NULL ? datastruct->dataptr : NULL));
+ } else if (filter != NULL) {
+ OPENFILENAME ofn;
+ char filename[1024] = {0};
+ char filterspec[1024] = {0};
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = areawin->window;
+ if (*filter) {
+ _snprintf(filterspec, 1024, "Enable Filter (*%s)%c*%s%cDisable Filter (*.*)%c*.*%c%c%c",
+ filter, 0, filter, 0, 0, 0, 0, 0);
+ ofn.lpstrFilter = filterspec;
+ } else
+ ofn.lpstrFilter = "All Files (*.*)\000*.*\000\000\000";
+ ofn.lpstrFile = filename;
+ ofn.nMaxFile = 1024;
+ if (GetOpenFileName(&ofn)) {
+ char *c;
+ strcpy(_STR2, ofn.lpstrFile);
+ for (c=_STR2; *c; c++)
+ if (*c == '\\') *c = '/';
+ (*function)(button, datastruct->dataptr);
+ }
+ } else {
+ if (MessageBox(areawin->window, request, "XCircuit", MB_YESNO|MB_ICONQUESTION) == IDYES)
+ (*function)(button, datastruct->dataptr);
+ }
+
+ if (datastruct != NULL) free(datastruct);
+}
+
+static void get_vkey_name(int key, char *str, int len)
+{
+ UINT scan = MapVirtualKey(key, 0);
+ scan = (scan&0xff)<<16;
+ switch (key) {
+ case VK_HOME:
+ case VK_PRIOR:
+ case VK_NEXT:
+ case VK_END:
+ case VK_DELETE:
+ case VK_INSERT:
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_UP:
+ case VK_DOWN:
+ scan |= (1<<24);
+ break;
+ case VK_CLEAR:
+ memcpy(str, "CLEAR", 5);
+ return;
+ default:
+ break;
+ }
+ GetKeyNameText(scan, str, len);
+}
+
+char *WinKeyToString(int key)
+{
+ static char buffer[1024];
+
+ memset(buffer, 0, 1024);
+ if (key >= XK_a && key <= XK_z)
+ buffer[0] = (char)key;
+ else if (key >= XK_A && key <= XK_Z)
+ buffer[0] = (char)key;
+ else {
+ int offset = 0;
+
+ if (key & KPMOD) {
+ strcpy(buffer, "Keypad_");
+ offset = 7;
+ }
+ if (key & VKMOD)
+ get_vkey_name(key&0x00ff, buffer+offset, 1024-offset);
+ else
+ buffer[offset] = key&0x00ff;
+ }
+
+ return buffer;
+}
+
+int WinStringToKey(const char *str)
+{
+ int key;
+ char buf[256];
+
+ for (key=1; key<256; key++) {
+ memset(buf, 0, 256);
+ get_vkey_name(key, buf, 256);
+ if (strcmp(str, buf) == 0)
+ return key;
+ }
+ return 0;
+}
+
+static Widget WndFound;
+
+BOOL CALLBACK WndLookupProc(HWND hwnd, LPARAM lParam)
+{
+ Widget w = (Widget)get_widget(hwnd);
+
+ if (w != NULL && strcmp((char*)lParam, w->name) == 0) {
+ WndFound = w;
+ W32DEBUG(("widget name: '%s'\n", w->name));
+ return FALSE;
+ }
+ W32DEBUG(("widget name: '%s' (%p)\n", (w ? w->name : (char*)w)));
+ return TRUE;
+}
+
+const char* WinName(Widget w)
+{
+ switch (w->type) {
+ case WIN_WIDGET:
+ return w->name;
+ case WIN_MENUITEM:
+ return TOMENUITEM(w)->name;
+ case WIN_TOOLITEM:
+ return TOTOOLITEM(w)->name;
+ default:
+ return NULL;
+ }
+}
+
+Widget WinNameToWindow(Widget parent, const char *name)
+{
+ W32DEBUG(("Looking for '%s' in %p\n", name, parent));
+ WndFound = NULL;
+ if (parent != NULL)
+ switch (parent->type) {
+ case WIN_WIDGET:
+ if (parent == toolBar) {
+ TBBUTTON tb;
+ int nbuttons = SendMessage(toolBar->handle, TB_BUTTONCOUNT, 0, 0), i;
+ for (i=0; i<nbuttons; i++) {
+ ZeroMemory(&tb, sizeof(tb));
+ SendMessage(toolBar->handle, TB_GETBUTTON, i, (LPARAM)&tb);
+ if (tb.dwData != 0) {
+ ToolItem item = (ToolItem)tb.dwData;
+ if (item->name && strcmp(item->name, name) == 0) {
+ WndFound = (Widget)item;
+ break;
+ }
+ }
+ }
+ } else
+ EnumChildWindows(parent->handle, WndLookupProc, (LPARAM)name);
+ break;
+ case WIN_MENUITEM:
+ if (TOMENUITEM(parent)->popup != NULL)
+ parent = (Widget)TOMENUITEM(parent)->popup;
+ else
+ break;
+ case WIN_MENU:
+ {
+ int i, n = GetMenuItemCount((HMENU)parent->handle);
+ MENUITEMINFO mi_info;
+
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_DATA;
+ for (i=0; i<n; i++) {
+ mi_info.dwItemData = (LONG)NULL;
+ if (GetMenuItemInfo((HMENU)parent->handle, i, MF_BYPOSITION, &mi_info)
+ && mi_info.dwItemData && ((MenuItem)mi_info.dwItemData)->name
+ && strcmp(((MenuItem)mi_info.dwItemData)->name, name) == 0) {
+ WndFound = (Widget)mi_info.dwItemData;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return WndFound;
+}
+
+void outputpopup(Widget button, caddr_t clientdata, caddr_t calldata)
+{
+ if (is_page(topobject) == -1) {
+ Wprintf("Can only save a top-level page!");
+ return;
+ }
+ DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OUTPUTDLG), top->handle, OutputDlgProc);
+}
+
+typedef struct {
+ char *bits;
+ int width, height;
+} cursor_bits;
+
+static u_char reverse_byte(u_char c)
+{
+ u_char rc = 0;
+ int i;
+
+ for (i=(sizeof(char)*8-1); i>=0; i--, c>>=1)
+ rc |= (c&0x01) << i;
+ return rc;
+}
+
+static void compute_cursor_src_mask(u_char *src, u_char *mask)
+{
+ u_char pixsrc = *src, pixmask = *mask;
+ *src = ~(reverse_byte(pixmask));
+ *mask = reverse_byte((u_char)((~pixsrc&0xff)&pixmask));
+}
+
+static HBITMAP create_stipple(char *stipdata)
+{
+ HBITMAP hBitmap;
+ BYTE data[8];
+ int i;
+
+ for (i=0; i<4; i++) {
+ data[2*i] = 0xff & ~reverse_byte(stipdata[i]);
+ }
+ hBitmap = CreateBitmap(4, 4, 1, 1, data);
+ return hBitmap;
+}
+
+HBITMAP WinCreateBitmapFromData(HWND w, char *data, int width, int height)
+{
+ if (width == 4 && height == 4) {
+ return create_stipple(data);
+ } else {
+ cursor_bits *cbits = (cursor_bits*)malloc(sizeof(cursor_bits));
+ cbits->bits = data;
+ cbits->width = width;
+ cbits->height = height;
+ return (HBITMAP)cbits;
+ }
+}
+
+HCURSOR WinCreateCursor(HBITMAP _src, HBITMAP _mask, int xhot, int yhot)
+{
+ HCURSOR hCursor = NULL;
+ u_char *src = ((cursor_bits*)_src)->bits, *mask = ((cursor_bits*)_mask)->bits;
+ u_char *new_src, *new_mask;
+ int width = ((cursor_bits*)_src)->width, height = ((cursor_bits*)_src)->height;
+ int nb = (width-1)/(8*sizeof(char))+1;
+ int nb2 = (GetSystemMetrics(SM_CXCURSOR)-1)/(8*sizeof(char))+1, height2 = GetSystemMetrics(SM_CYCURSOR);
+ int i, j, idx1 = 0, idx2 = 0;
+
+ new_src = (u_char*)malloc(sizeof(char)*nb2*height2);
+ new_mask = (u_char*)malloc(sizeof(char)*nb2*height2);
+
+ for (j=0; j<height; j++) {
+ for (i=0; i<nb; i++, idx1++, idx2++) {
+ new_src[idx2] = src[idx1];
+ new_mask[idx2] = mask[idx1];
+ compute_cursor_src_mask(&new_src[idx2], &new_mask[idx2]);
+ }
+ for (i=0; i<(nb2-nb); i++, idx2++) {
+ new_src[idx2] = 0xff;
+ new_mask[idx2] = 0x00;
+ }
+ }
+ for (j=0; j<(height2-height); j++) {
+ for (i=0; i<nb2; i++, idx2++) {
+ new_src[idx2] = 0xff;
+ new_mask[idx2] = 0x00;
+ }
+ }
+
+ hCursor = CreateCursor(GetModuleHandle(NULL), xhot, yhot, nb2*8, height2, new_src, new_mask);
+
+ free(new_src);
+ free(new_mask);
+ free(_src);
+ free(_mask);
+
+ return hCursor;
+}
+
+static Widget create_widget(HWND handle, char *name)
+{
+ Widget w = (Widget)malloc(sizeof(struct __WinWidget));
+
+ ZeroMemory(w, sizeof(struct __WinWidget));
+ w->type = WIN_WIDGET;
+ w->handle = handle;
+ w->name = strdup(name);
+ if (strcmp(name, "Area") == 0) {
+ RECT r;
+ GetWindowRect(handle, &r);
+ w->buffer = WinCreatePixmap(handle, r.right-r.left, r.bottom-r.top);
+ w->bufhdc = CreateCompatibleDC(NULL);
+ SelectObject(w->bufhdc, w->buffer);
+ }
+ SetWindowLong(handle, GWL_USERDATA, (LONG)w);
+ return w;
+}
+
+static void destroy_widget(HWND handle)
+{
+ Widget w = (Widget)get_widget(handle);
+ WinCallback *cb = w->callbacks, *free_cb;
+ WinEventHandler *eh = w->handlers, *free_eh;
+
+ free(w->name);
+ while (cb != NULL) {
+ free_cb = cb;
+ cb = cb->next;
+ free(free_cb);
+ }
+ while (eh != NULL) {
+ free_eh = eh;
+ eh = eh->next;
+ free(free_eh);
+ }
+ if (w->wndproc != NULL)
+ SetWindowLong(handle, GWL_WNDPROC, (LONG)w->wndproc);
+ free(w);
+}
+
+LRESULT CALLBACK XcTopWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_CLOSE:
+ quitcheck(NULL, NULL, NULL);
+ return 0;
+ case WM_ACTIVATE:
+ if (wParam != 0) {
+ XCWindowData *w;
+
+ for (w=xobjs.windowlist; w!=NULL; w=w->next)
+ if (GetAncestor(w->window, GA_ROOT) == hwnd)
+ break;
+ if (w != NULL && areawin != w) {
+ areawin = w;
+ top = get_widget(GetAncestor(areawin->window, GA_ROOT));
+ topwin = top->handle;
+ toolBar = get_widget(GetDlgItem(topwin, TOOLBAR_ID));
+ statusBar = GetDlgItem(topwin, STATUSBAR_ID);
+ {
+ MENUITEMINFO mi_info;
+ HMENU hMenu = GetMenu(hwnd);
+ int i;
+
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ for (i=0; i<MaxMenuWidgets; i++) {
+ mi_info.fMask = MIIM_DATA;
+ mi_info.dwItemData = (LONG)NULL;
+ if (GetMenuItemInfo(hMenu, 100+i, FALSE, &mi_info))
+ menuwidgets[i] = (Widget)mi_info.dwItemData;
+ else
+ printf("menu not found: %d\n", i);
+ }
+ }
+ }
+ SetFocus(areawin->window);
+ }
+ return 0;
+ case WM_SIZE:
+ {
+ int width = LOWORD(lParam), th, sh, height = HIWORD(lParam), nbrows = 1;
+ DWORD sz;
+ RECT sr;
+
+ SetWindowPos(toolBar->handle, HWND_TOP, 0, 0, width, 25, 0);
+
+ sz = SendMessage(toolBar->handle, TB_GETBUTTONSIZE, 0, 0);
+ nbrows = SendMessage(toolBar->handle, TB_GETROWS, 0, 0);
+ th = nbrows*HIWORD(sz)+6;
+ GetWindowRect(statusBar, &sr);
+ sh = sr.bottom-sr.top;
+
+ SetWindowPos(areawin->area->handle, HWND_TOP, SBARSIZE, th, width-SBARSIZE, height-sh-th-SBARSIZE, 0);
+ SetWindowPos(areawin->scrollbarh->handle, HWND_TOP, SBARSIZE, height-sh-SBARSIZE, width-SBARSIZE, SBARSIZE, 0);
+ SetWindowPos(areawin->scrollbarv->handle, HWND_TOP, 0, th, SBARSIZE, height-sh-th-SBARSIZE, 0);
+ SetWindowPos(corner, HWND_TOP, 0, height-sh-SBARSIZE, 0, 0, SWP_NOSIZE);
+ SetWindowPos(statusBar, HWND_TOP, 0, height-sh, width, sh, 0);
+ InvalidateRect(statusBar, NULL, FALSE);
+ SetWindowPos(toolBar->handle, HWND_TOP, 0, 0, width, th, 0);
+ InvalidateRect(toolBar->handle, NULL, FALSE);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_MENUCOMMAND:
+ {
+ MENUITEMINFO mi_info;
+ MenuItem item;
+
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_DATA;
+ GetMenuItemInfo((HMENU)lParam, wParam, MF_BYPOSITION, &mi_info);
+
+ if ((item = (MenuItem)mi_info.dwItemData) != NULL && item->callbacks != NULL) {
+ W32DEBUG(("Calling callback\n"));
+ execute_callback(XtNselect, (Widget)item, NULL);
+ }
+ }
+ return 0;
+ case WM_COMMAND:
+ if ((HWND)lParam == toolBar->handle) {
+ TBBUTTONINFO tbi;
+
+ ZeroMemory(&tbi, sizeof(tbi));
+ tbi.cbSize = sizeof(tbi);
+ tbi.dwMask = TBIF_LPARAM;
+ if (SendMessage(toolBar->handle, TB_GETBUTTONINFO, LOWORD(wParam), (LPARAM)&tbi) != -1) {
+ ToolItem item = (ToolItem)tbi.lParam;
+ W32DEBUG(("Tool button: %s\n", item->name));
+ execute_callback(XtNselect, (Widget)item, NULL);
+ }
+ }
+ return 0;
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+}
+
+void button_event(Widget win, int type, int button, short x, short y)
+{
+ XButtonEvent event;
+
+ event.type = type;
+ event.x = x;
+ event.y = y;
+ event.button = (button & MK_LBUTTON ? Button1 : 0) |
+ (button & MK_RBUTTON ? Button3 : 0) |
+ (button & MK_MBUTTON ? Button2 : 0) |
+ (button & MK_XBUTTON1 ? Button4 : 0) |
+ (button & MK_XBUTTON2 ? Button5 : 0);
+ event.state = (GetKeyState(VK_CONTROL) & 0x8000 ? ControlMask : 0) |
+ (GetKeyState(VK_SHIFT) & 0x8000 ? ShiftMask : 0) |
+ (GetKeyState(VK_MENU) & 0x8000 ? Mod1Mask : 0);
+
+ if (win == areawin->scrollbarh || win == areawin->scrollbarv)
+ if (type == ButtonPress)
+ SetCapture(win->handle);
+ else if (type == ButtonRelease)
+ ReleaseCapture();
+
+ switch (type) {
+ case ButtonPress:
+ execute_callback(XtNselect, win, &event);
+ break;
+ case ButtonRelease:
+ execute_callback(XtNrelease, win, &event);
+ break;
+ case MotionNotify:
+ if (event.button && HAS_HANDLER(win, ButtonMotionMask))
+ execute_handler(ButtonMotionMask, win, &event);
+ if ((event.button & Button1Mask) && HAS_HANDLER(win, Button1MotionMask))
+ execute_handler(Button1MotionMask, win, &event);
+ if ((event.button & Button2Mask) && HAS_HANDLER(win, Button2MotionMask))
+ execute_handler(Button2MotionMask, win, &event);
+ if (HAS_HANDLER(win, PointerMotionMask))
+ execute_handler(PointerMotionMask, win, &event);
+ break;
+ }
+}
+
+void key_event(Widget win, int type, int key, int scan)
+{
+ POINT pt;
+ static BYTE keys[256];
+ WORD c = 0x0000;
+ XKeyEvent event;
+
+ GetCursorPos(&pt);
+ ScreenToClient(win->handle, &pt);
+ event.type = type;
+ event.x = pt.x;
+ event.y = pt.y;
+ event.state = 0;
+ event.keycode = 0;
+
+ GetKeyboardState(keys);
+ if (keys[VK_CONTROL] & 0x80) { event.state |= ControlMask; keys[VK_CONTROL] &= ~0x80; }
+ if (keys[VK_MENU] & 0x80) { event.state |= Mod1Mask; keys[VK_MENU] &= ~0x80; }
+ keys[VK_NUMLOCK] &= 0x01;
+ if (ToAscii(key, scan, keys, &c, 0) == 1 && c >= ' ' && c <= '~') {
+ W32DEBUG(("char: %c (%08x)\n", c, c));
+ event.keycode = 0xff & c;
+ switch (c) {
+ case '/':
+ if (scan & 0x1000000) event.keycode |= KPMOD;
+ break;
+ case '*':
+ case '-':
+ case '+':
+ if ((VkKeyScan(c)&0xff) != key)
+ event.keycode |= KPMOD;
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (keys[VK_SHIFT] & 0x80) event.state |= ShiftMask;
+ event.keycode |= VKMOD;
+ switch (key) {
+ case VK_RETURN:
+ if (scan & 0x1000000) event.keycode |= KPMOD;
+ else event.keycode |= VKMOD;
+ break;
+ case VK_HOME:
+ case VK_UP:
+ case VK_PRIOR:
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_END:
+ case VK_DOWN:
+ case VK_NEXT:
+ case VK_DELETE:
+ if (!(scan & 0x1000000)) event.keycode |= KPMOD;
+ else event.keycode |= VKMOD;
+ break;
+ case VK_CLEAR:
+ if (scan == 0x004c0001 || scan == 0xc04c0001) event.keycode |= KPMOD;
+ break;
+ default:
+ event.keycode |= VKMOD;
+ break;
+ }
+ event.keycode |= key;
+ W32DEBUG(("non char: %d\n", event.keycode));
+ }
+
+ switch (type) {
+ case KeyPress:
+ execute_callback(XtNkeyDown, win, &event);
+ break;
+ case KeyRelease:
+ execute_callback(XtNkeyUp, win, &event);
+ break;
+ }
+}
+
+LRESULT CALLBACK XcWidgetProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget win = (Widget)get_widget(hwnd);
+
+ switch (msg) {
+ case WM_DESTROY:
+ destroy_widget(hwnd);
+ return 0;
+ case WM_PAINT:
+ {
+ RECT r;
+ GetUpdateRect(hwnd, &r, FALSE);
+ if (win != NULL)
+ execute_callback(XtNexpose, win, NULL);
+ ValidateRect(hwnd, &r);
+ }
+ return 0;
+ case WM_SIZE:
+ InvalidateRect(hwnd, NULL, FALSE);
+ if (win != NULL) {
+ execute_callback(XtNresize, win, NULL);
+ if (win->buffer != NULL) {
+ WinFreePixmap(win->buffer);
+ win->buffer = WinCreatePixmap(hwnd, LOWORD(lParam), HIWORD(lParam));
+ SelectObject(win->bufhdc, win->buffer);
+ }
+ }
+ return 0;
+ case WM_CHAR:
+ W32DEBUG(("WM_CHAR: %08x %08x\n", wParam, lParam));
+ return 0;
+ case WM_SYSKEYDOWN:
+ if (wParam == VK_MENU || (wParam == VK_F4 && GetKeyState(VK_MENU) && 0x8000))
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_KEYDOWN:
+ W32DEBUG(("WM_KEYDOWN: %08x %08x %08x\n", wParam, lParam, MapVirtualKey((0x00ff0000&lParam)>>16, 1)));
+ key_event(win, KeyPress, MapVirtualKey((0x00ff0000&lParam)>>16, 1), lParam);
+ return 0;
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_KEYUP:
+ W32DEBUG(("WM_KEYUP: %08x %08x\n", wParam, lParam));
+ key_event(win, KeyRelease, MapVirtualKey((0x00ff0000&lParam)>>16, 1), lParam);
+ return 0;
+ case WM_MOUSEMOVE:
+ button_event(win, MotionNotify, wParam, LOWORD(lParam), HIWORD(lParam));
+ return 0;
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ button_event(win, ButtonPress, wParam, LOWORD(lParam), HIWORD(lParam));
+ return 0;
+ case WM_RBUTTONUP:
+ button_event(win, ButtonRelease, MK_RBUTTON, LOWORD(lParam), HIWORD(lParam));
+ return 0;
+ case WM_MBUTTONUP:
+ button_event(win, ButtonRelease, MK_MBUTTON, LOWORD(lParam), HIWORD(lParam));
+ return 0;
+ case WM_LBUTTONUP:
+ button_event(win, ButtonRelease, MK_LBUTTON, LOWORD(lParam), HIWORD(lParam));
+ return 0;
+ case WM_MOUSEWHEEL:
+ {
+ SHORT delta = HIWORD(wParam);
+ panbutton((delta > 0 ? 3 : 4), 0, 0, 0.05);
+ refresh(NULL, NULL, NULL);
+ }
+ return 0;
+ case WM_HSCROLL:
+ switch (LOWORD(wParam)) {
+ case SB_LINELEFT:
+ panbutton(1, 0, 0, 0.03);
+ break;
+ case SB_LINERIGHT:
+ panbutton(2, 0, 0, 0.03);
+ break;
+ }
+ refresh(NULL, NULL, NULL);
+ return 0;
+ default:
+ if (msg == WM_BITBLT && win != NULL && win->buffer != NULL) {
+ HDC winhdc = GetDC(hwnd);
+ RECT r;
+ MSG pmsg;
+
+ while (PeekMessage(&pmsg, hwnd, WM_BITBLT, WM_BITBLT, PM_REMOVE));
+ GetWindowRect(hwnd, &r);
+ BitBlt(winhdc, 0, 0, r.right-r.left, r.bottom-r.top, win->bufhdc, 0, 0, SRCCOPY);
+ ReleaseDC(hwnd, winhdc);
+ return 0;
+ } else
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+}
+
+LRESULT CALLBACK XcHelppixProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_GETDLGCODE:
+ return DLGC_WANTARROWS;
+ case WM_CREATE:
+ if (helppix == NULL)
+ printhelppix();
+ helptop = 0;
+ return 0;
+ case WM_SIZE:
+ {
+ SCROLLINFO si;
+
+ si.cbSize = sizeof(SCROLLINFO);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = (helpheight-HIWORD(lParam)+400-1);
+ si.nPage = 400;
+ si.nPos = 0;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ return 0;
+ }
+ case WM_PAINT:
+ {
+ HDC hdc, pixhdc;
+ PAINTSTRUCT ps;
+ RECT r;
+
+ hdc = BeginPaint(hwnd, &ps);
+ pixhdc = get_hdc(helppix, hgc);
+ GetClientRect(hwnd, &r);
+ BitBlt(hdc, 0, 0, r.right-r.left, r.bottom-r.top, pixhdc, 0, helptop, SRCCOPY);
+ release_hdc(helppix, pixhdc);
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+ break;
+ case WM_VSCROLL:
+ {
+ SCROLLINFO si;
+ int pos;
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ switch (LOWORD(wParam)) {
+ case SB_PAGEUP:
+ si.nPos -= si.nPage;
+ break;
+ case SB_PAGEDOWN:
+ si.nPos += si.nPage;
+ break;
+ case SB_LINEUP:
+ si.nPos -= 15;
+ break;
+ case SB_LINEDOWN:
+ si.nPos += 15;
+ break;
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+ }
+ si.fMask = SIF_POS;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ helptop = si.nPos;
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+ return 0;
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_NEXT:
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
+ break;
+ case VK_PRIOR:
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
+ break;
+ case VK_DOWN:
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
+ break;
+ case VK_UP:
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
+ break;
+ }
+ return 0;
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+}
+
+static XFontStruct* create_font_struct(HFONT hFont)
+{
+ TEXTMETRIC tm;
+ XFontStruct *fs = NULL;
+ HDC hdc = GetDC(NULL);
+
+ SelectObject(hdc, hFont);
+ if (GetTextMetrics(hdc, &tm)) {
+ fs = (XFontStruct*)malloc(sizeof(XFontStruct));
+ fs->ascent = tm.tmAscent;
+ fs->descent = tm.tmDescent;
+ fs->fid = hFont;
+ } else {
+ W32DEBUG(("Failed to create font structure\n"));
+ }
+ ReleaseDC(NULL, hdc);
+
+ return fs;
+}
+
+static menuID = 100;
+
+static Menu create_win_menu(HMENU menu)
+{
+ Menu wmenu = (Menu)malloc(sizeof(struct __WinMenu));
+ MENUINFO minfo;
+
+ wmenu->type = WIN_MENU;
+ wmenu->handle = menu;
+ minfo.cbSize = sizeof(MENUINFO);
+ minfo.fMask = MIM_MENUDATA | MIM_STYLE;
+ minfo.dwStyle = MNS_NOTIFYBYPOS;
+ minfo.dwMenuData = (DWORD)wmenu;
+ SetMenuInfo(menu, &minfo);
+
+ return wmenu;
+}
+
+static MenuItem insert_win_menuitem(Menu menu, MENUITEMINFO* mi_info, menustruct *ms, int pos)
+{
+ MenuItem item = (MenuItem)malloc(sizeof(struct __WinMenuItem));
+
+ ZeroMemory(item, sizeof(struct __WinMenuItem));
+ item->type = WIN_MENUITEM;
+ item->parentMenu = menu;
+ if (mi_info->fMask & MIIM_SUBMENU && mi_info->hSubMenu != NULL) {
+ MENUINFO popup_info;
+ ZeroMemory(&popup_info, sizeof(popup_info));
+ popup_info.cbSize = sizeof(popup_info);
+ popup_info.fMask = MIM_MENUDATA;
+ if (GetMenuInfo(mi_info->hSubMenu, &popup_info))
+ item->popup = (Menu)popup_info.dwMenuData;
+ }
+ else if (mi_info->fMask & MIIM_ID) {
+ item->ID = mi_info->wID;
+ menuwidgets[mi_info->wID-100] = (Widget)item;
+ } else if (!(mi_info->fMask & MIIM_FTYPE && mi_info->fType == MFT_SEPARATOR)){
+ }
+ if (ms != NULL) {
+ if (ms->func != NULL && ms->func != DoNothing)
+ WinAddCallback((Widget)item, XtNselect, ms->func, ms->passeddata);
+ item->name = strdup(ms->name);
+ }
+ if (pos < 0)
+ pos = GetMenuItemCount(menu->handle);
+ item->position = pos;
+ item->menudata = mi_info->dwItemData;
+ mi_info->fMask |= MIIM_DATA;
+ mi_info->dwItemData = (DWORD)item;
+ InsertMenuItem(menu->handle, item->position, MF_BYPOSITION, mi_info);
+ for (pos++; pos<GetMenuItemCount(menu->handle); pos++) {
+ MENUITEMINFO info;
+ ZeroMemory(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_DATA;
+ GetMenuItemInfo(menu->handle, pos, MF_BYPOSITION, &info);
+ TOMENUITEM(info.dwItemData)->position = pos;
+ }
+ return item;
+}
+
+#if 0
+#define MENUICON_WIDTH GetSystemMetrics(SM_CXMENUCHECK)
+#define MENUICON_HEIGHT GetSystemMetrics(SM_CYMENUCHECK)
+#else
+#define MENUICON_WIDTH 12
+#define MENUICON_HEIGHT 12
+#endif
+
+static HBITMAP create_color_icon(int color, int width, int height)
+{
+ HDC hdc = GetDC(NULL);
+ HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
+ HBRUSH hBrush = CreateSolidBrush(color);
+ RECT r = {0, 0};
+
+ ReleaseDC(NULL, hdc);
+ r.right = width;
+ r.bottom = height;
+ hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, hBitmap);
+ FillRect(hdc, &r, hBrush);
+ DeleteObject(hBrush);
+ DeleteDC(hdc);
+
+ return hBitmap;
+}
+
+static HBITMAP create_stipple_icon(int stipdata, int width, int height)
+{
+ HDC hdc = GetDC(NULL);
+ HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
+ HBRUSH hBrush = CreatePatternBrush(STIPPLE[stipdata]);
+ RECT r = {0, 0};
+
+ ReleaseDC(NULL, hdc);
+ r.right = width;
+ r.bottom = height;
+ hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, hBitmap);
+ FillRect(hdc, &r, hBrush);
+ DeleteObject(hBrush);
+ DeleteDC(hdc);
+
+ return hBitmap;
+}
+
+static char* color_string(int c)
+{
+ static char buf[256];
+ char *cname = WinColorName(c);
+
+ if (cname)
+ _snprintf(buf, 256, " %s", cname);
+ else
+ _snprintf(buf, 256, " %3d, %3d, %3d", GetRValue(c), GetGValue(c), GetBValue(c));
+ return buf;
+}
+
+static void makesubmenu(Menu menu, menustruct *items, int n);
+static void make_color_submenu(Menu menu, menustruct *items, int n)
+{
+ if (dpy == NULL)
+ makesubmenu(menu, items, n);
+ else {
+ int i;
+ MENUITEMINFO mi_info;
+ MenuItem item;
+
+ makesubmenu(menu, items, 3);
+ menuID += (n-3);
+ for (i=0; i<number_colors; i++) {
+ int color = colorlist[i].color.pixel;
+ HBITMAP hBitmap = create_color_icon(color, MENUICON_WIDTH, MENUICON_HEIGHT);
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_BITMAP | MIIM_STRING;
+ mi_info.hbmpItem = hBitmap;
+ mi_info.dwTypeData = color_string(color);
+ mi_info.dwItemData = color;
+
+ item = insert_win_menuitem(menu, &mi_info, NULL, -1);
+ item->name = strdup(mi_info.dwTypeData);
+ WinAddCallback((Widget)item, XtNselect, (XtCallbackProc)setcolor, NULL);
+ }
+ }
+
+}
+
+static void makesubmenu(Menu menu, menustruct *items, int n)
+{
+ int i;
+ MENUITEMINFO mi_info;
+ int is_color = -1;
+ MenuItem mitem;
+
+ for (i=0; i<n; i++) {
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ if (items[i].submenu == NULL) {
+ if (items[i].name[0] == ' ') {
+ mi_info.fMask = MIIM_FTYPE;
+ mi_info.fType = MFT_SEPARATOR;
+ }
+ else if (items[i].name[0] == '_') {
+ int color = WinNamedColor(items[i].name+1);
+ HBITMAP hBitmap = create_color_icon(color, MENUICON_WIDTH, MENUICON_HEIGHT);
+ mi_info.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
+ mi_info.wID = menuID++;
+ mi_info.hbmpItem = hBitmap;
+ mi_info.dwTypeData = color_string(color);
+ mi_info.dwItemData = color;
+ is_color = color;;
+ } else if (items[i].name[0] == ':') {
+ HBITMAP hBitmap;
+ if ((int)items[i].passeddata == (OPAQUE | FILLED | FILLSOLID))
+ hBitmap = create_color_icon(RGB(0, 0, 0), MENUICON_WIDTH, MENUICON_HEIGHT);
+ else
+ hBitmap = create_stipple_icon(((int)items[i].passeddata & FILLSOLID)>>5, MENUICON_WIDTH, MENUICON_HEIGHT);
+ mi_info.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
+ mi_info.wID = menuID++;
+ mi_info.hbmpItem = hBitmap;
+ mi_info.dwTypeData = items[i].name;
+ mi_info.dwItemData = (DWORD)items[i].passeddata;
+ } else {
+ mi_info.fMask = MIIM_STRING | MIIM_ID;
+ mi_info.wID = menuID++;
+ mi_info.dwTypeData = items[i].name;
+ }
+ } else {
+ Menu popup = create_win_menu(CreatePopupMenu());
+ if (strncmp(items[i].name, "Color", 5) == 0)
+ make_color_submenu(popup, items[i].submenu, items[i].size);
+ else
+ makesubmenu(popup, items[i].submenu, items[i].size);
+ mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
+ mi_info.hSubMenu = popup->handle;
+ mi_info.dwTypeData = items[i].name;
+ }
+ mitem = insert_win_menuitem(menu, &mi_info, &items[i], -1);
+ if (is_color != -1 && dpy == NULL)
+ addtocolorlist((Widget)mitem, is_color);
+ }
+}
+
+static HMENU create_menus()
+{
+ Menu menu;
+ MENUITEMINFO mi_info;
+ int i;
+
+ menuID = 100;
+ menu = create_win_menu(CreateMenu());
+ for (i=0; i<maxbuttons; i++) {
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ if (TopButtons[i].submenu == NULL) {
+ mi_info.fMask = MIIM_STRING | MIIM_ID;
+ mi_info.wID = menuID++;
+ mi_info.dwTypeData = TopButtons[i].name;
+ } else {
+ Menu popup = create_win_menu(CreatePopupMenu());
+ makesubmenu(popup, TopButtons[i].submenu, TopButtons[i].size);
+ mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
+ mi_info.hSubMenu = popup->handle;
+ mi_info.dwTypeData = TopButtons[i].name;
+ }
+ insert_win_menuitem(menu, &mi_info, &TopButtons[i], -1);
+ }
+
+ return menu->handle;
+}
+
+static void create_statusbar()
+{
+ HDC hdc;
+ SIZE sz;
+ StatusItem msg2, msg3;
+
+ hdc = GetDC(NULL);
+ GetTextExtentPoint32(hdc, "Editing: filename (Page 1)", 26, &sz);
+ statusBarWidth[0] = sz.cx;
+ ReleaseDC(NULL, hdc);
+
+ statusBar = CreateWindow(STATUSCLASSNAME, "", WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP,
+ 0, 0, 100, 100, top->handle, (HMENU)STATUSBAR_ID, NULL, NULL);
+ SendMessage(statusBar, SB_SETPARTS, 2, (LPARAM)statusBarWidth);
+ SendMessage(statusBar, SB_SETTEXT, 0, (LPARAM)"Editing: Page 1");
+ SendMessage(statusBar, SB_SETTEXT, 1, (LPARAM)"Don't Panic");
+
+ msg2 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
+ msg2->handle = statusBar;
+ msg2->type = WIN_STATUS;
+ msg2->position = 0;
+ message2 = (Widget)msg2;
+
+ msg3 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
+ msg3->handle = statusBar;
+ msg3->type = WIN_STATUS;
+ msg3->position = 1;
+ message3 = (Widget)msg3;
+}
+
+typedef struct { int c; RGBQUAD color; } xpm_color;
+
+static HBITMAP create_bitmap_from_xpm(char **xpm)
+{
+ int width, height, ncolors, nchar;
+ int i, j, k;
+ BITMAPINFO *bmi;
+ HBITMAP hBitmap = NULL;
+ xpm_color *colors;
+ BYTE *data;
+ HDC hdc;
+
+ if (sscanf(xpm[0], "%d %d %d %d", &width, &height, &ncolors, &nchar) != 4)
+ return NULL;
+ if (nchar != 1) {
+ W32DEBUG(("(XPM) Unsupported number of char per data\n"));
+ return NULL;
+ }
+ colors = (xpm_color*)malloc(sizeof(xpm_color)*ncolors);
+ for (i=0; i<ncolors; i++) {
+ char *str = xpm[i+1];
+ char snum[5];
+ colors[i].c = str[0]; str++;
+ for (; *str!='c'; str++); str+=2;
+ if (*str == '#') {
+ str++;
+ strncpy(snum, str, 4); snum[4] = 0; str+=4;
+ colors[i].color.rgbRed = 0xff&(strtol(snum, NULL, 16)>>8);
+ strncpy(snum, str, 4); snum[4] = 0; str+=4;
+ colors[i].color.rgbGreen = 0xff&(strtol(snum, NULL, 16)>>8);
+ strncpy(snum, str, 4); snum[4] = 0; str+=4;
+ colors[i].color.rgbBlue = 0xff&(strtol(snum, NULL, 16)>>8);
+ } else {
+ COLORREF cr = WinNamedColor(str);
+ colors[i].color.rgbRed = GetRValue(cr);
+ colors[i].color.rgbGreen = GetGValue(cr);
+ colors[i].color.rgbBlue = GetBValue(cr);
+ }
+ }
+
+ data = (BYTE*)malloc(sizeof(BYTE)*width*height);
+ for (j=k=0; j<height; j++) {
+ for (i=0; i<width; i++, k++) {
+ char pix = xpm[j+ncolors+1][i];
+ int idx;
+ for (idx=0; idx<ncolors; idx++)
+ if (pix == colors[idx].c) break;
+ data[k] = idx;
+ }
+ }
+
+ bmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+(ncolors-1)*sizeof(RGBQUAD));
+ ZeroMemory(bmi, sizeof(BITMAPINFO));
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biWidth = width;
+ bmi->bmiHeader.biHeight = -height;
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biBitCount = 8;
+ bmi->bmiHeader.biCompression = BI_RGB;
+ bmi->bmiHeader.biClrUsed = ncolors;
+ for (i=0; i<ncolors; i++)
+ memcpy(bmi->bmiColors+i, &colors[i].color, sizeof(RGBQUAD));
+ hdc = GetDC(NULL);
+ hBitmap = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, data, bmi, DIB_RGB_COLORS);
+
+ ReleaseDC(NULL, hdc);
+ free(bmi);
+ free(colors);
+
+ return hBitmap;
+}
+
+static void create_toolbar()
+{
+ TBBUTTON *buttons;
+ TBADDBITMAP bitmap;
+ int i;
+
+ toolBar = create_widget(CreateWindow(TOOLBARCLASSNAME, NULL, WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|TBSTYLE_WRAPABLE, 0, 0, 0, 0,
+ top->handle, (HMENU)TOOLBAR_ID, NULL, NULL), "ToolBar");
+ SendMessage(toolBar->handle, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+ SendMessage(toolBar->handle, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20));
+
+ buttons = (TBBUTTON*)malloc(sizeof(TBBUTTON) * toolbuttons);
+ for (i=0; i<toolbuttons; i++) {
+ ToolItem item;
+
+ buttons[i].iBitmap = i;
+ buttons[i].idCommand = menuID++;
+ buttons[i].fsState = TBSTATE_ENABLED;
+ buttons[i].fsStyle = TBSTYLE_BUTTON;
+ buttons[i].iString = 0;
+ bitmap.hInst = NULL;
+ bitmap.nID = (INT_PTR)create_bitmap_from_xpm(ToolBar[i].icon_data);
+ SendMessage(toolBar->handle, TB_ADDBITMAP, 1, (LPARAM)&bitmap);
+
+ item = (ToolItem)malloc(sizeof(struct __WinToolItem));
+ ZeroMemory(item, sizeof(struct __WinToolItem));
+ item->type = WIN_TOOLITEM;
+ item->toolbar = toolBar;
+ item->ID = buttons[i].idCommand;
+ item->name = strdup(ToolBar[i].name);
+ buttons[i].dwData = (DWORD)item;
+
+ menuwidgets[item->ID-100] = (Widget)item;
+ XtAddCallback((Widget)item, XtNselect, (XtCallbackProc)ToolBar[i].func, ToolBar[i].passeddata);
+
+ /*
+ if (ToolBar[i].func == changetool ||
+ ToolBar[i].func == exec_or_changetool)
+ buttons[i].fsStyle |= TBSTYLE_CHECK;
+ */
+ }
+ SendMessage(toolBar->handle, TB_ADDBUTTONS, toolbuttons, (LPARAM)buttons);
+ free(buttons);
+}
+
+static void register_win32_classes()
+{
+ WNDCLASS wndClass;
+
+ /* Top-level window */
+ ZeroMemory(&wndClass, sizeof(wndClass));
+ wndClass.lpfnWndProc = XcTopWindowProc;
+ wndClass.lpszClassName = "XcTopLevel";
+ wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), "xcircuit");
+ RegisterClass(&wndClass);
+
+ /* Main area */
+ ZeroMemory(&wndClass, sizeof(wndClass));
+ wndClass.lpfnWndProc = XcWidgetProc;
+ wndClass.lpszClassName = "XcWidget";
+ wndClass.cbWndExtra = sizeof(void*);
+ RegisterClass(&wndClass);
+
+ /* Scroll bar */
+ ZeroMemory(&wndClass, sizeof(wndClass));
+ wndClass.lpfnWndProc = XcWidgetProc;
+ wndClass.lpszClassName = "XcScrollBar";
+ wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndClass.cbWndExtra = sizeof(void*);
+ RegisterClass(&wndClass);
+
+ /* Help widget */
+ ZeroMemory(&wndClass, sizeof(wndClass));
+ wndClass.lpfnWndProc = XcHelppixProc;
+ wndClass.lpszClassName = "XcHelp";
+ RegisterClass(&wndClass);
+
+ /* Popup */
+ /*
+ ZeroMemory(&wndClass, sizeof(wndClass));
+ wndClass.lpfnWndProc = XcPopupProc;
+ wndClass.lpszClassName = "XcPopup";
+ wndClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
+ wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ RegisterClass(&wndClass);
+ */
+}
+
+XCWindowData* GUI_init(int argc, char *argv[])
+{
+ int i;
+ XGCValues values;
+ Arg wargs[2];
+ RECT clientRect = { 0, 0, 0, 0 };
+ XCWindowData *newwin;
+
+#if 0 && defined(USE_WIN32_COM)
+ for (i=0; i<argc; i++)
+ if (strcmp(argv[i], "-register") == 0)
+ COM_register(1);
+ else if (strcmp(argv[i], "-unregister") == 0)
+ COM_register(0);
+#endif
+
+ if (dpy == NULL) {
+ register_win32_classes();
+
+ appdata.globalcolor = WinNamedColor("Orange2");
+ appdata.localcolor = WinNamedColor("Red");
+ appdata.infocolor = WinNamedColor("SeaGreen");
+ appdata.ratsnestcolor = WinNamedColor("Tan4");
+ appdata.bboxpix = WinNamedColor("greenyellow");
+ appdata.clipcolor = WinNamedColor("powderblue");
+ appdata.fg = WinNamedColor("Black");
+ appdata.bg = WinNamedColor("White");
+ appdata.gridpix = WinNamedColor("Gray95");
+ appdata.snappix = WinNamedColor("Red");
+ appdata.selectpix = WinNamedColor("Gold3");
+ appdata.querypix = WinNamedColor("Turquoise");
+ appdata.filterpix = WinNamedColor("SteelBlue3");
+ appdata.axespix = WinNamedColor("Antique White");
+ appdata.buttonpix = WinNamedColor("Gray85");
+ appdata.auxpix = WinNamedColor("Green3");
+ appdata.barpix = WinNamedColor("Tan");
+ appdata.parampix = WinNamedColor("Plum3");
+ appdata.fg2 = WinNamedColor("White");
+ appdata.bg2 = WinNamedColor("DarkSlateGray");
+ appdata.gridpix2 = WinNamedColor("Gray40");
+ appdata.snappix2 = WinNamedColor("Red");
+ appdata.selectpix2 = WinNamedColor("Gold");
+ appdata.querypix2 = WinNamedColor("Turquoise");
+ appdata.filterpix2 = WinNamedColor("SteelBlue1");
+ appdata.axespix2 = WinNamedColor("NavajoWhite4");
+ appdata.buttonpix2 = WinNamedColor("Gray50");
+ appdata.auxpix2 = WinNamedColor("Green");
+ appdata.barpix2 = WinNamedColor("Tan");
+ appdata.parampix2 = WinNamedColor("Plum3");
+ appdata.width = 950;
+ appdata.height = 760;
+ appdata.timeout = 10;
+ appdata.xcfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
+ appdata.helpfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
+ appdata.filefont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
+ appdata.textfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
+ appdata.titlefont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
+
+ for (i=0; i<STIPPLES; i++) {
+ STIPPLE[i] = WinCreateBitmapFromData(NULL, STIPDATA[i], 4, 4);
+ }
+
+ number_colors = 0;
+ colorlist = (colorindex *)malloc(sizeof(colorindex));
+ appcolors = (int *) malloc(NUMBER_OF_COLORS * sizeof(int));
+ }
+
+ clientRect.right = appdata.width+SBARSIZE;
+ clientRect.bottom = appdata.height+SBARSIZE;
+ AdjustWindowRect(&clientRect, WS_TILEDWINDOW, TRUE);
+ OffsetRect(&clientRect, -clientRect.left, -clientRect.top);
+
+ top = create_widget(CreateWindow("XcTopLevel", "XCircuit", WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, clientRect.right, clientRect.bottom,
+ NULL, create_menus(), NULL, NULL), "XCircuit");
+ topwin = top->handle;
+
+ dpy = XtDisplay(top);
+ newwin = create_new_window();
+
+ newwin->scrollbarv = create_widget(CreateWindow("XcScrollBar", "SBV", WS_VISIBLE|WS_CHILD,
+ 0, 0, SBARSIZE, appdata.height-SBARSIZE, top->handle, 0, NULL, NULL), "SBV");
+ newwin->scrollbarh = create_widget(CreateWindow("XcScrollBar", "SBH", WS_VISIBLE|WS_CHILD,
+ SBARSIZE, appdata.height-SBARSIZE, appdata.width-SBARSIZE, SBARSIZE, top->handle, 0, NULL, NULL), "SBH");
+ newwin->area = create_widget(CreateWindow("XcWidget", "Area", WS_VISIBLE|WS_CHILD,
+ SBARSIZE, 0, appdata.width, appdata.height, top->handle, 0, NULL, NULL), "Area");
+ newwin->window = newwin->area->handle;
+ corner = CreateWindow("BUTTON", "", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_FLAT, 0, appdata.height-SBARSIZE, SBARSIZE, SBARSIZE, top->handle, NULL, NULL, NULL);
+
+ create_statusbar();
+ create_toolbar();
+
+ XtAddCallback(newwin->area, XtNexpose, (XtCallbackProc)drawarea, NULL);
+ XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
+
+ XtAddCallback(newwin->area, XtNselect, (XtCallbackProc)buttonhandler, NULL);
+ XtAddCallback(newwin->area, XtNrelease, (XtCallbackProc)buttonhandler, NULL);
+ XtAddCallback(newwin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
+ XtAddCallback(newwin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
+
+ XtAddEventHandler(newwin->area, Button1MotionMask | Button2MotionMask,
+ False, (XtEventHandler)xlib_drag, NULL);
+
+ XtAddEventHandler(newwin->scrollbarh, ButtonMotionMask, False,
+ (XtEventHandler)panhbar, NULL);
+ XtAddEventHandler(newwin->scrollbarv, ButtonMotionMask, False,
+ (XtEventHandler)panvbar, NULL);
+
+ XtAddCallback(newwin->scrollbarh, XtNrelease, (XtCallbackProc)endhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNrelease, (XtCallbackProc)endvbar, NULL);
+
+ XtAddCallback(newwin->scrollbarh, XtNexpose, (XtCallbackProc)drawhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNexpose, (XtCallbackProc)drawvbar, NULL);
+ XtAddCallback(newwin->scrollbarh, XtNresize, (XtCallbackProc)drawhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNresize, (XtCallbackProc)drawvbar, NULL);
+
+ values.foreground = RGB(0, 0, 0);
+ values.background = RGB(255, 255, 255);
+ values.font = appdata.xcfont->fid;
+
+ newwin->gc = XCreateGC(dpy, newwin->window,
+ GCForeground | GCBackground | GCFont, &values);
+
+ XtSetArg(wargs[0], XtNwidth, &newwin->width);
+ XtSetArg(wargs[1], XtNheight, &newwin->height);
+ XtGetValues(newwin->area, wargs, 2);
+
+ SendMessage(((ToolItem)WireToolButton)->toolbar->handle, TB_CHECKBUTTON, ((ToolItem)WireToolButton)->ID, MAKELONG(TRUE, 0));
+
+#ifdef USE_WIN32_COM
+ if (!COM_initialize())
+ printf("Failed to initialize COM interface\n");
+#endif
+
+ return newwin;
+}
+
+void WinAddEventHandler(Widget win, int event, void(*proc)(), void *data)
+{
+ WinEventHandler *h = win->handlers;
+
+ if (win->type != WIN_WIDGET) {
+ W32DEBUG(("Can't add event handler to non widget\n"));
+ return;
+ }
+
+ while (h != NULL) {
+ if (h->proc == proc && h->data == data) {
+ h->action |= event;
+ break;
+ } else
+ h = h->next;
+ }
+
+ if (h == NULL) {
+ h = (WinEventHandler*)malloc(sizeof(WinEventHandler));
+ h->action = event;
+ h->proc = proc;
+ h->data = data;
+ h->next = win->handlers;
+ win->handlers = h;
+ }
+
+ update_event_mask(win);
+}
+
+void WinRemoveEventHandler(Widget win, int event, void(*proc)(), void *data)
+{
+ WinEventHandler *h, *prev = NULL;
+
+ if (win->type != WIN_WIDGET) {
+ W32DEBUG(("Can't remove event handler from non widget\n"));
+ return;
+ }
+
+ h = win->handlers;
+ for (; h!=NULL;)
+ if ((h->action & event) && h->proc == proc && h->data == data) {
+ h->action &= ~event;
+ if (h->action == 0) {
+ WinEventHandler *old_h = h;
+ if (prev == NULL)
+ win->handlers = h = h->next;
+ else
+ prev->next = h = h->next;
+ free(old_h);
+ }
+ } else {
+ prev = h;
+ h = h->next;
+ }
+ update_event_mask(win);
+}
+
+void WinAddCallback(Widget win, int event, void(*proc)(), void *data)
+{
+ WinCallback *cb, **root, *prev = NULL;
+
+ if (win == NULL)
+ return;
+
+ switch (win->type) {
+ case WIN_MENUITEM:
+ if (TOMENUITEM(win)->popup != NULL) {
+ Wprintf("Trying to add a callback to a popup menu");
+ return;
+ }
+ root = &((MenuItem)win)->callbacks;
+ break;
+ case WIN_TOOLITEM:
+ root = &((ToolItem)win)->callbacks;
+ break;
+ default:
+ root = &win->callbacks;
+ break;
+ }
+
+ cb = *root;
+ while (cb) {
+ prev = cb;
+ cb = cb->next;
+ }
+
+ cb = (WinCallback*)malloc(sizeof(WinCallback));
+ cb->action = event;
+ cb->proc = proc;
+ cb->data = data;
+ cb->next = NULL;
+
+ if (prev)
+ prev->next = cb;
+ else
+ *root = cb;
+}
+
+int WinFindCallback(Widget win, int event, void(**proc)(), void **data)
+{
+ WinCallback *cb;
+
+ if (win == NULL)
+ return 0;
+
+ switch (win->type) {
+ case WIN_MENUITEM:
+ cb = TOMENUITEM(win)->callbacks;
+ break;
+ case WIN_TOOLITEM:
+ cb = TOTOOLITEM(win)->callbacks;
+ break;
+ default:
+ cb = win->callbacks;
+ break;
+ }
+
+ while (cb) {
+ if (cb->action == event) {
+ if (proc == NULL || *proc == NULL || *proc == cb->proc) {
+ if (proc != NULL) *proc = cb->proc;
+ if (data != NULL) *data = cb->data;
+ return 1;
+ }
+ }
+ cb = cb->next;
+ }
+
+ return 0;
+}
+
+void WinRemoveCallback(Widget win, int event, void(*proc)(), void *data)
+{
+ WinCallback *cb;
+ WinCallback *prev = NULL, **root;
+
+ if (win == NULL)
+ return;
+
+ switch (win->type) {
+ case WIN_MENUITEM:
+ cb = ((MenuItem)win)->callbacks;
+ root = &((MenuItem)win)->callbacks;
+ break;
+ case WIN_TOOLITEM:
+ cb = ((ToolItem)win)->callbacks;
+ root = &((ToolItem)win)->callbacks;
+ break;
+ default:
+ cb = win->callbacks;
+ root = &win->callbacks;
+ break;
+ }
+ while (cb != NULL) {
+ if (cb->action == event && (proc == NULL || (cb->proc == proc && cb->data == data))) {
+ WinCallback *old_cb = cb;
+ if (prev == NULL)
+ *root = cb = cb->next;
+ else
+ prev->next = cb = cb->next;
+ free(old_cb);
+ } else {
+ prev = cb;
+ cb = cb->next;
+ }
+ }
+}
+
+void WinRemoveAllCallbacks(Widget win, int event)
+{
+ if (win == NULL)
+ return;
+
+ WinRemoveCallback(win, event, NULL, NULL);
+}
+
+static Arg* look_arg(Arg *args, int type, int n)
+{
+ int i;
+ for (i=0; i<n; i++)
+ if (args[i].type == type)
+ return &args[i];
+ return NULL;
+}
+
+static void get_window_location(Arg *args, int n, POINT *pt, SIZE *sz)
+{
+ int i;
+ for (i=0; i<n; i++)
+ switch (args[i].type) {
+ case XtNx: if (pt) pt->x = (int)args[i].data; break;
+ case XtNy: if (pt) pt->y = (int)args[i].data; break;
+ case XtNwidth: if (sz) sz->cx = (int)args[i].data; break;
+ case XtNheight: if (sz) sz->cy = (int)args[i].data; break;
+ }
+}
+
+Widget WinCreateWidget(const char *name, int cls, Widget parent, Arg *args, int n, int show)
+{
+ int i;
+ Widget win;
+
+ switch (cls) {
+ case XwcascadeWidgetClass:
+ {
+ MENUITEMINFO mi_info;
+ MenuItem item;
+ Menu popup = create_win_menu(CreatePopupMenu());
+ Arg *a;
+ int pos = -1;
+
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
+ mi_info.hSubMenu = popup->handle;
+ mi_info.dwTypeData = (char*)name;
+ if (IS_MENUITEM(parent))
+ parent = (Widget)TOMENUITEM(parent)->popup;
+ if ((a = look_arg(args, XtNattachTo, n)) != NULL) {
+ Widget after = WinNameToWindow(parent, (char*)a->data);
+ if (after != NULL)
+ pos = TOMENUITEM(after)->position + 1;
+ }
+ item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
+ item->name = strdup(name);
+ DrawMenuBar(topwin);
+ return (Widget)item;
+ }
+ case XwmenubuttonWidgetClass:
+ {
+ MENUITEMINFO mi_info;
+ Arg *a;
+ MenuItem item;
+ int pos = -1;
+
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ if ((a=look_arg(args, XtNrectColor, n)) != NULL) {
+ HBITMAP hBitmap = create_color_icon((int)a->data, MENUICON_WIDTH, MENUICON_HEIGHT);
+ mi_info.fMask = MIIM_BITMAP | MIIM_STRING /*| MIIM_FTYPE*/;
+ /*mi_info.fType = MFT_OWNERDRAW*/;
+ mi_info.hbmpItem = hBitmap;
+ mi_info.dwTypeData = color_string((int)a->data);
+ mi_info.dwItemData = (int)a->data;
+ } else {
+ mi_info.fMask = MIIM_STRING;
+ mi_info.dwTypeData = (char*)name;
+ }
+ if (IS_MENUITEM(parent))
+ parent = (Widget)TOMENUITEM(parent)->popup;
+ if ((a = look_arg(args, XtNattachTo, n)) != NULL) {
+ Widget after = WinNameToWindow(parent, (char*)a->data);
+ if (after != NULL)
+ pos = TOMENUITEM(after)->position + 1;
+ }
+ item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
+ item->name = strdup(name);
+ DrawMenuBar(topwin);
+ return (Widget)item;
+ }
+ break;
+ /*
+ case XwstaticTextWidgetClass:
+ {
+ POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
+
+ get_window_location(args, n, &pt, NULL);
+ win = create_widget(CreateWindow("STATIC", "", WS_CHILD|WS_VISIBLE, pt.x, pt.y,
+ CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
+ win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcStaticProc);
+ WinSetValues(win, args, n);
+ }
+ break;
+ case XwtextEditWidgetClass:
+ {
+ POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
+ SIZE sz = {CW_USEDEFAULT, CW_USEDEFAULT};
+
+ get_window_location(args, n, &pt, &sz);
+ win = create_widget(CreateWindow("EDIT", "", WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, pt.x, pt.y, sz.cx, sz.cy,
+ parent->handle, NULL, NULL, NULL), (char*)name);
+ //win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcEditProc);
+ }
+ break;
+ case XwpushButtonWidgetClass:
+ case XwmenuButtonWidgetClass:
+ {
+ POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
+
+ get_window_location(args, n, &pt, NULL);
+ win = create_widget(CreateWindow("BUTTON", name, BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE, pt.x, pt.y,
+ CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
+ win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcButtonProc);
+ WinSetValues(win, args, n);
+ }
+ break;
+ case XwtoggleWidgetClass:
+ {
+ POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
+
+ get_window_location(args, n, &pt, NULL);
+ win = create_widget(CreateWindow("BUTTON", name, BS_CHECKBOX|WS_CHILD|WS_VISIBLE, pt.x, pt.y,
+ CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
+ win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcToggleProc);
+ WinSetValues(win, args, n);
+ }
+ break;
+ case XwbulletinWidgetClass:
+ win = parent;
+ break;
+ */
+ default:
+ W32DEBUG(("Should create widget: %02x, %s\n", cls, name));
+ win = NULL;
+ break;
+ }
+
+ if (show)
+ ShowWindow(win->handle, SW_SHOW);
+ else
+ ShowWindow(win->handle, SW_HIDE);
+
+ return win;
+}
+
+Widget WinCreatePopup(const char *name, Arg *args, int n)
+{
+ HWND hwnd;
+
+ hwnd = CreateWindow("XcPopup", name, WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
+ 300, 200, NULL, NULL, NULL, NULL);
+ return create_widget(hwnd, (char*)name);
+}
+
+void WinPopup(Widget popup)
+{
+ ShowWindow(popup->handle, SW_SHOWNORMAL);
+}
+
+char* WinGetText(Widget win)
+{
+ static char buffer[1024];
+
+ GetWindowText(win->handle, buffer, 1024);
+ return buffer;
+}
+
+void WinClearText(Widget win)
+{
+ SetWindowText(win->handle, "");
+}
+
+int WinNamedColor(const char *cname)
+{
+ int i;
+
+ for (i=0; X11Colors[i].name; i++) {
+ if (_stricmp(X11Colors[i].name, cname) == 0)
+ return RGB(X11Colors[i].red, X11Colors[i].green, X11Colors[i].blue);
+ }
+ W32DEBUG(("Unknown color: %s\n", cname));
+ return -1;
+}
+
+int WinLookupColor(const char *cname, XColor *color)
+{
+ int cval = WinNamedColor(cname);
+ if (cval == -1)
+ return 0;
+ else {
+ color->pixel = cval;
+ WinQueryColors(color, 1);
+ return 1;
+ }
+}
+
+char *WinColorName(int c)
+{
+ int red = GetRValue(c), green = GetGValue(c), blue = GetBValue(c);
+ int i;
+
+ for (i=0; X11Colors[i].name; i++)
+ if (red == X11Colors[i].red && green == X11Colors[i].green && blue == X11Colors[i].blue)
+ return X11Colors[i].name;
+ return NULL;
+}
+
+HWND WinWindow(Widget w)
+{
+ return (w ? w->handle : NULL);
+}
+
+void WinManageChild(Widget w)
+{
+ if (w != NULL)
+ ShowWindow(w->handle, SW_SHOW);
+}
+
+void WinUnmanageChild(Widget w)
+{
+ if (w != NULL)
+ ShowWindow(w->handle, SW_HIDE);
+}
+
+void WinDebug(char *c)
+{
+ W32DEBUG(("%s", c));
+}
+
+void WinLookupString(XKeyEvent *event, KeySym *key)
+{
+ XKeyEvent *kevent = (XKeyEvent*)event;
+ int vk = kevent->keycode & 0xff;
+
+ if (vk == 0)
+ *key = 0;
+ else {
+ W32DEBUG(("Translating key event: %d\n", vk));
+ *key = kevent->keycode;
+ }
+}
+
+void WinPostPopup(Widget _menu, Widget _button, int dx, int dy)
+{
+ Menu menu = (Menu)_menu;
+ ToolItem button = (ToolItem)_button;
+ RECT bRect = { 0, 0, 0, 0 };
+ POINT pt;
+
+ SendMessage(button->toolbar->handle, TB_GETRECT, button->ID, (LPARAM)&bRect);
+ pt.x = bRect.left;
+ pt.y = bRect.bottom;
+ ClientToScreen(button->toolbar->handle, &pt);
+ SendMessage(button->toolbar->handle, TB_CHECKBUTTON, button->ID, MAKELONG(TRUE, 0));
+ TrackPopupMenu(menu->handle, TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y, 0, top->handle, NULL);
+ SendMessage(button->toolbar->handle, TB_CHECKBUTTON, button->ID, MAKELONG(FALSE, 0));
+}
+
+void overdrawpixmap(Widget button)
+{
+ MenuItem mitem = (MenuItem)button;
+ ToolItem titem = NULL;
+ int idx;
+
+ if (button == NULL) return;
+ idx = mitem->toolbar_idx;
+
+ if (mitem->parentMenu == ((MenuItem)ColorInheritColorButton)->parentMenu)
+ titem = (ToolItem)ColorsToolButton;
+ else if (mitem->parentMenu == ((MenuItem)FillBlackButton)->parentMenu)
+ titem = (ToolItem)FillsToolButton;
+ else
+ return;
+
+ if (idx == 0) {
+ if (mitem == (MenuItem)ColorInheritColorButton) {
+ idx = ((ToolItem)ColorsToolButton)->ID-((ToolItem)PanToolButton)->ID;
+ } else if (mitem == (MenuItem)FillWhiteButton) {
+ idx = ((ToolItem)FillsToolButton)->ID-((ToolItem)PanToolButton)->ID;
+ } else {
+ HBITMAP hBitmap = NULL;
+ TBADDBITMAP tb;
+ if (titem == (ToolItem)ColorsToolButton)
+ hBitmap = create_color_icon(mitem->menudata, 20, 20);
+ else {
+ if (mitem->menudata == (OPAQUE | FILLED | FILLSOLID))
+ hBitmap = create_color_icon(RGB(0, 0, 0), 20, 20);
+ else if (mitem != (MenuItem)FillOpaqueButton && mitem != (MenuItem)FillTransparentButton)
+ hBitmap = create_stipple_icon((mitem->menudata & FILLSOLID) >> 5, 20, 20);
+ }
+ if (hBitmap != NULL) {
+ tb.hInst = NULL;
+ tb.nID = (INT_PTR)hBitmap;
+ idx = mitem->toolbar_idx = SendMessage(titem->toolbar->handle, TB_ADDBITMAP, 1, (LPARAM)&tb);
+ }
+ }
+ }
+
+ W32DEBUG(("%s: %d\n", titem->name, idx));
+ if (idx > 0) {
+ SendMessage(titem->toolbar->handle, TB_CHANGEBITMAP, titem->ID, MAKELPARAM(idx, 0));
+ }
+}
+
+void starthelp(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_HELPDLG), areawin->window, HelpDlgProc, (LPARAM)NULL);
+}
+
+/*
+static void get_text_size(HWND hwnd, HFONT hfont, SIZE *sz)
+{
+ HDC hdc = GetDC(hwnd);
+ char str[64];
+ int n;
+
+ SelectObject(hdc, hfont);
+ n = GetWindowText(hwnd, str, 64);
+ GetTextExtentPoint32(hdc, str, n, sz);
+ ReleaseDC(hwnd, hdc);
+}
+
+LRESULT CALLBACK XcStaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (msg) {
+ case WM_SETFONT:
+ {
+ SIZE sz;
+ get_text_size(hwnd, (HFONT)wParam, &sz);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx, sz.cy, SWP_NOMOVE);
+ }
+ break;
+ }
+
+ return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK XcEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (msg) {
+ case WM_KEYDOWN:
+ if (wParam == VK_RETURN) {
+ execute_callback(XtNexecute, w, NULL);
+ return 0;
+ }
+ break;
+ }
+
+ return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK XcButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (msg) {
+ case WM_SETFONT:
+ {
+ SIZE sz;
+ get_text_size(hwnd, (HFONT)wParam, &sz);
+ printf("%d %d\n", sz.cx, sz.cy);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
+ }
+ break;
+ case WM_SETTEXT:
+ {
+ LRESULT result = CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+ SIZE sz;
+ get_text_size(hwnd, (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0), &sz);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
+ return result;
+ }
+ case WM_LBUTTONDOWN:
+ execute_callback(XtNselect, w, NULL);
+ break;
+ }
+
+ return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK XcToggleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (msg) {
+ case WM_SETFONT:
+ {
+ SIZE sz;
+ get_text_size(hwnd, (HFONT)wParam, &sz);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
+ }
+ break;
+ case WM_LBUTTONUP:
+ {
+ LRESULT result = CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+ if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED)
+ execute_callback(XtNselect, w, NULL);
+ else
+ execute_callback(XtNrelease, w, NULL);
+ }
+ break;
+ }
+
+ return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK XcPopupProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return DefDlgProc(hwnd, msg, wParam, lParam);
+}
+*/
+
+static void change_char(char *str, char cfrom, char cto)
+{
+ char *c = str;
+ for (; *c; c++)
+ if (*c == cfrom)
+ *c = cto;
+}
+
+LRESULT CALLBACK OutputDlgEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget win = get_widget (hwnd);
+
+ switch (msg) {
+ case WM_GETDLGCODE:
+ if (lParam) {
+ MSG *message = (MSG*)lParam;
+ if (message->message == WM_KEYDOWN && message->wParam == VK_RETURN)
+ return DLGC_WANTMESSAGE;
+ }
+ break;
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_RETURN:
+ execute_callback(XtNexecute, win, NULL);
+ break;
+ }
+ break;
+ }
+ return CallWindowProc(win->wndproc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK OutputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ Widget popup = get_widget(hwnd);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ RECT r, pr;
+ Widget win;
+ Pagedata *curpage;
+ Widget *entertext;
+ int i;
+ void (*function[MAXPROPS])() = { setfilename, setpagelabel, setfloat, setscalex, setscaley, setorient, setpmode };
+ void (*update[MAXPROPS])() = { updatename, NULL, updatetext, updatetext, updatetext, updatetext, NULL };
+ char statics[MAXPROPS][50], edit[MAXPROPS][75], request[150];
+ void *data[MAXPROPS];
+ struct {int edit; int apply; int label;} ID[MAXPROPS] = {
+ { IDC_FILENAME, IDC_APPLY1, IDC_STATIC1 },
+ { IDC_PAGELABEL, IDC_APPLY2, IDC_STATIC2 },
+ { IDC_SCALE, IDC_APPLY3, IDC_STATIC3 },
+ { IDC_WIDTH, IDC_APPLY4, IDC_STATIC4 },
+ { IDC_HEIGHT, IDC_APPLY5, IDC_STATIC5 },
+ { IDC_ORIENTATION, -1, IDC_STATIC6 },
+ { IDC_MODE, -1, IDC_STATIC7 } };
+ struct stat statbuf;
+
+ GetWindowRect(GetParent(hwnd), &pr);
+ GetWindowRect(hwnd, &r);
+ SetWindowPos(hwnd, HWND_TOP, pr.left+((pr.right-pr.left)-(r.right-r.left))/2,
+ pr.top+((pr.bottom-pr.top)-(r.bottom-r.top))/2, 0, 0, SWP_NOSIZE);
+
+ SendDlgItemMessage(hwnd, IDC_ORIENTATION, CB_ADDSTRING, 0, (LPARAM)"Landscape");
+ SendDlgItemMessage(hwnd, IDC_ORIENTATION, CB_ADDSTRING, 0, (LPARAM)"Portrait");
+ SendDlgItemMessage(hwnd, IDC_MODE, CB_ADDSTRING, 0, (LPARAM)"Embedded (EPS)");
+ SendDlgItemMessage(hwnd, IDC_MODE, CB_ADDSTRING, 0, (LPARAM)"Full page");
+
+ curpage = xobjs.pagelist[areawin->page];
+ entertext = (Widget*)malloc(sizeof(Widget)*MAXPROPS);
+ memset(okstruct, 0, sizeof(propstruct)*MAXPROPS);
+
+ sprintf(edit[0], "%s", curpage->filename);
+ sprintf(edit[1], "%s", topobject->name);
+ calcbbox(areawin->topinstance);
+ if (curpage->pmode & 2) autoscale(areawin->page);
+ writescalevalues(edit[2], edit[3], edit[4]);
+ sprintf(edit[5], "%s", (curpage->orient == 0) ? "Portrait" : "Landscape");
+ sprintf(edit[6], "%s", (curpage->pmode & 1) ? "Full page" : "Embedded (EPS)");
+ data[0] = &(curpage->filename);
+ data[1] = topobject->name;
+ data[2] = data[3] = data[4] = &(curpage->outscale);
+ data[5] = &(curpage->orient);
+ data[6] = &(curpage->pmode);
+
+ popup = create_widget(hwnd, "outputpopup");
+ popup->bufhdc = (HDC)entertext;
+ create_widget(GetDlgItem(hwnd, IDOK), "Write File");
+ create_widget(GetDlgItem(hwnd, IDCANCEL), "Close");
+
+ sprintf(request, "PostScript output properties (Page %d):", areawin->page + 1);
+ sprintf(statics[0], "Filename:");
+ sprintf(statics[1], "Page label:");
+ sprintf(statics[2], "Scale:");
+ if (curpage->coordstyle == CM) {
+ sprintf(statics[3], "X Size (cm):");
+ sprintf(statics[4], "Y Size (cm):");
+ } else {
+ sprintf(statics[3], "X Size (in):");
+ sprintf(statics[4], "Y Size (in):");
+ }
+ sprintf(statics[5], "Orientation:");
+ sprintf(statics[6], "Mode:");
+ SetDlgItemText(hwnd, IDC_PSINFO, request);
+
+ strcpy(request, edit[0]);
+ if (strstr(request, ".") == NULL)
+ strcat(request, ".ps");
+ if (stat(request, &statbuf) == 0) {
+ SetWindowText(GetDlgItem(hwnd, IDOK), "Overwrite File");
+ Wprintf(" Warning: File exists");
+ } else {
+ if (errno == ENOTDIR)
+ Wprintf("Error: Incorrect pathname");
+ else if (errno == EACCES)
+ Wprintf("Error: Path not readable");
+ else
+ Wprintf(" ");
+ }
+
+ for (i=0; i<MAXPROPS; i++) {
+ SetDlgItemText(hwnd, ID[i].label, statics[i]);
+ if (i<5) {
+ okstruct[i].textw = entertext[i] = create_widget(GetDlgItem(hwnd, ID[i].edit), "Edit");
+ okstruct[i].buttonw = create_widget(GetDlgItem(hwnd, ID[i].apply), "Apply");
+ okstruct[i].setvalue = function[i];
+ okstruct[i].dataptr = data[i];
+ SetWindowText(okstruct[i].textw->handle, edit[i]);
+
+ WinAddCallback(okstruct[i].buttonw, XtNselect, getproptext, &okstruct[i]);
+ WinAddCallback(okstruct[i].textw, XtNexecute, getproptext, &okstruct[i]);
+ if (update[i] != NULL) {
+ WinAddCallback(okstruct[i].buttonw, XtNselect, update[i], entertext);
+ WinAddCallback(okstruct[i].textw, XtNexecute, update[i], entertext);
+ }
+
+ okstruct[i].textw->wndproc = (WNDPROC)SetWindowLong(okstruct[i].textw->handle,
+ GWL_WNDPROC, (LONG)OutputDlgEditProc);
+ } else {
+ entertext[i] = create_widget(GetDlgItem(hwnd, ID[i].edit), "Toggle");
+ SendMessage(entertext[i]->handle, CB_SELECTSTRING, -1, (LPARAM)edit[i]);
+ WinAddCallback(entertext[i], XtNselect, function[i], data[i]);
+ if (update[i] != NULL)
+ WinAddCallback(entertext[i], XtNselect, update[i], entertext);
+ }
+ }
+
+ sprintf(request, "%d Pages", pagelinks(areawin->page));
+ win = create_widget(GetDlgItem(hwnd, IDC_PAGENUM), "LToggle");
+ SetWindowText(win->handle, request);
+ CheckDlgButton(hwnd, IDC_PAGENUM, BST_CHECKED);
+ WinAddCallback(win, XtNrelease, linkset, &okstruct[0]);
+
+ win = create_widget(GetDlgItem(hwnd, IDC_AUTOFIT), "Auto-fit");
+ SendMessage(win->handle, BM_SETCHECK, (curpage->pmode & 2 ? BST_CHECKED : BST_UNCHECKED), 0);
+ WinAddCallback(win, XtNselect, autoset, entertext);
+ WinAddCallback(win, XtNrelease, autostop, NULL);
+
+ if (curpage->coordstyle == CM) {
+ sprintf(request, "%3.2f x %3.2f cm",
+ (float)curpage->pagesize.x / IN_CM_CONVERT,
+ (float)curpage->pagesize.y / IN_CM_CONVERT);
+ } else {
+ sprintf(request, "%3.2f x %3.2f in",
+ (float)curpage->pagesize.x / 72.0,
+ (float)curpage->pagesize.y / 72.0);
+ }
+ fpokstruct.textw = create_widget(GetDlgItem(hwnd, IDC_FPEDIT), "fpedit");
+ SetWindowText(fpokstruct.textw->handle, request);
+ fpokstruct.buttonw = create_widget(GetDlgItem(hwnd, IDC_APPLY6), "fpokay");
+ fpokstruct.setvalue = setpagesize;
+ fpokstruct.dataptr = &(curpage->pagesize);
+ WinAddCallback(fpokstruct.buttonw, XtNselect, getproptext, &fpokstruct);
+ WinAddCallback(fpokstruct.buttonw, XtNselect, updatetext, entertext);
+ WinAddCallback(fpokstruct.textw, XtNexecute, getproptext, &fpokstruct);
+ WinAddCallback(fpokstruct.textw, XtNexecute, updatetext, entertext);
+
+ WinAddCallback(get_widget(GetDlgItem(hwnd, IDOK)), XtNselect, setfile, entertext[0]);
+
+ if (curpage->pmode > 0) {
+ XtManageChild(get_widget(GetDlgItem(hwnd, IDC_AUTOFIT)));
+ XtManageChild(fpokstruct.textw);
+ XtManageChild(fpokstruct.buttonw);
+ }
+
+ if (pagelinks(areawin->page) > 1)
+ XtManageChild(get_widget(GetDlgItem(hwnd, IDC_PAGENUM)));
+
+ SetFocus(entertext[0]->handle);
+ }
+ return FALSE;
+ case WM_DESTROY:
+ if (popup->bufhdc)
+ free((Widget*)popup->bufhdc);
+ destroy_widget(hwnd);
+ {
+ int ID[] = { IDOK, IDCANCEL, IDC_APPLY1, IDC_FILENAME, IDC_APPLY2, IDC_PAGELABEL,
+ IDC_APPLY3, IDC_SCALE, IDC_APPLY4, IDC_WIDTH, IDC_APPLY5, IDC_HEIGHT,
+ IDC_PAGENUM, IDC_AUTOFIT, IDC_FPEDIT, -1 };
+ int i;
+
+ for (i=0; ID[i]!=-1; i++)
+ destroy_widget(GetDlgItem(hwnd, ID[i]));
+ }
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (HIWORD(wParam) == BN_CLICKED) {
+ execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
+ EndDialog(hwnd, 1);
+ }
+ break;
+ case IDCANCEL:
+ if (HIWORD(wParam) == BN_CLICKED)
+ EndDialog(hwnd, 0);
+ break;
+ case IDC_FILEOPEN:
+ {
+ OPENFILENAME ofn;
+ int len;
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFile = _STR2;
+ ofn.nMaxFile = 250;
+ ofn.lpstrFilter = "XCircuit Files (*.ps;*.eps)\000*.ps;*.eps\000All Files (*.*)\000*.*\000\000\000";
+ GetDlgItemText(hwnd, IDC_FILENAME, _STR2, 250);
+ change_char(_STR2, '/', '\\');
+ if (strstr(_STR2, ".") == NULL)
+ strncat(_STR2, ".ps", 250);
+ if (GetSaveFileName(&ofn)) {
+ change_char(_STR2, '\\', '/');
+ len = strlen(_STR2);
+ if (len >= 3 && strncmp(_STR2+len-3, ".ps", 3) == 0)
+ _STR2[len-3] = '\0';
+ SetDlgItemText(hwnd, IDC_FILENAME, _STR2);
+ SendDlgItemMessage(hwnd, IDC_APPLY1, BM_CLICK, 0, 0);
+ }
+ }
+ break;
+ case IDC_APPLY1:
+ case IDC_APPLY2:
+ case IDC_APPLY3:
+ case IDC_APPLY4:
+ case IDC_APPLY5:
+ case IDC_APPLY6:
+ if (HIWORD(wParam) == BN_CLICKED)
+ execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
+ break;
+ case IDC_PAGENUM:
+ case IDC_AUTOFIT:
+ if (HIWORD(wParam) == BN_CLICKED) {
+ if (SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED)
+ execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
+ else
+ execute_callback(XtNrelease, get_widget((HWND)lParam), NULL);
+ }
+ break;
+ case IDC_MODE:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
+ break;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern int main(int argc, char **argv);
+
+int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
+{
+ LPWSTR *wargv;
+ char **argv;
+ int argc, i;
+
+ wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ argv = (char**)malloc(sizeof(char*)*argc);
+ for (i=0; i<argc; i++) {
+ int len = wcslen(wargv[i]);
+ argv[i] = (char*)malloc(sizeof(char)*2*(len+1));
+ wcstombs(argv[i], wargv[i], 2*(len+1));
+ if (argv[i][0] != '-')
+ change_char(argv[i], '\\', '/');
+ }
+
+ LocalFree(wargv);
+ return main(argc, argv);
+}
+
+const char* WinBuiltinsDir()
+{
+ static char buffer[MAX_PATH] = {0};
+
+ if (buffer[0] == 0) {
+ char *c;
+ GetModuleFileName(NULL, buffer, MAX_PATH);
+ c = strrchr(buffer, '\\');
+ if (c == NULL)
+ c = strrchr(buffer, '/');
+ if (c != NULL) {
+ *c = '\0';
+ change_char(buffer, '\\', '/');
+ }
+ }
+ return buffer;
+}
+
+static Widget find_menu_from_name(Menu menu, const char *name)
+{
+ int count, i;
+ MENUITEMINFO mi_info;
+ MenuItem item;
+ Widget found = NULL;
+
+ count = GetMenuItemCount((HMENU)menu->handle);
+ ZeroMemory(&mi_info, sizeof(mi_info));
+ mi_info.cbSize = sizeof(mi_info);
+ mi_info.fMask = MIIM_DATA;
+ for (i=0; found == NULL && i<count; i++) {
+ mi_info.dwItemData = (LONG)NULL;
+ if (GetMenuItemInfo((HMENU)menu->handle, i, MF_BYPOSITION, &mi_info) &&
+ (item = (MenuItem)mi_info.dwItemData) != NULL) {
+ if (item->name && strcmp(item->name, name) == 0)
+ found = (Widget)item;
+ else if (item->popup != NULL)
+ found = find_menu_from_name(item->popup, name);
+ }
+ }
+ return found;
+}
+
+Widget WinGetMenu(const char *name)
+{
+ MENUINFO minfo;
+
+ ZeroMemory(&minfo, sizeof(minfo));
+ minfo.cbSize = sizeof(minfo);
+ minfo.fMask = MIM_MENUDATA;
+ if (GetMenuInfo(GetMenu(topwin), &minfo)) {
+ Menu menu = (Menu)minfo.dwMenuData;
+ if (name == NULL || *name == '\0')
+ return (Widget)menu;
+ else
+ return find_menu_from_name(menu, name);
+ }
+ return NULL;
+}
+
+int WinIsPopupMenu(Widget w)
+{
+ if (IS_MENU(w) ||
+ (IS_MENUITEM(w) && TOMENUITEM(w)->popup != NULL))
+ return 1;
+ return 0;
+}
+
+void exec_script_command(void *button, void *data)
+{
+#ifdef USE_WIN32_COM
+ COM_execute(_STR2);
+#endif
+}
+
+void docommand()
+{
+ popupprompt(NULL, "Enter command to execute:", "", exec_script_command, NULL, NULL);
+}
+
+#ifdef USE_WIN32_COM
+
+void win32_comscript()
+{
+ COM_runscript(_STR2);
+}
+
+void win32_comdotnet()
+{
+ COM_load_dotnet(_STR2);
+}
+
+#endif
+
+void win32_new_window(Widget w, void *clientData, void *callData)
+{
+ XCWindowData *newwin = GUI_init(0, NULL);
+
+ newwin->page = areawin->page;
+ newwin->vscale = areawin->vscale;
+ newwin->pcorner = areawin->pcorner;
+ newwin->topinstance = areawin->topinstance;
+
+ areawin = newwin;
+ ShowWindow(top->handle, SW_SHOW);
+}
diff --git a/xcwin32.h b/xcwin32.h
new file mode 100644
index 0000000..1724481
--- /dev/null
+++ b/xcwin32.h
@@ -0,0 +1,587 @@
+#ifndef __XCWIN32_H__
+#define __XCWIN32_H__
+
+#include <windows.h>
+#include <commctrl.h>
+
+typedef int Boolean;
+typedef Boolean Bool;
+#define True 1
+#define False 0
+typedef void* XtPointer;
+typedef short Dimension;
+typedef short Position;
+typedef HBITMAP Pixmap;
+typedef struct __WinWidget *Widget;
+typedef Widget *WidgetList;
+typedef HWND Window;
+typedef int Pixel;
+typedef struct {
+ int pixel;
+ int red, green, blue;
+ int flags;
+} XColor;
+#define DoRed 0x1
+#define DoGreen 0x2
+#define DoBlue 0x4
+typedef struct __GC *GC;
+typedef void Display;
+typedef void* Colormap;
+typedef int XtIntervalId;
+typedef HCURSOR Cursor;
+typedef void* caddr_t;
+typedef void(*XtCallbackProc)();
+typedef void(*XtEventHandler)();
+typedef void(*XtTimerCallbackProc)();
+typedef void* XtAppContext;
+typedef struct __XrmValue *XrmValuePtr;
+typedef struct {
+ short x, y;
+} XPoint;
+typedef struct {
+ short width, height;
+ char *data;
+ int bits_per_pixel;
+ int bytes_per_line;
+ HBITMAP handle;
+} XImage;
+typedef struct {
+ int ascent, descent;
+ HFONT fid;
+} XFontStruct;
+typedef struct {
+ int type;
+ int x, y;
+ int button;
+ int state;
+} XButtonEvent;
+typedef struct {
+ int type;
+ int x, y;
+ int keycode;
+ int state;
+} XKeyEvent;
+typedef struct {
+ int type;
+ int x, y;
+} XMotionEvent, XPointerMovedEvent;
+typedef void* XCrossingEvent;
+typedef struct {
+ int type;
+ int message_type;
+ Display* display;
+ int format;
+ HWND window;
+ union {
+ long l[5];
+ } data;
+} XClientMessageEvent;
+typedef union {
+ int type;
+ XButtonEvent button;
+ XKeyEvent key;
+ XMotionEvent motion;
+ XPointerMovedEvent pointer_moved;
+ XCrossingEvent crossing;
+ XClientMessageEvent xclient;
+} XEvent;
+typedef unsigned int KeySym;
+typedef struct {
+ int type;
+ void *data;
+} Arg;
+typedef struct __CharStruct *XCharStruct;
+
+struct __GC {
+ /* colors */
+ int foreground, background;
+ int function;
+ /* fill */
+ int fill_style;
+ HBITMAP fill_stipple;
+ /* line */
+ int line_width;
+ int line_style;
+ int line_cap;
+ int line_join;
+ int line_dash_len;
+ char *line_dash;
+ /* font */
+ HFONT font;
+ /* misc */
+ Boolean graphics_exposures;
+ HBITMAP clipMask;
+};
+typedef struct __GC XGCValues;
+typedef ATOM Atom;
+typedef void XWMHints;
+
+typedef unsigned int Cardinal;
+#define XtOffset(p_type,field) \
+ ((Cardinal) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
+
+#define GCForeground 0x01
+#define GCBackground 0x02
+#define GCFont 0x04
+#define GCFunction 0x08
+#define GCGraphicsExposures 0x10
+
+#define GXcopy R2_COPYPEN
+#define GXxor R2_XORPEN
+
+/* TODO */
+#define PointerMotionMask 0x0001
+#define ButtonMotionMask 0x0002
+#define Button1MotionMask 0x0004
+#define Button2MotionMask 0x0008
+#define EnterWindowMask 0x0010
+#define LeaveWindowMask 0x0020
+#define ButtonPressMask 0x0040
+#define KeyPressMask 0x0080
+#define NoEventMask 0x0000
+
+#define ButtonPress 0x01
+#define ButtonRelease 0x02
+#define KeyPress 0x03
+#define KeyRelease 0x04
+#define ClientMessage 0x05
+#define MotionNotify 0x06
+
+#define None 0
+#define Nonconvex 0
+#define CoordModeOrigin 0
+#define NoSymbol 0
+
+#define Mod1Mask 0x0001
+#define Mod2Mask 0x0002
+#define LockMask 0x0004
+#define ShiftMask 0x0008
+#define ControlMask 0x0010
+#define Mod5Mask 0x0080
+#define Button1 0x0100
+#define Button2 0x0200
+#define Button3 0x0800
+#define Button4 0x1000
+#define Button5 0x2000
+#define Button1Mask Button1
+#define Button2Mask Button2
+#define Button3Mask Button3
+#define Button4Mask Button4
+#define Button5Mask Button5
+
+#define LineSolid PS_SOLID
+#define LineOnOffDash PS_DASH
+#define CapRound PS_ENDCAP_ROUND
+#define CapButt PS_ENDCAP_FLAT
+#define CapProjecting PS_ENDCAP_SQUARE
+#define JoinBevel PS_JOIN_BEVEL
+#define JoinMiter PS_JOIN_MITER
+#define FillSolid 0
+#define FillStippled 1
+#define FillOpaqueStippled 2
+
+#define XtNwidth 0
+#define XtNheight 1
+#define XtNx 2
+#define XtNy 3
+#define XtNfont 4
+#define XtNexpose 5
+#define XtNset 6
+#define XtNsquare 7
+#define XtNlabelLocation 8
+#define XtNborderWidth 9
+#define XtNselect 10
+#define XtNrelease 11
+#define XtNlabel 12
+#define XtNxResizable 13
+#define XtNyResizable 14
+#define XtNxRefWidget 15
+#define XtNyRefWidget 16
+#define XtNyAddHeight 17
+#define XtNyAttachBottom 18
+#define XtNxAttachRight 19
+#define XtNyAddHeight 17
+#define XtNyAttachBottom 18
+#define XtNxAttachRight 19
+#define XtNyAddHeight 17
+#define XtNyAttachBottom 18
+#define XtNxAttachRight 19
+#define XtNxAddWidth 20
+#define XtNforeground 21
+#define XtNstring 22
+#define XtNsetMark 23
+#define XtNbackground 24
+#define XtNborderColor 25
+#define XtNrectColor 26
+#define XtNresize 27
+#define XtNlabelType 28
+#define XtNrectStipple 29
+#define XtNattachTo 30
+#define XtNsensitive 31
+#define XtNxOffset 32
+#define XtNyOffset 33
+#define XtNlayout 34
+#define XtNinsertPosition 35
+#define XtNgravity 36
+#define XtNscroll 37
+#define XtNwrap 38
+#define XtNexecute 39
+#define XtNkeyUp 40
+#define XtNkeyDown 41
+#define XtNcolormap 42
+#define XtNstrip 43
+
+#define XwLEFT 0
+#define XwRECT 1
+#define XwIMAGE 2
+#define XwIGNORE 3
+
+#define WestGravity 0
+#define XwWrapOff 0
+#define XwAutoScrollHorizontal 0
+
+#define XwworkSpaceWidgetClass 0x01
+#define XwtoggleWidgetClass 0x02
+#define XwmenubuttonWidgetClass 0x03
+#define XwformWidgetClass 0x04
+#define XwmenuButtonWidgetClass 0x05
+#define XwbulletinWidgetClass 0x06
+#define XwcascadeWidgetClass 0x07
+#define XwpopupmgrWidgetClass 0x08
+#define XwstaticTextWidgetClass 0x09
+#define XwpushButtonWidgetClass 0x0A
+#define XwtextEditWidgetClass 0x0B
+
+#define XC_xterm IDC_IBEAM
+#define XC_watch IDC_WAIT
+
+#define XtWindow(x) WinWindow(x)
+#define XtAppAddTimeOut(app,delay,proc,data) WinAddTimeOut(delay,proc,data)
+#define XtRemoveTimeOut(ID) WinRemoveTimeOut(ID)
+#define XWarpPointer(dpy,flag,win,x1,y1,x2,y2,x3,y3) WinWarpPointer(win,x3,y3)
+/*#define XCheckWindowEvent(dpy,win,mask,evt) WinCheckWindowEvent(win,mask,evt)*/
+#define XCheckWindowEvent(dpy,win,mask,evt) False
+#define XtDispatchEvent(evt)
+#define XtSetArg(arg,t,d) (arg.type = t, arg.data = (void*)(d))
+#define XtGetValues(win,args,n) WinGetValues(win,args,n)
+#define XtSetValues(win,args,n) WinSetValues(win,args,n)
+#define XCreatePixmap(dpy,win,w,h,depth) WinCreatePixmap(win,w,h)
+#define XFreePixmap(dpy,w) WinFreePixmap(w)
+#define XCreateImage(dpy,visual,depth,flag,offset,data,w,h,pad,bpl) WinCreateImage(w,h)
+#define XDestroyImage(img) WinDestroyImage(img)
+#define XSetLineAttributes(dpy,gc,w,style,cap,join) WinSetLineAttributes(gc,w,style,cap,join)
+#define XCreateGC(dpy,win,mask,gc) WinCreateGC(win,mask,gc)
+#define XFreeGC(gc) WinFreeGC(gc)
+#define XtParent(w) WinParent(w)
+#define XtNameToWidget(parent,name) WinNameToWindow(parent,name)
+#define XtCreateManagedWidget(name,cls,parent,args,n) WinCreateWidget(name,cls,parent,args,n,1)
+#define XtCreateWidget(name,cls,parent,args,n) WinCreateWidget(name,cls,parent,args,n,0)
+#define DefaultRootWindow(dpy) GetDesktopWindow()
+#define DefaultColormap(dpy,screen) NULL
+#define DefaultScreen(dpy) 0
+#define XFreeColormap(dpy,cmap)
+#define XtDisplay(x) GetDesktopWindow()
+#define XtCreatePopupShell(name,cls,btn,args,n) WinCreatePopup(name,args,n)
+#define XtPopup(w,flag) WinPopup(w)
+#define XKeysymToString(ks) WinKeyToString(ks)
+#define XChangeProperty(dpy,win,prop,type,format,mode,data,len)
+#define XCreateBitmapFromData(dpy,win,bits,w,h) WinCreateBitmapFromData(win,bits,w,h)
+#define XCreatePixmapCursor(dpy,src,mask,fg,bg,xhot,yhot) WinCreateCursor(src,mask,xhot,yhot)
+#define XCreateFontCursor(dpy,type) WinCreateStandardCursor(type)
+#define XtOpenApplication(app,name,dummy,n,Argc,Argv,argfb,cls,arglist,narg) WinCreateTopLevel(name,Argc,Argv)
+#define XDefineCursor(dpy,w,cur) WinSetCursor(w,cur)
+#define XtMalloc malloc
+#define BlackPixel(dpy,screen) RGB(0,0,0)
+#define WhitePixel(dpy,screen) RGB(255,255,255)
+#define XBell(dpy,len) MessageBeep(-1)
+#define XSync(dpy,flag) WinDebug("Should sync\n")
+#define XFlush(dpy) WinDebug("Should flush\n")
+#define XSendEvent(dpy,win,prop,mask,evt) WinDebug("Should send an event\n")
+#define DisplayWidth(dpy,screen) WinDesktopWidth()
+#define DisplayHeight(dpy,screen) WinDesktopHeight()
+#define XGetPixel(img,x,y) WinGetPixel(img,x,y)
+#define XPutPixel(img,x,y,c) WinPutPixel(img,x,y,c)
+#define XDrawArc(dpy,win,gc,x,y,w,h,a1,a2) WinDrawArc(win,gc,x,y,w,h,a1,a2)
+#define XDrawLine(dpy,win,gc,x1,y1,x2,y2) WinDrawLine(win,gc,x1,y1,x2,y2)
+#define XDrawLines(dpy,win,gc,pl,n,dummy) WinDrawLines(win,gc,pl,n)
+#define XFillPolygon(dpy,win,gc,pl,n,x1,x2) WinFillPolygon(win,gc,pl,n)
+#define XClearArea(dpy,win,x,y,w,h,dummy) WinClearArea(win,x,y,w,h)
+#define XFillRectangle(dpy,win,gc,x,y,w,h) WinFillRectangle(win,gc,x,y,w,h)
+/*#define XSetLineAttributes(dpy,gc,w,s,c,j) WinSetLineAttributes(gc,w,s,c,j)*/
+#define XDrawPoint(dpy,win,gc,x,y) WinDrawPoint(win,gc,x,y)
+#define XSetForeground(dpy,gc,c) WinSetForeground(gc,c)
+#define XSetFunction(dpy,gc,z) WinSetFunction(gc,z)
+#define XSetBackground(dpy,gc,c) WinSetBackground(gc,c)
+#define XCopyArea(dpy,win1,win2,gc,x,y,w,h,offx,offy) WinCopyArea(win1,win2,gc,x,y,w,h,offx,offy)
+#define XTextWidth(font,str,len) WinTextWidth(font,str,len)
+#define XtNumber(arr) ((int) (sizeof(arr) / sizeof(arr[0])))
+#define XSetFillStyle(dpy,gc,fs) WinSetFillStyle(gc,fs)
+#define XSetDashes(dpy,gc,offset,dash,n) WinSetDashes(gc,offset,dash,n)
+#define XSetStipple(dpy,gc,stipple) WinSetStipple(gc,stipple)
+#define XQueryPointer(dpy,win,rr,cr,rx,ry,x,y,m) WinQueryPointer(win,x,y)
+#define XDrawRectangle(dpy,win,gc,x,y,w,h) WinDrawRectangle(win,gc,x,y,w,h)
+#define XtManageChild(win) WinManageChild(win)
+#define XtUnmanageChild(win) WinUnmanageChild(win)
+#define XRecolorCursor(dpy,cur,fg,bg)
+#define XDrawString(dpy,win,gc,x,y,str,len) WinDrawString(win,gc,x,y,str,len)
+#define XTextExtents(font,str,len,dum1,w,h,dum2) WinTextExtents(font,str,len,w,h)
+#define XDisplayString(dpy) "unknown:0.0"
+#define XQueryColors(dpy,cmap,cl,n) WinQueryColors(cl,n)
+#define XLookupColor(dpy,cmap,cname,exact,color) WinLookupColor(cname,color)
+#define XtAppMainLoop(app) WinAppMainLoop()
+#define XtIsRealized(w) True
+#define XPutImage(dpy,win,gc,img,srcx,srcy,destx,desty,w,h) WinPutImage(win,gc,img,srcx,srcy,destx,desty,w,h)
+#define XFreeColorMap(dpy,cmap)
+#define XtDestroyWidget(w) DeleteObject(w)
+#define XtTranslateCoords(win,x,y,rx,ry) WinTranslateCoords(win,x,y,rx,ry)
+#define XStringToKeysym(str) WinStringToKey(str)
+#define XInternAtom(dpy,str,flag) AddAtom(str)
+#define XSetClipMask(dpy,gc,pix) WinSetClipMask(gc,pix)
+#define XSetClipOrigin(dpy,gc,x,y)
+#define XtAddEventHandler(win,mask,flag,proc,data) WinAddEventHandler(win,mask,proc,data)
+#define XtRemoveEventHandler(win,mask,flag,proc,data) WinRemoveEventHandler(win,mask,proc,data)
+#define XtAddCallback(win,mask,proc,data) WinAddCallback(win,mask,proc,data)
+#define XtRemoveCallback(win,mask,proc,data) WinRemoveCallback(win,mask,proc,data)
+#define XtRemoveAllCallbacks(win,event)
+#define XwTextCopyBuffer(win) WinGetText(win)
+#define XwTextClearBuffer(win) WinClearText(win)
+#define XLookupString(event,str,size,keyptr,flag) WinLookupString(event,keyptr)
+#define XwPostPopup(shell,menu,button,dx,dy) WinPostPopup(menu,button,dx,dy)
+#define XtOverrideTranslations(win,table,def)
+
+void WinWarpPointer(HWND w, int x, int y);
+int WinAddTimeOut(int delay, void(*proc)(), void* data);
+void WinRemoveTimeOut(int ID);
+int WinCheckWindowEvent(HWND w, int mask, XEvent *event);
+void WinGetValues(Widget win, Arg *args, int n);
+void WinSetValues(Widget win, Arg *args, int n);
+HBITMAP WinCreatePixmap(HWND w, int width, int height);
+XImage* WinCreateImage(int width, int height);
+void WinSetLineAttributes(GC gc, int width, int style, int cap, int join);
+GC WinCreateGC(HWND w, int mask, XGCValues *values);
+void WinFreeGC(GC gc);
+Widget WinParent(Widget w);
+Widget WinNameToWindow(Widget parent, const char *name);
+Widget WinCreateWidget(const char *name, int cls, Widget parent, Arg *args, int n, int show);
+Widget WinCreatePopup(const char *name, Arg *args, int n);
+void WinPopup(Widget w);
+char* WinKeyToString(int ks);
+HCURSOR WinCreateCursor(HBITMAP src, HBITMAP mask, int xhot, int yhot);
+HBITMAP WinCreateBitmapFromData(HWND w, char *data, int width, int height);
+HCURSOR WinCreateStandardCursor(char *type);
+HWND WinCreateTopLevel(const char *name, int *argc, char **argv);
+void WinSetCursor(HWND w, HCURSOR cur);
+void WinFreePixmap(Pixmap w);
+int WinDesktopWidth(void);
+int WinDesktopHeight(void);
+int WinGetPixel(XImage *img, int x, int y);
+void WinPutPixel(XImage *img, int x, int y, int c);
+void WinDrawArc(HWND win, GC gc, int x, int y, int w, int h, int a1, int a2);
+void WinDrawLines(HWND win, GC gc, XPoint* pathlist, int number);
+void WinFillPolygon(HWND win, GC gc, XPoint* pathlist, int number);
+void WinClearArea(HWND win, int x, int y, int w, int h);
+void WinFillRectangle(HWND win, GC gc, int x, int y, int w, int h);
+void WinSetForeground(GC gc, int rgb);
+int WinTextWidth(XFontStruct *f, char *s, int len);
+void WinSetFillStyle(GC gc, int style);
+void WinSetStipple(GC gc, Pixmap pattern);
+void WinSetFunction(GC gc, int op);
+void WinDrawLine(HWND win, GC gc, int x1, int y1, int x2, int y2);
+void WinDrawPoint(HWND win, GC gc, int x, int y);
+void WinSetBackground(GC gc, int rgb);
+void WinCopyArea(Pixmap buf, HWND win, GC gc, int x, int y, int w, int h, int offx, int offy);
+void WinSetDashes(GC gc, int offset, char *dash, int n);
+void WinQueryPointer(HWND w, int *x, int *y);
+void WinDrawRectangle(HWND w, GC gc, int x, int y, int width, int height);
+void WinDrawString(HWND win, GC gc, int x, int y, const char *str, int len);
+void WinTextExtents(XFontStruct *fs, char *str, int len, int *width, int *height);
+void WinQueryColors(XColor *cl, int n);
+void WinAppMainLoop(void);
+void WinPutImage(HWND win, GC gc, XImage *img, int srcx, int srcy, int destx, int desty, int width, int height);
+void WinTranslateCoords(Widget win, short x, short y, short *rx, short *ry);
+int WinStringToKey(const char *str);
+void WinAddEventHandler(Widget win, int event, void(*proc)(), void *data);
+void WinRemoveEventHandler(Widget win, int event, void(*proc)(), void *data);
+void WinAddCallback(Widget win, int event, void(*proc)(), void *data);
+int WinFindCallback(Widget win, int event, void(**proc)(), void **data);
+void WinRemoveCallback(Widget win, int event, void(*proc)(), void *data);
+void WinRemoveAllCallbacks(Widget win, int event);
+char* WinGetText(Widget win);
+void WinClearText(Widget win);
+int WinNamedColor(const char *cname);
+int WinLookupColor(const char *cname, XColor *color);
+char* WinColorName(int c);
+HWND WinWindow(Widget w);
+void WinManageChild(Widget w);
+void WinUnmanageChild(Widget w);
+void WinLookupString(XKeyEvent *event, KeySym *key);
+void WinPostPopup(Widget menu, Widget button, int dx, int dy);
+const char* WinBuiltinsDir(void);
+Widget WinGetMenu(const char *name);
+const char* WinName(Widget w);
+int WinIsPopupMenu(Widget w);
+
+#define KPMOD 0x1000
+#define VKMOD 0x2000
+
+#define XK_Control_L (VKMOD|VK_CONTROL)
+#define XK_Control_R (VKMOD|VK_CONTROL)
+#define XK_Alt_L (VKMOD|VK_MENU)
+#define XK_Alt_R (VKMOD|VK_MENU)
+#define XK_Shift_L (VKMOD|VK_SHIFT)
+#define XK_Shift_R (VKMOD|VK_SHIFT)
+#define XK_Caps_Lock (VKMOD|VK_CAPITAL)
+#define XK_Num_Lock (VKMOD|VK_NUMLOCK)
+
+#define XK_a 'a'
+#define XK_b 'b'
+#define XK_c 'c'
+#define XK_d 'd'
+#define XK_e 'e'
+#define XK_f 'f'
+#define XK_g 'g'
+#define XK_h 'h'
+#define XK_i 'i'
+#define XK_j 'j'
+#define XK_k 'k'
+#define XK_l 'l'
+#define XK_m 'm'
+#define XK_n 'n'
+#define XK_o 'o'
+#define XK_p 'p'
+#define XK_q 'q'
+#define XK_r 'r'
+#define XK_s 's'
+#define XK_t 't'
+#define XK_u 'u'
+#define XK_v 'v'
+#define XK_w 'w'
+#define XK_x 'x'
+#define XK_y 'y'
+#define XK_z 'z'
+#define XK_A 'A'
+#define XK_B 'B'
+#define XK_C 'C'
+#define XK_D 'D'
+#define XK_E 'E'
+#define XK_F 'F'
+#define XK_G 'G'
+#define XK_H 'H'
+#define XK_I 'I'
+#define XK_J 'J'
+#define XK_K 'K'
+#define XK_L 'L'
+#define XK_M 'M'
+#define XK_N 'N'
+#define XK_O 'O'
+#define XK_P 'P'
+#define XK_Q 'Q'
+#define XK_R 'R'
+#define XK_S 'S'
+#define XK_T 'T'
+#define XK_U 'U'
+#define XK_V 'V'
+#define XK_W 'W'
+#define XK_X 'X'
+#define XK_Y 'Y'
+#define XK_Z 'Z'
+#define XK_Home (VKMOD|VK_HOME)
+#define XK_Delete (VKMOD|VK_DELETE)
+#define XK_Escape (VKMOD|VK_ESCAPE)
+#define XK_F19 (VKMOD|VK_F19)
+#define XK_Right (VKMOD|VK_RIGHT)
+#define XK_Left (VKMOD|VK_LEFT)
+#define XK_Down (VKMOD|VK_DOWN)
+#define XK_Up (VKMOD|VK_UP)
+#define XK_Insert (VKMOD|VK_INSERT)
+#define XK_End (VKMOD|VK_END)
+#define XK_Return (VKMOD|VK_RETURN)
+#define XK_BackSpace (VKMOD|VK_BACK)
+#define XK_Undo (VKMOD|VK_F6)
+#define XK_Redo (VKMOD|VK_F7)
+#define XK_Tab (VKMOD|VK_TAB)
+#define XK_percent '%'
+#define XK_period '.'
+#define XK_bar '|'
+#define XK_greater '>'
+#define XK_less '<'
+#define XK_question '?'
+#define XK_colon ':'
+#define XK_underscore '_'
+#define XK_space ' '
+#define XK_plus '+'
+#define XK_minus '-'
+#define XK_slash '/'
+#define XK_backslash '\\'
+#define XK_1 '1'
+#define XK_2 '2'
+#define XK_3 '3'
+#define XK_4 '4'
+#define XK_5 '5'
+#define XK_6 '6'
+#define XK_7 '7'
+#define XK_8 '8'
+#define XK_9 '9'
+#define XK_0 '0'
+#define XK_KP_1 (KPMOD|XK_1)
+#define XK_KP_2 (KPMOD|XK_2)
+#define XK_KP_3 (KPMOD|XK_3)
+#define XK_KP_4 (KPMOD|XK_4)
+#define XK_KP_5 (KPMOD|XK_5)
+#define XK_KP_6 (KPMOD|XK_6)
+#define XK_KP_7 (KPMOD|XK_7)
+#define XK_KP_8 (KPMOD|XK_8)
+#define XK_KP_9 (KPMOD|XK_9)
+#define XK_KP_0 (KPMOD|XK_0)
+#define XK_KP_Enter (KPMOD|VKMOD|VK_RETURN)
+#define XK_KP_Add (KPMOD|XK_plus)
+#define XK_KP_Subtract (KPMOD|XK_minus)
+#define XK_KP_End (KPMOD|VKMOD|VK_END)
+#define XK_KP_Home (KPMOD|VKMOD|VK_HOME)
+#define XK_KP_Up (KPMOD|VKMOD|VK_UP)
+#define XK_KP_Down (KPMOD|VKMOD|VK_DOWN)
+#define XK_KP_Right (KPMOD|VKMOD|VK_RIGHT)
+#define XK_KP_Left (KPMOD|VKMOD|VK_LEFT)
+#define XK_KP_Next (KPMOD|VKMOD|VK_NEXT)
+#define XK_KP_Prior (KPMOD|VKMOD|VK_PRIOR)
+#define XK_KP_Begin (KPMOD|VKMOD|VK_CLEAR)
+
+struct direct {
+ char *d_name;
+};
+typedef struct {
+ HANDLE hnd;
+ WIN32_FIND_DATA fd;
+ int dirty;
+ struct direct d;
+} DIR;
+DIR* opendir(const char*);
+struct direct* readdir(DIR*);
+void closedir(DIR*);
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define va_copy(a,b) a=b
+#define pipe _pipe
+#define strdup _strdup
+#define unlink _unlink
+#define putenv _putenv
+#define fdopen _fdopen
+
+#define usleep(x) if (x < 1000) WinDebug("Cannot sleep less than 1us\n"); else Sleep(x/1000);
+
+#ifdef USE_WIN32_COM
+extern void win32_comscript();
+#ifdef USE_WIN32_DOTNET
+extern void win32_comdotnet();
+#endif
+enum win32_events {
+ ModifiedChanged,
+ ZoomChanged
+};
+extern void win32_fire_event(int event_type);
+#endif
+
+extern void win32_new_window(Widget, void*, void*);
+
+#endif
diff --git a/xcwrap.c b/xcwrap.c
new file mode 100644
index 0000000..fd0d827
--- /dev/null
+++ b/xcwrap.c
@@ -0,0 +1,239 @@
+/*--------------------------------------------------------------*/
+/* xcwrap.c: */
+/* Tcl module generator for xcircuit */
+/*--------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tk.h>
+
+Tcl_Interp *xcinterp;
+Tcl_Interp *consoleinterp;
+
+/*------------------------------------------------------*/
+/* Redefine all of the callback functions for Tcl/Tk */
+/*------------------------------------------------------*/
+
+extern int Tk_SimpleObjCmd();
+extern int xctcl_standardaction();
+extern int xctcl_action();
+extern int xctcl_refresh();
+extern int xctcl_library();
+extern int xctcl_tech();
+extern int xctcl_font();
+extern int xctcl_cursor();
+extern int xctcl_bind();
+extern int xctcl_filerecover();
+extern int xctcl_color();
+extern int xctcl_dofill();
+extern int xctcl_doborder();
+extern int xctcl_promptquit();
+extern int xctcl_quit();
+extern int xctcl_promptsavepage();
+extern int xctcl_eventmode();
+extern int xctcl_delete();
+extern int xctcl_undo();
+extern int xctcl_redo();
+extern int xctcl_copy();
+extern int xctcl_move();
+extern int xctcl_edit();
+extern int xctcl_param();
+extern int xctcl_select();
+extern int xctcl_deselect();
+extern int xctcl_push();
+extern int xctcl_pop();
+extern int xctcl_rotate();
+extern int xctcl_flip();
+extern int xctcl_config();
+extern int xctcl_page();
+extern int xctcl_spice();
+extern int xctcl_svg();
+extern int xctcl_zoom();
+extern int xctcl_pan();
+extern int xctcl_element();
+extern int xctcl_label();
+extern int xctcl_polygon();
+extern int xctcl_instance();
+extern int xctcl_spline();
+extern int xctcl_path();
+extern int xctcl_arc();
+extern int xctcl_graphic();
+extern int xctcl_object();
+extern int xctcl_here();
+extern int xctcl_start();
+extern int xctcl_netlist();
+extern int xctcl_symschem();
+extern int xctcl_tag();
+
+typedef struct {
+ const char *cmdstr;
+ void (*func)();
+} cmdstruct;
+
+static cmdstruct xc_commands[] =
+{
+ {"action", (void *)xctcl_action},
+ {"standardaction", (void *)xctcl_standardaction},
+ {"start", (void *)xctcl_start},
+ {"tag", (void *)xctcl_tag},
+ {"refresh", (void *)xctcl_refresh},
+ {"library", (void *)xctcl_library},
+ {"technology", (void *)xctcl_tech},
+ {"loadfont", (void *)xctcl_font},
+ {"cursor", (void *)xctcl_cursor},
+ {"bindkey", (void *)xctcl_bind},
+ {"filerecover", (void *)xctcl_filerecover},
+ {"color", (void *)xctcl_color},
+ {"fill", (void *)xctcl_dofill},
+ {"border", (void *)xctcl_doborder},
+ {"quit", (void *)xctcl_promptquit},
+ {"quitnocheck", (void *)xctcl_quit},
+ {"promptsavepage", (void *)xctcl_promptsavepage},
+ {"eventmode", (void *)xctcl_eventmode},
+ {"delete", (void *)xctcl_delete},
+ {"undo", (void *)xctcl_undo},
+ {"redo", (void *)xctcl_redo},
+ {"select", (void *)xctcl_select},
+ {"deselect", (void *)xctcl_deselect},
+ {"copy", (void *)xctcl_copy},
+ {"move", (void *)xctcl_move},
+ {"edit", (void *)xctcl_edit},
+ {"parameter", (void *)xctcl_param},
+ {"push", (void *)xctcl_push},
+ {"pop", (void *)xctcl_pop},
+ {"rotate", (void *)xctcl_rotate},
+ {"flip", (void *)xctcl_flip},
+ {"config", (void *)xctcl_config},
+ {"page", (void *)xctcl_page},
+ {"zoom", (void *)xctcl_zoom},
+ {"pan", (void *)xctcl_pan},
+ {"element", (void *)xctcl_element},
+ {"label", (void *)xctcl_label},
+ {"polygon", (void *)xctcl_polygon},
+ {"instance", (void *)xctcl_instance},
+ {"spline", (void *)xctcl_spline},
+ {"path", (void *)xctcl_path},
+ {"arc", (void *)xctcl_arc},
+ {"graphic", (void *)xctcl_graphic},
+ {"object", (void *)xctcl_object},
+ {"here", (void *)xctcl_here},
+ {"netlist", (void *)xctcl_netlist},
+ {"symbol", (void *)xctcl_symschem},
+ {"schematic", (void *)xctcl_symschem},
+ {"spice", (void *)xctcl_spice},
+ {"svg", (void *)xctcl_svg},
+ {"", NULL} /* sentinel */
+};
+
+extern Tcl_HashTable XcTagTable;
+
+/*--------------------------------------------------------------*/
+/* Initialization procedure for Tcl/Tk */
+/*--------------------------------------------------------------*/
+
+#ifdef _MSC_VER
+__declspec(dllexport)
+#endif
+int
+Xcircuit_Init(Tcl_Interp *interp)
+{
+ char command[256];
+ int cmdidx;
+ Tk_Window tktop;
+ char *tmp_s, *tmp_l;
+ char *cadhome;
+ char version_string[20];
+
+ /* Interpreter sanity checks */
+ if (interp == NULL) return TCL_ERROR;
+
+ /* Remember the interpreter */
+ xcinterp = interp;
+
+ if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR;
+
+ tmp_s = getenv("XCIRCUIT_SRC_DIR");
+ if (tmp_s == NULL) tmp_s = SCRIPTS_DIR;
+
+ tmp_l = getenv("XCIRCUIT_LIB_DIR");
+ if (tmp_l == NULL) tmp_l = BUILTINS_DIR;
+
+ strcpy(command, "xcircuit::");
+
+ /* Create the start command */
+
+ tktop = Tk_MainWindow(interp);
+
+ /* Create all of the commands (except "simple") */
+
+ for (cmdidx = 0; xc_commands[cmdidx].func != NULL; cmdidx++) {
+ sprintf(command + 10, "%s", xc_commands[cmdidx].cmdstr);
+ Tcl_CreateObjCommand(interp, command,
+ (Tcl_ObjCmdProc *)xc_commands[cmdidx].func,
+ (ClientData)tktop, (Tcl_CmdDeleteProc *) NULL);
+ }
+
+ /* Command which creates a "simple" window (this is a top- */
+ /* level command, not one in the xcircuit namespace which */
+ /* is why I treat it separately from the other commands). */
+
+ Tcl_CreateObjCommand(interp, "simple",
+ (Tcl_ObjCmdProc *)Tk_SimpleObjCmd,
+ (ClientData)tktop, (Tcl_CmdDeleteProc *) NULL);
+
+ sprintf(command, "lappend auto_path %s", tmp_s);
+ Tcl_Eval(interp, command);
+ if (!strstr(tmp_s, "tcl")) {
+ sprintf(command, "lappend auto_path %s/tcl", tmp_s);
+ Tcl_Eval(interp, command);
+ }
+
+ if (strcmp(tmp_s, SCRIPTS_DIR))
+ Tcl_Eval(interp, "lappend auto_path " SCRIPTS_DIR );
+
+ /* Set $XCIRCUIT_SRC_DIR and $XCIRCUIT_LIB_DIR as Tcl variables */
+
+ Tcl_SetVar(interp, "XCIRCUIT_SRC_DIR", tmp_s, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "XCIRCUIT_LIB_DIR", tmp_l, TCL_GLOBAL_ONLY);
+
+ /* Set $CAD_ROOT as a Tcl variable */
+
+ cadhome = getenv("CAD_ROOT");
+ if (cadhome == NULL) cadhome = CAD_DIR;
+ Tcl_SetVar(interp, "CAD_ROOT", cadhome, TCL_GLOBAL_ONLY);
+
+ /* Set $XCIRCUIT_VERSION and $XCIRCUIT_REVISION as Tcl variables */
+
+ sprintf(version_string, "%d", PROG_REVISION);
+ Tcl_SetVar(interp, "XCIRCUIT_REVISION", version_string, TCL_GLOBAL_ONLY);
+
+ sprintf(version_string, "%g", PROG_VERSION);
+ Tcl_SetVar(interp, "XCIRCUIT_VERSION", version_string, TCL_GLOBAL_ONLY);
+
+#ifdef ASG
+ /* Set a variable in Tcl indicating that the ASG module is compiled in */
+ Tcl_SetVar(interp, "XCIRCUIT_ASG", "1", TCL_GLOBAL_ONLY);
+#endif
+
+ /* Export the namespace commands */
+
+ Tcl_Eval(interp, "namespace eval xcircuit namespace export *");
+ Tcl_PkgProvide(interp, "Xcircuit", version_string);
+
+ /* Initialize the console interpreter, if there is one. */
+
+ if ((consoleinterp = Tcl_GetMaster(interp)) == NULL)
+ consoleinterp = interp;
+
+ /* Initialize the command tag table */
+
+ Tcl_InitHashTable(&XcTagTable, TCL_STRING_KEYS);
+
+ return TCL_OK;
+}
+
+#endif /* TCL_WRAPPER */
diff --git a/xtfuncs.c b/xtfuncs.c
new file mode 100644
index 0000000..60f65e5
--- /dev/null
+++ b/xtfuncs.c
@@ -0,0 +1,1822 @@
+/*----------------------------------------------------------------------*/
+/* xtfuncs.c --- Functions associated with the XCircuit Xt GUI */
+/* (no Tcl/Tk interpreter) */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+
+#include "Xw/Xw.h"
+#include "Xw/MenuBtn.h"
+#include "Xw/PopupMgr.h"
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* External Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern char _STR2[250];
+extern char _STR[150]; /* Generic multipurpose string */
+extern xcWidget top;
+extern Display *dpy;
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern ApplicationData appdata;
+extern Cursor appcursors[NUM_CURSORS];
+extern fontinfo *fonts;
+extern short fontcount;
+extern xcWidget menuwidgets[];
+extern xcWidget toolbar;
+extern short popups; /* total number of popup windows */
+
+/*----------------------------------------------------------------------*/
+/* The rest of the local includes depend on the prototype declarations */
+/* and some of the external global variable declarations. */
+/*----------------------------------------------------------------------*/
+
+#include "menus.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* External variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern u_short *fontnumbers;
+extern u_char nfontnumbers;
+
+/*----------------------------------------------*/
+/* Set Poly and Arc line styles and fill styles */
+/*----------------------------------------------*/
+
+#define BORDERS (NOBORDER | DOTTED | DASHED)
+#define ALLFILLS (FILLSOLID | FILLED)
+
+/*--------------------------------------------------------------*/
+/* Menu toggle button functions (keeps Xt functions out of the */
+/* file menucalls.c). These are wrappers for toggleexcl(). */
+/*--------------------------------------------------------------*/
+
+void togglegridstyles(xcWidget button) {
+ if (button != NULL)
+ toggleexcl(button, GridStyles, XtNumber(GridStyles));
+}
+
+void togglejustifs(xcWidget button) {
+ if (button != NULL)
+ toggleexcl(button, Justifs, XtNumber(Justifs));
+}
+
+void togglefontstyles(xcWidget button) {
+ if (button != NULL)
+ toggleexcl(button, FontStyles, XtNumber(FontStyles));
+}
+
+void toggleencodings(xcWidget button) {
+ if (button != NULL)
+ toggleexcl(button, FontEncodings, XtNumber(FontEncodings));
+}
+
+/*--------------------------------------------------------------*/
+/* Toggle a bit in the justification field of a label */
+/*--------------------------------------------------------------*/
+
+void dojustifybit(xcWidget w, labelptr settext, short bitfield)
+{
+ if (settext != NULL) {
+ int oldjust = (int)settext->justify;
+
+ undrawtext(settext);
+ settext->justify ^= bitfield;
+ redrawtext(settext);
+ pwriteback(areawin->topinstance);
+
+ register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance,
+ (genericptr)settext, oldjust);
+ }
+ else
+ areawin->justify ^= bitfield;
+
+ if (w != NULL) {
+ Boolean boolval;
+ if (settext)
+ boolval = (settext->justify & bitfield) ? 0 : 1;
+ else
+ boolval = (areawin->justify & bitfield) ? 0 : 1;
+ toggle(w, (pointertype)(-1), &boolval);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Toggle a pin-related bit in the justification field of a */
+/* label. This differs from dojustifybit() in that the label */
+/* must be a pin, and this function cannot change the default */
+/* behavior set by areawin->justify. */
+/*--------------------------------------------------------------*/
+
+void dopinjustbit(xcWidget w, labelptr settext, short bitfield)
+{
+ if ((settext != NULL) && settext->pin) {
+ int oldjust = (int)settext->justify;
+
+ undrawtext(settext);
+ settext->justify ^= bitfield;
+ redrawtext(settext);
+ pwriteback(areawin->topinstance);
+
+ register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance,
+ (genericptr)settext, oldjust);
+
+ if (w != NULL) {
+ Boolean boolval = (settext->justify & bitfield) ? 0 : 1;
+ toggle(w, (pointertype)(-1), &boolval);
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the justification for the label passed as 3rd parameter */
+/*----------------------------------------------------------------*/
+
+void setjust(xcWidget w, pointertype value, labelptr settext, short mode)
+{
+ short newjust, oldjust;
+
+ if (settext != NULL) {
+
+ if (mode == 1)
+ newjust = (settext->justify & (NONJUSTFIELD | TBJUSTFIELD))
+ | value;
+ else
+ newjust = (settext->justify & (NONJUSTFIELD | RLJUSTFIELD))
+ | value;
+
+ if (settext->justify != newjust) {
+ oldjust = (int)settext->justify;
+ undrawtext(settext);
+ settext->justify = newjust;
+ redrawtext(settext);
+ pwriteback(areawin->topinstance);
+
+ register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance,
+ (genericptr)settext, oldjust);
+ }
+ }
+ else {
+ if (mode == 1)
+ newjust = (areawin->justify & (NONJUSTFIELD | TBJUSTFIELD))
+ | value;
+ else
+ newjust = (areawin->justify & (NONJUSTFIELD | RLJUSTFIELD))
+ | value;
+ areawin->justify = newjust;
+ }
+ if (w != NULL) togglejustifs(w);
+}
+
+/*----------------------------------------------------------------*/
+/* Set vertical justification (top, middle, bottom) on all */
+/* selected labels */
+/*----------------------------------------------------------------*/
+
+void setvjust(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setjust(w, value, settext, 2);
+ }
+ else {
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setjust(NULL, value, settext, 2);
+ }
+ }
+ if (labelcount == 0) setjust(w, value, NULL, 2);
+ else unselect_all();
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set horizontal justification (left, center, right) on all */
+/* selected labels */
+/*----------------------------------------------------------------*/
+
+void sethjust(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setjust(w, value, settext, 1);
+ }
+ else {
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setjust(NULL, value, settext, 1);
+ }
+ }
+ if (labelcount == 0) setjust(w, value, NULL, 1);
+ else unselect_all();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Set a justify field bit on all selected labels */
+/* (flip invariance, latex mode, etc.) */
+/*--------------------------------------------------------------*/
+
+void setjustbit(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ dojustifybit(w, settext, (short)value);
+ }
+ else {
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ dojustifybit(NULL, settext, (short)value);
+ }
+ }
+ if (labelcount == 0) dojustifybit(w, NULL, (short)value);
+ else unselect_all();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Set pin-related bit field of "justify" on all selected pins */
+/* (e.g., pin visibility) */
+/*--------------------------------------------------------------*/
+
+void setpinjustbit(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ if (settext->pin)
+ dopinjustbit(w, settext, (short)value);
+ }
+ else {
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ settext = SELTOLABEL(fselect);
+ if (settext->pin)
+ dopinjustbit(NULL, settext, (short)value);
+ }
+ }
+ unselect_all();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Enable or Disable the toolbar */
+/*--------------------------------------------------------------*/
+
+#ifdef HAVE_XPM
+void dotoolbar(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ Arg wargs[1];
+
+ if (areawin->toolbar_on) {
+ areawin->toolbar_on = False;
+ XtUnmanageChild(toolbar);
+ XtSetArg(wargs[0], XtNlabel, "Enable Toolbar");
+ XtSetValues(OptionsDisableToolbarButton, wargs, 1);
+ XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
+ }
+ else {
+ areawin->toolbar_on = True;
+ XtManageChild(toolbar);
+ XtSetArg(wargs[0], XtNlabel, "Disable Toolbar");
+ XtSetValues(OptionsDisableToolbarButton, wargs, 1);
+ XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Overwrite the toolbar pixmap for color or stipple entries */
+/*--------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void overdrawpixmap(xcWidget button)
+{
+ xcWidget pbutton;
+ Arg args[3];
+ int ltype, color;
+ Pixmap stippix;
+
+ if (button == NULL) return;
+
+ XtSetArg(args[0], XtNlabelType, &ltype);
+ XtGetValues(button, args, 1);
+
+ if (ltype != XwRECT && button != ColorInheritColorButton) return;
+
+ XtSetArg(args[0], XtNrectColor, &color);
+ XtSetArg(args[1], XtNrectStipple, &stippix);
+ XtGetValues(button, args, 2);
+
+ if (stippix == (Pixmap)NULL && button != FillBlackButton)
+ pbutton = ColorsToolButton;
+ else
+ pbutton = FillsToolButton;
+
+ if (button == ColorInheritColorButton) {
+ XtSetArg(args[0], XtNlabelType, XwIMAGE);
+ XtSetValues(pbutton, args, 1);
+ }
+ else if (button == FillBlackButton) {
+ XtSetArg(args[0], XtNlabelType, XwRECT);
+ XtSetArg(args[1], XtNrectColor, color);
+ XtSetArg(args[2], XtNrectStipple, (Pixmap)NULL);
+ XtSetValues(pbutton, args, 3);
+ }
+ else if (button != FillOpaqueButton) {
+ XtSetArg(args[0], XtNlabelType, XwRECT);
+ if (stippix == (Pixmap)NULL)
+ XtSetArg(args[1], XtNrectColor, color);
+ else
+ XtSetArg(args[1], XtNrectStipple, stippix);
+
+ XtSetValues(pbutton, args, 2);
+ }
+}
+
+#endif
+
+#else
+#define overdrawpixmap(a)
+#endif /* XPM */
+
+/*--------------------------------------------------------------*/
+/* Generic routine for use by all other data handling routines */
+/*--------------------------------------------------------------*/
+
+buttonsave *getgeneric(xcWidget button, void (*getfunction)(), void *dataptr)
+{
+ Arg wargs[1];
+ buttonsave *saveptr;
+
+ saveptr = (buttonsave *)malloc(sizeof(buttonsave));
+ saveptr->button = button;
+ saveptr->buttoncall = getfunction;
+ saveptr->dataptr = dataptr;
+
+ if (button != NULL) {
+ XtSetArg(wargs[0], XtNforeground, &saveptr->foreground);
+ XtGetValues(button, wargs, 1);
+ XtSetArg(wargs[0], XtNforeground, OFFBUTTONCOLOR);
+ XtSetValues(button, wargs, 1);
+ XtRemoveAllCallbacks(button, XtNselect);
+ }
+ return saveptr;
+}
+
+/*--------------------------------------------------------------*/
+/* Generate popup dialog for snap space value input */
+/*--------------------------------------------------------------*/
+
+void getsnapspace(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ float *floatptr = &xobjs.pagelist[areawin->page]->snapspace;
+
+ savebutton = getgeneric(button, getsnapspace, (void *)floatptr);
+ measurestr(*floatptr, buffer);
+ popupprompt(button, "Enter value:", buffer, setgrid, savebutton, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Generate popup dialog for grid space value input */
+/*--------------------------------------------------------------*/
+
+void getgridspace(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ float *floatptr = &xobjs.pagelist[areawin->page]->gridspace;
+
+ savebutton = getgeneric(button, getgridspace, (void *)floatptr);
+ measurestr(*floatptr, buffer);
+ popupprompt(button, "Enter value:", buffer, setgrid, savebutton, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Generic routine for setting a floating-point value (through a */
+/* (float *) pointer passed as the second parameter) */
+/*----------------------------------------------------------------*/
+
+void setfloat(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ int res = sscanf(_STR2, "%f", dataptr);
+
+ if (res == 0 || *dataptr <= 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set text scale. */
+/*----------------------------------------------------------------*/
+
+void settsize(xcWidget w, labelptr settext)
+{
+ float tmpres;
+
+ int res = sscanf(_STR2, "%f", &tmpres);
+
+ if (res == 0 || tmpres <= 0) { /* can't interpret value or bad value */
+ Wprintf("Illegal value");
+ return;
+ }
+ changetextscale(tmpres);
+
+ if (areawin->selects > 0) unselect_all();
+}
+
+/*--------------------------------------------------------------*/
+/* Auto-set: Enable automatic scaling */
+/*--------------------------------------------------------------*/
+
+void autoset(xcWidget w, xcWidgetList entertext, caddr_t nulldata)
+{
+ xobjs.pagelist[areawin->page]->pmode |= 2;
+ updatetext(w, entertext, nulldata);
+}
+
+/*--------------------------------------------------------------*/
+
+void autostop(xcWidget w, caddr_t clientdata, caddr_t nulldata)
+{
+ xobjs.pagelist[areawin->page]->pmode &= 1;
+}
+
+/*--------------------------------------------------------------*/
+/* Set the denomenator value of the drawing scale */
+/*--------------------------------------------------------------*/
+
+void setscaley(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ int res = sscanf(_STR2, "%f", dataptr);
+
+ if (res == 0 || *dataptr <= 0 || topobject->bbox.height == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else {
+ *dataptr = (*dataptr * 72) / topobject->bbox.height;
+ *dataptr /= getpsscale(1.0, areawin->page);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the numerator value of the drawing scale */
+/*----------------------------------------------------------------*/
+
+void setscalex(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ int res = sscanf(_STR2, "%f", dataptr);
+
+ if (res == 0 || *dataptr <= 0 || topobject->bbox.width == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else {
+ *dataptr = (*dataptr * 72) / topobject->bbox.width;
+ *dataptr /= getpsscale(1.0, areawin->page);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the page orientation (either Landscape or Portrait) */
+/*----------------------------------------------------------------*/
+
+void setorient(xcWidget w, short *dataptr)
+{
+ Arg wargs[1];
+
+ if (*dataptr == 0) {
+ *dataptr = 90;
+ XtSetArg(wargs[0], XtNlabel, "Landscape");
+ }
+ else {
+ *dataptr = 0;
+ XtSetArg(wargs[0], XtNlabel, "Portrait");
+ }
+ XtSetValues(w, wargs, 1);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the output mode to "Full Page" (unencapsulated PostScript) */
+/* or "Embedded" (encapsulated PostScript) */
+/*----------------------------------------------------------------*/
+
+void setpmode(xcWidget w, short *dataptr)
+{
+ Arg wargs[1];
+ xcWidget pwidg = XtParent(w);
+ xcWidget autowidg = XtNameToWidget(pwidg, "Auto-fit");
+
+ if (!(*dataptr & 1)) {
+ *dataptr = 1;
+ XtSetArg(wargs[0], XtNlabel, "Full Page");
+
+ XtManageChild(XtNameToWidget(pwidg, "fpedit"));
+ XtManageChild(XtNameToWidget(pwidg, "fpokay"));
+ XtManageChild(autowidg);
+ }
+ else {
+ *dataptr = 0; /* This also turns off auto-fit */
+ XtSetArg(wargs[0], XtNset, False);
+ XtSetValues(autowidg, wargs, 1);
+ XtSetArg(wargs[0], XtNlabel, "Embedded");
+
+ XtUnmanageChild(XtNameToWidget(pwidg, "fpedit"));
+ XtUnmanageChild(XtNameToWidget(pwidg, "fpokay"));
+ XtUnmanageChild(autowidg);
+ }
+ XtSetValues(w, wargs, 1);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the output page size, in the current unit of measure */
+/*--------------------------------------------------------------*/
+
+void setpagesize(xcWidget w, XPoint *dataptr)
+{
+ char fpedit[75];
+ Arg wargs[1];
+ Boolean is_inches;
+
+ is_inches = setoutputpagesize(dataptr);
+ sprintf(fpedit, "%3.2f x %3.2f %s",
+ (float)xobjs.pagelist[areawin->page]->pagesize.x / 72.0,
+ (float)xobjs.pagelist[areawin->page]->pagesize.y / 72.0,
+ (is_inches) ? "in" : "cm");
+
+ XtSetArg(wargs[0], XtNstring, fpedit);
+ XtSetValues(XtNameToWidget(XtParent(w), "fpedit"), wargs, 1);
+}
+
+/*--------------------------------------------------------------*/
+/* Generate popup dialog to get a character kern value, which */
+/* is two integer numbers in the range -128 to +127 (size char) */
+/*--------------------------------------------------------------*/
+
+void getkern(xcWidget button, caddr_t nulldata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ int kx, ky;
+ stringpart *strptr, *nextptr;
+
+ strcpy(buffer, "0,0");
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ labelptr curlabel = TOLABEL(EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
+ areawin->topinstance);
+ if (strptr->type == KERN) {
+ kx = strptr->data.kern[0];
+ ky = strptr->data.kern[1];
+ sprintf(buffer, "%d,%d", kx, ky);
+ }
+ else if (nextptr && nextptr->type == KERN) {
+ strptr = nextptr;
+ kx = strptr->data.kern[0];
+ ky = strptr->data.kern[1];
+ sprintf(buffer, "%d,%d", kx, ky);
+ }
+ else strptr = NULL;
+ }
+
+ savebutton = getgeneric(button, getkern, strptr);
+ popupprompt(button, "Enter Kern X,Y:", buffer, setkern, savebutton, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Generate popup dialog to get the drawing scale, specified as a */
+/* whole-number ratio X:Y */
+/*----------------------------------------------------------------*/
+
+void getdscale(xcWidget button, caddr_t nulldata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ XPoint *ptptr = &(xobjs.pagelist[areawin->page]->drawingscale);
+
+ savebutton = getgeneric(button, getdscale, ptptr);
+ sprintf(buffer, "%d:%d", ptptr->x, ptptr->y);
+ popupprompt(button, "Enter Scale:", buffer, setdscale, savebutton, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Generate the popup dialog for getting text scale. */
+/*--------------------------------------------------------------*/
+
+void gettsize(xcWidget button, caddr_t nulldata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ float *floatptr;
+ Boolean local;
+ labelptr settext;
+
+ settext = gettextsize(&floatptr);
+ sprintf(buffer, "%5.2f", *floatptr);
+
+ if (settext) {
+ savebutton = getgeneric(button, gettsize, settext);
+ popupprompt(button, "Enter text scale:", buffer, settsize, savebutton, NULL);
+ }
+ else {
+ savebutton = getgeneric(button, gettsize, floatptr);
+ popupprompt(button,
+ "Enter default text scale:", buffer, setfloat, savebutton, NULL);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Generate popup dialog for getting object scale */
+/*----------------------------------------------------------------*/
+
+void getosize(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ char buffer[50];
+ float flval;
+ buttonsave *savebutton;
+ short *osel = areawin->selectlist;
+ short selects = 0;
+ objinstptr setobj = NULL;
+
+ for (; osel < areawin->selectlist + areawin->selects; osel++)
+ if (SELECTTYPE(osel) == OBJINST) {
+ setobj = SELTOOBJINST(osel);
+ selects++;
+ break;
+ }
+ if (setobj == NULL) {
+ Wprintf("No objects were selected for scaling.");
+ return;
+ }
+ flval = setobj->scale;
+ savebutton = getgeneric(button, getosize, setobj);
+ sprintf(buffer, "%4.2f", flval);
+ popupprompt(button, "Enter object scale:", buffer, setosize, savebutton, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Generate popup prompt for getting global linewidth */
+/*----------------------------------------------------------------*/
+
+void getwirewidth(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ float *widthptr;
+
+ widthptr = &(xobjs.pagelist[areawin->page]->wirewidth);
+ savebutton = getgeneric(button, getwirewidth, widthptr);
+ sprintf(buffer, "%4.2f", *widthptr / 2.0);
+ popupprompt(button, "Enter new global linewidth:", buffer, setwidth,
+ savebutton, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Generate popup dialong for getting linewidths of elements */
+/*----------------------------------------------------------------*/
+
+void getwwidth(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+ short *osel = areawin->selectlist;
+ genericptr setel;
+ float flval;
+
+ for (; osel < areawin->selectlist + areawin->selects; osel++) {
+ setel = *(topobject->plist + (*osel));
+ if (IS_ARC(setel)) {
+ flval = ((arcptr)setel)->width;
+ break;
+ }
+ else if (IS_POLYGON(setel)) {
+ flval = ((polyptr)setel)->width;
+ break;
+ }
+ else if (IS_SPLINE(setel)) {
+ flval = ((splineptr)setel)->width;
+ break;
+ }
+ else if (IS_PATH(setel)) {
+ flval = ((pathptr)setel)->width;
+ break;
+ }
+ }
+ savebutton = getgeneric(button, getwwidth, setel);
+ if (osel == areawin->selectlist + areawin->selects) {
+ sprintf(buffer, "%4.2f", areawin->linewidth);
+ popupprompt(button, "Enter new default line width:", buffer, setwwidth,
+ savebutton, NULL);
+ }
+ else {
+ sprintf(buffer, "%4.2f", flval);
+ popupprompt(button, "Enter new line width:", buffer, setwwidth,
+ savebutton, NULL);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Generic popup prompt for getting a floating-point value */
+/*----------------------------------------------------------------*/
+
+void getfloat(xcWidget button, float *floatptr, caddr_t calldata)
+{
+ char buffer[50];
+ buttonsave *savebutton;
+
+ savebutton = getgeneric(button, getfloat, floatptr);
+ sprintf(buffer, "%4.2f", *floatptr);
+ popupprompt(button, "Enter value:", buffer, setfloat, savebutton, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the filename for the current page */
+/*----------------------------------------------------------------*/
+
+void setfilename(xcWidget w, char **dataptr)
+{
+ short cpage, depend = 0;
+ objectptr checkpage;
+ char *oldstr = xobjs.pagelist[areawin->page]->filename;
+
+ if ((*dataptr != NULL) && !strcmp(*dataptr, _STR2))
+ return; /* no change in string */
+
+ /* Make the change to the current page */
+ xobjs.pagelist[areawin->page]->filename = strdup(_STR2);
+
+ /* All existing filenames which match the old string should also be changed */
+ for (cpage = 0; cpage < xobjs.pages; cpage++) {
+ if ((xobjs.pagelist[cpage]->pageinst != NULL) && (cpage != areawin->page)) {
+ if ((oldstr != NULL) && (!strcmp(xobjs.pagelist[cpage]->filename, oldstr))) {
+ free(xobjs.pagelist[cpage]->filename);
+ xobjs.pagelist[cpage]->filename = strdup(_STR2);
+ }
+ }
+ }
+ free(oldstr);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the page label for the current page */
+/*----------------------------------------------------------------*/
+
+void setpagelabel(xcWidget w, char *dataptr)
+{
+ short i;
+
+ /* Whitespace and non-printing characters not allowed */
+
+ for (i = 0; i < strlen(_STR2); i++) {
+ if ((!isprint(_STR2[i])) || (isspace(_STR2[i]))) {
+ _STR2[i] = '_';
+ Wprintf("Replaced illegal whitespace in name with underscore");
+ }
+ }
+
+ if (!strcmp(dataptr, _STR2)) return; /* no change in string */
+ if (strlen(_STR2) == 0)
+ sprintf(topobject->name, "Page %d", areawin->page + 1);
+ else
+ sprintf(topobject->name, "%.79s", _STR2);
+
+ /* For schematics, all pages with associations to symbols must have */
+ /* unique names. */
+ if (topobject->symschem != NULL) checkpagename(topobject);
+
+ printname(topobject);
+ renamepage(areawin->page);
+}
+
+/*--------------------------------------------------------------*/
+/* Change the Button1 binding for a particular mode (non-Tcl) */
+/*--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------*/
+/* Change to indicated tool (key binding w/o value) */
+/*--------------------------------------------------------------*/
+
+void changetool(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ mode_rebinding((int)value, (short)-1);
+ highlightexcl(w, (int)value, (int)-1);
+}
+
+/*--------------------------------------------------------------*/
+/* Execute function binding for the indicated tool if something */
+/* is selected; otherwise, change to the indicated tool mode. */
+/*--------------------------------------------------------------*/
+
+void exec_or_changetool(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ if (areawin->selects > 0)
+ mode_tempbinding((int)value, -1);
+ else {
+ mode_rebinding((int)value, -1);
+ highlightexcl(w, (int)value, -1);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Special case of exec_or_changetool(), where an extra value */
+/* is passed to the routine indication amount of rotation, or */
+/* type of flip operation. */
+/*--------------------------------------------------------------*/
+
+void rotatetool(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ if (areawin->selects > 0)
+ mode_tempbinding(XCF_Rotate, (int)value);
+ else {
+ mode_rebinding(XCF_Rotate, (int)value);
+ highlightexcl(w, (int)XCF_Rotate, (int)value);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Special case of changetool() for pan mode, where a value is */
+/* required to pass to the key binding routine. */
+/*--------------------------------------------------------------*/
+
+void pantool(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ mode_rebinding(XCF_Pan, (int)value);
+ highlightexcl(w, (int)XCF_Pan, (int)value);
+}
+
+/*--------------------------------------------------------------*/
+/* Add a new font name to the list of known fonts */
+/* Register the font number for the Alt-F cycling mechanism */
+/* Tcl: depends on command tag mechanism for GUI menu update. */
+/*--------------------------------------------------------------*/
+
+void makenewfontbutton()
+{
+
+ Arg wargs[1];
+ int n = 0;
+ xcWidget newbutton, cascade;
+
+ if (fontcount == 0) return;
+
+ cascade = XtParent(FontAddNewFontButton);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ newbutton = XtCreateWidget(fonts[fontcount - 1].family, XwmenubuttonWidgetClass,
+ cascade, wargs, n);
+
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setfont,
+ Number(fontcount - 1));
+ XtManageChild(newbutton);
+
+ nfontnumbers++;
+ if (nfontnumbers == 1)
+ fontnumbers = (u_short *)malloc(sizeof(u_short));
+ else
+ fontnumbers = (u_short *)realloc(fontnumbers, nfontnumbers
+ * sizeof(u_short));
+ fontnumbers[nfontnumbers - 1] = fontcount - 1;
+}
+
+/*--------------------------------------------------------------*/
+/* Make new encoding menu button */
+/*--------------------------------------------------------------*/
+
+void makenewencodingbutton(char *ename, char value)
+{
+ Arg wargs[1];
+ int n = 0;
+ xcWidget newbutton, cascade;
+
+ cascade = XtParent(EncodingStandardButton);
+
+ /* return if button has already been made */
+ newbutton = XtNameToWidget(cascade, ename);
+ if (newbutton != NULL) return;
+
+ XtnSetArg(XtNfont, appdata.xcfont);
+ newbutton = XtCreateWidget(ename, XwmenubuttonWidgetClass,
+ cascade, wargs, n);
+
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setfontencoding,
+ Number(value));
+ XtManageChild(newbutton);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the font menu */
+/*--------------------------------------------------------------*/
+
+void togglefontmark(int fontval)
+{
+ Arg args[1];
+ xcWidget widget, cascade, sibling;
+ short i;
+
+ cascade = XtParent(FontAddNewFontButton);
+ widget = XtNameToWidget(cascade, fonts[fontval].family);
+
+ /* Remove checkmark from all widgets in the list */
+
+ XtSetArg(args[0], XtNsetMark, False);
+ for (i = 0; i < fontcount; i++) {
+ if (i != fontval) {
+ sibling = XtNameToWidget(cascade, fonts[i].family);
+ XtSetValues(sibling, args, 1);
+ }
+ }
+
+ /* Add checkmark to designated font */
+
+ XtSetArg(args[0], XtNsetMark, True);
+ XtSetValues(widget, args, 1);
+}
+
+/*--------------------------------------------------------------------*/
+/* Toggle one of a set of menu items, only one of which can be active */
+/*--------------------------------------------------------------------*/
+
+void toggleexcl(xcWidget widget, menuptr menu, int menulength)
+{
+ Arg args[1];
+ xcWidget parent = xcParent(widget);
+ xcWidget sibling;
+ menuptr mitem, mtest;
+ short i;
+
+ /* find the menu item which corresponds to the widget which was pushed */
+
+ for (mtest = menu; mtest < menu + menulength; mtest++) {
+ sibling = XtNameToWidget(parent, mtest->name);
+ if (sibling == widget) break;
+ }
+
+ /* remove checkmark from other widgets in the list */
+
+ XtSetArg(args[0], XtNsetMark, False);
+ if (menu == Fonts) { /* special action for font list */
+ for (i = 0; i < fontcount; i++) {
+ sibling = XtNameToWidget(parent, fonts[i].family);
+ if (sibling != widget)
+ XtSetValues(sibling, args, 1);
+ }
+ mtest = &Fonts[3]; /* so that mtest->func has correct value below */
+ }
+ else if (mtest == menu + menulength) return; /* something went wrong? */
+
+ for (mitem = menu; mitem < menu + menulength; mitem++) {
+ sibling = XtNameToWidget(parent, mitem->name);
+ if (mitem->func == mtest->func)
+ XtSetValues(sibling, args, 1);
+ }
+
+ /* Now set the currently pushed widget */
+
+ XtSetArg(args[0], XtNsetMark, True);
+ XtSetValues(widget, args, 1);
+}
+
+/*----------------------------------------------------------------------*/
+/* Cursor changes based on toolbar mode */
+/*----------------------------------------------------------------------*/
+
+void toolcursor(int mode)
+{
+ /* Some cursor types for different modes */
+ switch(mode) {
+ case XCF_Spline:
+ case XCF_Move:
+ case XCF_Join:
+ case XCF_Unjoin:
+ XDefineCursor (dpy, areawin->window, ARROW);
+ areawin->defaultcursor = &ARROW;
+ break;
+ case XCF_Pan:
+ XDefineCursor (dpy, areawin->window, HAND);
+ areawin->defaultcursor = &HAND;
+ break;
+ case XCF_Delete:
+ XDefineCursor (dpy, areawin->window, SCISSORS);
+ areawin->defaultcursor = &SCISSORS;
+ break;
+ case XCF_Copy:
+ XDefineCursor (dpy, areawin->window, COPYCURSOR);
+ areawin->defaultcursor = &COPYCURSOR;
+ break;
+ case XCF_Push:
+ case XCF_Select_Save:
+ XDefineCursor (dpy, areawin->window, QUESTION);
+ areawin->defaultcursor = &QUESTION;
+ break;
+ case XCF_Rotate:
+ case XCF_Flip_X:
+ case XCF_Flip_Y:
+ XDefineCursor (dpy, areawin->window, ROTATECURSOR);
+ areawin->defaultcursor = &ROTATECURSOR;
+ break;
+ case XCF_Edit:
+ XDefineCursor (dpy, areawin->window, EDCURSOR);
+ areawin->defaultcursor = &EDCURSOR;
+ break;
+ case XCF_Arc:
+ XDefineCursor (dpy, areawin->window, CIRCLE);
+ areawin->defaultcursor = &CIRCLE;
+ break;
+ case XCF_Text:
+ case XCF_Pin_Label:
+ case XCF_Pin_Global:
+ case XCF_Info_Label:
+ XDefineCursor (dpy, areawin->window, TEXTPTR);
+ areawin->defaultcursor = &TEXTPTR;
+ break;
+ default:
+ XDefineCursor (dpy, areawin->window, CROSS);
+ areawin->defaultcursor = &CROSS;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+/* Highlight one of a set of toolbar items, only one of which can be active */
+/*--------------------------------------------------------------------------*/
+
+void highlightexcl(xcWidget widget, int func, int value)
+{
+ Arg args[2];
+ xcWidget parent = xcParent(PanToolButton);
+ xcWidget sibling, self = (xcWidget)NULL;
+ toolbarptr titem, ttest;
+
+ /* remove highlight from all widgets in the toolbar */
+
+ XtSetArg(args[0], XtNbackground, BACKGROUND);
+ XtSetArg(args[1], XtNborderColor, SNAPCOLOR);
+ for (titem = ToolBar; titem < ToolBar + toolbuttons; titem++) {
+ sibling = XtNameToWidget(parent, titem->name);
+ if (sibling == widget)
+ self = sibling;
+ else
+ XtSetValues(sibling, args, 2);
+ }
+
+ if (self == (xcWidget)NULL) {
+ /* We invoked a toolbar button from somewhere else. Highlight */
+ /* the toolbar associated with the function value. */
+ switch (func) {
+ case XCF_Pan:
+ self = PanToolButton;
+ break;
+
+ case XCF_Rotate:
+ if (value > 0)
+ self = RotPToolButton;
+ else
+ self = RotNToolButton;
+ break;
+
+ default:
+ for (titem = ToolBar; titem < ToolBar + toolbuttons; titem++) {
+ if (func == (pointertype)(titem->passeddata)) {
+ self = XtNameToWidget(parent, titem->name);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ /* Now highlight the currently pushed widget */
+
+ if (self != (xcWidget)NULL) {
+ XtSetArg(args[0], XtNbackground, RATSNESTCOLOR);
+ XtSetArg(args[1], XtNborderColor, RATSNESTCOLOR);
+ XtSetValues(self, args, 2);
+ }
+}
+
+/*--------------------*/
+/* Toggle a menu item */
+/*--------------------*/
+
+void toggle(xcWidget w, pointertype soffset, Boolean *setdata)
+{
+ Arg wargs[1];
+ Boolean *boolvalue;
+
+ if (soffset == -1)
+ boolvalue = setdata;
+ else
+ boolvalue = (Boolean *)(areawin + soffset);
+
+ *boolvalue = !(*boolvalue);
+ XtSetArg(wargs[0], XtNsetMark, *boolvalue);
+ XtSetValues(w, wargs, 1);
+ drawarea(w, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Invert the color scheme used for the background/foreground */
+/*----------------------------------------------------------------*/
+
+void inversecolor(xcWidget w, pointertype soffset, caddr_t calldata)
+{
+ Boolean *boolvalue = (Boolean *)(areawin + soffset);
+
+ /* change color scheme */
+
+ setcolorscheme(*boolvalue);
+
+ /* toggle checkmark in menu on "Alt colors" */
+
+ if (w == NULL) w = OptionsAltColorsButton;
+ if (w != NULL) toggle(w, soffset, calldata);
+ if (eventmode == NORMAL_MODE)
+ XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
+}
+
+/*----------------------------------------------------------------*/
+/* Change menu selection for reported measurement units */
+/*----------------------------------------------------------------*/
+
+void togglegrid(u_short type)
+{
+ xcWidget button, bparent = XtParent(GridtypedisplayDecimalInchesButton);
+
+ if (type == CM) button = XtNameToWidget(bparent, "Centimeters");
+ else if (type == FRAC_INCH) button = XtNameToWidget(bparent, "Fractional Inches");
+ else if (type == DEC_INCH) button = XtNameToWidget(bparent, "Decimal Inches");
+ else if (type == INTERNAL) button = XtNameToWidget(bparent, "Internal Units");
+ else button = XtNameToWidget(bparent, "Coordinates");
+ if (button) {
+ toggleexcl(button, GridStyles, XtNumber(GridStyles));
+ W1printf(" ");
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the default reported grid units to inches or centimeters */
+/*----------------------------------------------------------------*/
+
+void setgridtype(char *string)
+{
+ xcWidget button, bparent = XtParent(GridtypedisplayDecimalInchesButton);
+
+ if (!strcmp(string, "inchscale")) {
+ button = XtNameToWidget(bparent, "Fractional Inches");
+ getgridtype(button, FRAC_INCH, NULL);
+ }
+ else if (!strcmp(string, "cmscale")) {
+ button = XtNameToWidget(bparent, "Centimeters");
+ getgridtype(button, CM, NULL);
+ }
+}
+
+/*----------------------------------------------*/
+/* Make new library and add a new button to the */
+/* "Libraries" cascaded menu. */
+/*----------------------------------------------*/
+
+int createlibrary(Boolean force)
+{
+ xcWidget libmenu, newbutton, oldbutton;
+ Arg wargs[2];
+ char libstring[20];
+ int libnum;
+ objectptr newlibobj;
+
+ /* If there's an empty library, return its number */
+ if ((!force) && (libnum = findemptylib()) >= 0) return (libnum + LIBRARY);
+ libnum = (xobjs.numlibs++) + LIBRARY;
+ xobjs.libtop = (objinstptr *)realloc(xobjs.libtop,
+ (libnum + 1) * sizeof(objinstptr));
+ xobjs.libtop[libnum] = xobjs.libtop[libnum - 1];
+ libnum--;
+
+ newlibobj = (objectptr) malloc(sizeof(object));
+ initmem(newlibobj);
+ xobjs.libtop[libnum] = newpageinst(newlibobj);
+
+ sprintf(newlibobj->name, "Library %d", libnum - LIBRARY + 1);
+
+ /* Create the library */
+
+ xobjs.userlibs = (Library *) realloc(xobjs.userlibs, xobjs.numlibs
+ * sizeof(Library));
+ xobjs.userlibs[libnum + 1 - LIBRARY] = xobjs.userlibs[libnum - LIBRARY];
+ xobjs.userlibs[libnum - LIBRARY].library = (objectptr *) malloc(sizeof(objectptr));
+ xobjs.userlibs[libnum - LIBRARY].number = 0;
+ xobjs.userlibs[libnum - LIBRARY].instlist = NULL;
+
+ /* To-do: initialize technology list */
+ /*
+ xobjs.userlibs[libnum - LIBRARY].filename = NULL;
+ xobjs.userlibs[libnum - LIBRARY].flags = (char)0;
+ */
+
+ /* Previously last button becomes new library pointer */
+
+ oldbutton = GotoLibraryLibrary2Button;
+ XtRemoveAllCallbacks (oldbutton, XtNselect);
+ XtAddCallback (oldbutton, XtNselect, (XtCallbackProc)startcatalog,
+ Number(libnum));
+ XtSetArg(wargs[0], XtNlabel, xobjs.libtop[libnum]->thisobject->name);
+ XtSetValues(oldbutton, wargs, 1);
+
+ /* Make new entry in the menu to replace the User Library button */
+ /* xcWidget name is unique so button can be found later. Label is */
+ /* always set to "User Library" */
+
+ sprintf(libstring, "Library %d", libnum - LIBRARY + 2);
+ libmenu = XtParent(GotoLibraryAddNewLibraryButton);
+ XtSetArg(wargs[0], XtNfont, appdata.xcfont);
+ XtSetArg(wargs[1], XtNlabel, "User Library");
+ newbutton = XtCreateWidget(libstring, XwmenubuttonWidgetClass,
+ libmenu, wargs, 2);
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)startcatalog,
+ Number(libnum + 1));
+ XtManageChild(newbutton);
+ GotoLibraryLibrary2Button = newbutton;
+
+ /* Update the library directory to include the new page */
+
+ composelib(LIBLIB);
+
+ return libnum;
+}
+
+/*--------------------------------------------------------------*/
+/* Routine called by newpage() if new button needs to be made */
+/* to add to the "Pages" cascaded menu. */
+/*--------------------------------------------------------------*/
+
+void makepagebutton()
+{
+ xcWidget pagemenu, newbutton;
+ Arg wargs[1];
+ char pagestring[10];
+
+ /* make new entry in the menu */
+
+ pagemenu = XtParent(GotoPageAddNewPageButton);
+ XtSetArg(wargs[0], XtNfont, appdata.xcfont);
+ sprintf(pagestring, "Page %d", xobjs.pages);
+ newbutton = XtCreateWidget(pagestring, XwmenubuttonWidgetClass,
+ pagemenu, wargs, 1);
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)newpagemenu,
+ Number(xobjs.pages - 1));
+ XtManageChild(newbutton);
+
+ /* Update the page directory */
+
+ composelib(PAGELIB);
+}
+
+/*----------------------------------------------------------------*/
+/* Find the Page menu button associated with the page number */
+/* (passed parameter) and set the label of that button to the */
+/* object name (= page label) */
+/*----------------------------------------------------------------*/
+
+void renamepage(short pagenumber)
+{
+ int page;
+ objinstptr thisinst = xobjs.pagelist[pagenumber]->pageinst;
+ Arg wargs[1];
+ xcWidget parent = XtParent(GotoPageAddNewPageButton);
+ xcWidget button;
+ char bname[10];
+
+ sprintf(bname, "Page %d", pagenumber + 1);
+ button = XtNameToWidget(parent, bname);
+
+ if ((button != NULL) && (thisinst != NULL)) {
+ if (thisinst->thisobject->name != NULL)
+ XtSetArg(wargs[0], XtNlabel,
+ thisinst->thisobject->name);
+ else
+ XtSetArg(wargs[0], XtNlabel, bname);
+ XtSetValues(button, wargs, 1);
+ }
+ else if (button == NULL)
+ Fprintf(stderr, "Error: No Button Widget named \"%9s\"\n", bname);
+}
+
+/*--------------------------------------------------------------*/
+/* Same routine as above, for Library page menu buttons */
+/*--------------------------------------------------------------*/
+
+void renamelib(short libnumber)
+{
+ Arg wargs[1];
+ xcWidget parent = XtParent(GotoLibraryAddNewLibraryButton);
+ xcWidget button;
+ char bname[13];
+
+ sprintf(bname, "Library %d", libnumber - LIBRARY + 1);
+ button = XtNameToWidget(parent, bname);
+
+ if (button != NULL) {
+ if (xobjs.libtop[libnumber]->thisobject->name != NULL)
+ XtSetArg(wargs[0], XtNlabel, xobjs.libtop[libnumber]->thisobject->name);
+ else
+ XtSetArg(wargs[0], XtNlabel, bname);
+ XtSetValues(button, wargs, 1);
+ }
+ else
+ Fprintf(stderr, "Error: No Button Widget named \"%12s\"\n", bname);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the color menu */
+/*--------------------------------------------------------------*/
+
+void setcolormark(int colorval)
+{
+ Arg args[1];
+ xcWidget w = NULL;
+ short i;
+
+ if (colorval == DEFAULTCOLOR)
+ w = ColorInheritColorButton;
+ else {
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == colorval) {
+ w = colorlist[i].cbutton;
+ break;
+ }
+ }
+
+ /* Remove mark from all menu items */
+
+ XtSetArg(args[0], XtNsetMark, False);
+ for (i = 0; i < number_colors; i++)
+ XtSetValues(colorlist[i].cbutton, args, 1);
+ XtSetValues(ColorInheritColorButton, args, 1);
+
+ /* Add mark to the menu button for the chosen color */
+
+ if (w != (xcWidget)NULL) {
+ overdrawpixmap(w);
+ XtSetArg(args[0], XtNsetMark, True);
+ XtSetValues(w, args, 1);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the checkmarks on the element styles menu */
+/*----------------------------------------------------------------*/
+
+void setallstylemarks(u_short styleval)
+{
+ xcWidget w;
+ Arg wargs[1];
+
+ XtSetArg(wargs[0], XtNsetMark, (styleval & UNCLOSED) ? 0 : 1);
+ XtSetValues(BorderClosedButton, wargs, 1);
+
+ XtSetArg(wargs[0], XtNsetMark, (styleval & BBOX) ? 1 : 0);
+ XtSetValues(BorderBoundingBoxButton, wargs, 1);
+
+ if (styleval & NOBORDER)
+ w = BorderUnborderedButton;
+ else if (styleval & DASHED)
+ w = BorderDashedButton;
+ else if (styleval & DOTTED)
+ w = BorderDottedButton;
+ else
+ w = BorderSolidButton;
+ toggleexcl(w, BorderStyles, XtNumber(BorderStyles));
+
+ if (styleval & OPAQUE)
+ w = FillOpaqueButton;
+ else
+ w = FillTransparentButton;
+ toggleexcl(w, Stipples, XtNumber(Stipples));
+
+ if (!(styleval & FILLED))
+ w = FillWhiteButton;
+ else {
+ styleval &= FILLSOLID;
+ styleval /= STIP0;
+ switch(styleval) {
+ case 0: w = FillGray87Button; break;
+ case 1: w = FillGray75Button; break;
+ case 2: w = FillGray62Button; break;
+ case 3: w = FillGray50Button; break;
+ case 4: w = FillGray37Button; break;
+ case 5: w = FillGray25Button; break;
+ case 6: w = FillGray12Button; break;
+ case 7: w = FillBlackButton; break;
+ }
+ }
+ toggleexcl(w, Stipples, XtNumber(Stipples));
+}
+
+/*--------------------------------------------------------------*/
+/* The following five routines are all wrappers for */
+/* setelementstyle(), */
+/* used in menudefs to differentiate between sections, each of */
+/* which has settings independent of the others. */
+/*--------------------------------------------------------------*/
+
+void setfill(xcWidget w, pointertype value, caddr_t calldata)
+{
+ setelementstyle(w, (u_short)value, OPAQUE | FILLED | FILLSOLID);
+}
+
+/*--------------------------------------------------------------*/
+
+void makebbox(xcWidget w, pointertype value, caddr_t calldata)
+{
+ setelementstyle(w, (u_short)value, BBOX);
+}
+
+/*--------------------------------------------------------------*/
+
+void setclosure(xcWidget w, pointertype value, caddr_t calldata)
+{
+ setelementstyle(w, (u_short)value, UNCLOSED);
+}
+
+/*----------------------------------------------------------------*/
+
+void setopaque(xcWidget w, pointertype value, caddr_t calldata)
+{
+ setelementstyle(w, (u_short)value, OPAQUE);
+}
+
+/*----------------------------------------------------------------*/
+
+void setline(xcWidget w, pointertype value, caddr_t calldata)
+{
+ setelementstyle(w, (u_short)value, BORDERS);
+}
+
+/*-----------------------------------------------*/
+/* Set the color value for all selected elements */
+/*-----------------------------------------------*/
+
+void setcolor(xcWidget w, pointertype value, caddr_t calldata)
+{
+ short *scolor;
+ int *ecolor, cindex, cval;
+ Arg wargs[1];
+ Boolean selected = False;
+ stringpart *strptr, *nextptr;
+
+ /* Get the color index value from the menu button widget itself */
+
+ if (value == 1)
+ cindex = cval = -1;
+ else {
+ XtSetArg(wargs[0], XtNrectColor, &cval);
+ XtGetValues(w, wargs, 1);
+
+ for (cindex = 0; cindex < number_colors; cindex++)
+ if (colorlist[cindex].color.pixel == cval)
+ break;
+ if (cindex >= number_colors) {
+ Wprintf("Error: No such color!");
+ return;
+ }
+ }
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ labelptr curlabel = TOLABEL(EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ strptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else if (nextptr && nextptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ nextptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else {
+ sprintf(_STR2, "%d", cindex);
+ labeltext(FONT_COLOR, (char *)&cindex);
+ }
+ }
+
+ else if (areawin->selects > 0) {
+ for (scolor = areawin->selectlist; scolor < areawin->selectlist
+ + areawin->selects; scolor++) {
+ ecolor = &(SELTOCOLOR(scolor));
+
+ *ecolor = cval;
+ selected = True;
+ }
+ }
+
+ setcolormark(cval);
+ if (!selected) {
+ if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE)
+ areawin->color = cval;
+ overdrawpixmap(w);
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Parse a new color entry and add it to the color list. */
+/*----------------------------------------------------------------*/
+
+void setnewcolor(xcWidget w, caddr_t nullptr)
+{
+ int ccolor, red, green, blue;
+ char *ppos, *cpos;
+
+ ppos = strchr(_STR2, '#');
+ cpos = strchr(_STR2, ',');
+
+ if (cpos != NULL || ppos != NULL) {
+ if (cpos != NULL || strlen(ppos + 1) == 6) {
+ if (cpos != NULL)
+ sscanf(_STR2, "%d, %d, %d", &red, &green, &blue);
+ else
+ sscanf(ppos + 1, "%2x%2x%2x", &red, &green, &blue);
+ red *= 256;
+ green *= 256;
+ blue *= 256;
+ }
+ else if (sscanf(ppos + 1, "%4x%4x%4x", &red, &green, &blue) != 3) {
+ Wprintf("Bad color entry. Use #rrggbb");
+ return;
+ }
+ ccolor = rgb_alloccolor(red, green, blue);
+ }
+ else
+ ccolor = xc_alloccolor(_STR2);
+
+ addnewcolorentry(ccolor);
+}
+
+/*----------------------------------------------------------------*/
+/* Generate popup dialog for adding a new color name or RGB value */
+/*----------------------------------------------------------------*/
+
+void addnewcolor(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *savebutton;
+
+ savebutton = getgeneric(w, addnewcolor, NULL);
+ popupprompt(w, "Enter color name or #rgb or r,g,b:", "\0", setnewcolor,
+ savebutton, NULL);
+}
+
+/*------------------------------------------------------*/
+
+void setfontmarks(short fvalue, short jvalue)
+{
+ xcWidget w;
+ Arg wargs[1];
+
+ if ((fvalue >= 0) && (fontcount > 0)) {
+ switch(fonts[fvalue].flags & 0x03) {
+ case 0: w = StyleNormalButton; break;
+ case 1: w = StyleBoldButton; break;
+ case 2: w = StyleItalicButton; break;
+ case 3: w = StyleBoldItalicButton; break;
+ }
+ toggleexcl(w, FontStyles, XtNumber(FontStyles));
+
+ switch((fonts[fvalue].flags & 0xf80) >> 7) {
+ case 0: w = EncodingStandardButton; break;
+ case 2: w = EncodingISOLatin1Button; break;
+ default: w = NULL;
+ }
+ if (w != NULL) toggleexcl(w, FontEncodings, XtNumber(FontEncodings));
+
+ togglefontmark(fvalue);
+ }
+ if (jvalue >= 0) {
+ switch(jvalue & (RLJUSTFIELD)) {
+ case NORMAL: w = JustificationLeftJustifiedButton; break;
+ case NOTLEFT: w = JustificationCenterJustifiedButton; break;
+ case RIGHT|NOTLEFT: w = JustificationRightJustifiedButton; break;
+ }
+ toggleexcl(w, Justifs, XtNumber(Justifs));
+
+ switch(jvalue & (TBJUSTFIELD)) {
+ case NORMAL: w = JustificationBottomJustifiedButton; break;
+ case NOTBOTTOM: w = JustificationMiddleJustifiedButton; break;
+ case TOP|NOTBOTTOM: w = JustificationTopJustifiedButton; break;
+ }
+
+ toggleexcl(w, Justifs, XtNumber(Justifs));
+
+ /* Flip Invariance property */
+ w = JustificationFlipInvariantButton;
+ if (jvalue & FLIPINV)
+ XtSetArg(wargs[0], XtNsetMark, True);
+ else
+ XtSetArg(wargs[0], XtNsetMark, False);
+ XtSetValues(w, wargs, 1);
+
+ /* Pin visibility property */
+ w = NetlistPinVisibilityButton;
+ if (jvalue & PINVISIBLE)
+ XtSetArg(wargs[0], XtNsetMark, True);
+ else
+ XtSetArg(wargs[0], XtNsetMark, False);
+ XtSetValues(w, wargs, 1);
+ }
+}
+
+/*----------------------------------------------*/
+/* GUI wrapper for startparam() */
+/*----------------------------------------------*/
+
+void promptparam(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *popdata = (buttonsave *)malloc(sizeof(buttonsave));
+
+ if (areawin->selects == 0) return; /* nothing was selected */
+
+ /* Get a name for the new object */
+
+ eventmode = NORMAL_MODE;
+ popdata->dataptr = NULL;
+ popdata->button = NULL; /* indicates that no button is assc'd w/ the popup */
+ popupprompt(w, "Enter name for new parameter:", "\0", stringparam, popdata, NULL);
+}
+
+/*---------------------------*/
+/* Set polygon editing style */
+/*---------------------------*/
+
+void boxedit(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ if (w == NULL) {
+ switch (value) {
+ case MANHATTAN: w = PolygonEditManhattanBoxEditButton; break;
+ case RHOMBOIDX: w = PolygonEditRhomboidXButton; break;
+ case RHOMBOIDY: w = PolygonEditRhomboidYButton; break;
+ case RHOMBOIDA: w = PolygonEditRhomboidAButton; break;
+ case NORMAL: w = PolygonEditNormalButton; break;
+ }
+ }
+
+ if (areawin->boxedit == value) return;
+
+ toggleexcl(w, BoxEditStyles, XtNumber(BoxEditStyles));
+ areawin->boxedit = value;
+}
+
+/*----------------------------------------------------*/
+/* Generate popup dialog for entering a new font name */
+/*----------------------------------------------------*/
+
+void addnewfont(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *savebutton;
+ char *tempstr = malloc(2 * sizeof(char));
+ tempstr[0] = '\0';
+ savebutton = getgeneric(w, addnewfont, tempstr);
+ popupprompt(w, "Enter font name:", tempstr, locloadfont, savebutton, NULL);
+}
+
+/*-------------------------------------------------*/
+/* Wrapper for labeltext when called from the menu */
+/*-------------------------------------------------*/
+
+void addtotext(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE) return;
+ if (value == (pointertype)SPECIAL)
+ dospecial();
+ else
+ labeltext((int)value, (char *)1);
+}
+
+/*----------------------------------------------------------*/
+/* Position a popup menu directly beside the toolbar button */
+/*----------------------------------------------------------*/
+
+void position_popup(xcWidget toolbutton, xcWidget menubutton)
+{
+ int n = 0;
+ Arg wargs[2];
+ Position pz, pw, ph;
+ int dx, dy;
+
+ xcWidget cascade = XtParent(menubutton);
+ xcWidget pshell = XtParent(XtParent(cascade));
+
+ XtnSetArg(XtNheight, &pz);
+ XtGetValues(toolbutton, wargs, n); n = 0;
+
+ XtnSetArg(XtNwidth, &pw);
+ XtnSetArg(XtNheight, &ph);
+ XtGetValues(cascade, wargs, n); n = 0;
+
+ dx = -pw - 6;
+ dy = (pz - ph) >> 1;
+
+ XwPostPopup(pshell, cascade, toolbutton, dx, dy);
+}
+
+/*------------------------------------------------------*/
+/* Functions which pop up a menu cascade in sticky mode */
+/*------------------------------------------------------*/
+
+void border_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ position_popup(w, BorderLinewidthButton);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void color_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ position_popup(w, ColorAddNewColorButton);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void fill_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ position_popup(w, FillOpaqueButton);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void param_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ position_popup(w, ParametersSubstringButton);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#endif /* TCL_WRAPPER */
diff --git a/xtgui.c b/xtgui.c
new file mode 100644
index 0000000..5dc8ab7
--- /dev/null
+++ b/xtgui.c
@@ -0,0 +1,2086 @@
+/*----------------------------------------------------------------------*/
+/* xtgui.c --- */
+/* XCircuit's graphical user interface using the Xw widget set */
+/* (see directory Xw) (non-Tcl/Tk GUI) */
+/* Copyright (c) 2002 R. Timothy Edwards */
+/*----------------------------------------------------------------------*/
+
+#ifndef TCL_WRAPPER
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifndef XC_WIN32
+#include <unistd.h> /* for unlink() */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/Xproto.h>
+#include <X11/Xatom.h>
+
+#include "Xw/Xw.h"
+#include "Xw/Form.h"
+#include "Xw/WorkSpace.h"
+#include "Xw/PButton.h"
+#include "Xw/SText.h"
+#include "Xw/Cascade.h"
+#include "Xw/PopupMgr.h"
+#include "Xw/MenuBtn.h"
+#include "Xw/BBoard.h"
+#include "Xw/TextEdit.h"
+#include "Xw/Toggle.h"
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "xcircuit.h"
+#include "cursors.h"
+#include "colordefs.h"
+#include "menudep.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+#ifdef HAVE_XPM
+#ifndef XC_WIN32
+#include <X11/xpm.h>
+#endif
+#include "lib/pixmaps/xcircuit.xpm"
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Global Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern short popups; /* total number of popup widgets on the screen */
+extern int pressmode; /* Whether we are in a press & hold state */
+
+xcWidget top;
+xcWidget message1, message2, message3, toolbar, overlay = NULL;
+xcWidget menuwidgets[MaxMenuWidgets];
+xcWidget wschema, wsymb, netbutton;
+XtAppContext app;
+Atom wprot, wmprop[2];
+
+extern char _STR2[250]; /* Specifically for text returned from the popup prompt */
+extern char _STR[150]; /* Generic multipurpose string */
+extern Display *dpy;
+extern Colormap cmap;
+extern Pixmap STIPPLE[STIPPLES];
+extern Cursor appcursors[NUM_CURSORS];
+extern ApplicationData appdata;
+extern XCWindowData *areawin;
+extern Globaldata xobjs;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern short menusize;
+extern xcIntervalId printtime_id;
+extern short beeper;
+extern short fontcount;
+extern fontinfo *fonts;
+extern short help_up;
+extern menustruct TopButtons[];
+#ifdef HAVE_XPM
+extern toolbarstruct ToolBar[];
+extern short toolbuttons;
+#endif
+extern short maxbuttons;
+extern Pixmap helppix;
+extern aliasptr aliastop;
+extern float version;
+
+#ifndef OPENGL
+static
+#endif
+char STIPDATA[STIPPLES][4] = {
+ "\000\004\000\001",
+ "\000\005\000\012",
+ "\001\012\005\010",
+ "\005\012\005\012",
+ "\016\005\012\007",
+ "\017\012\017\005",
+ "\017\012\017\016",
+ "\000\000\000\000"
+};
+
+#ifdef DOUBLEBUFFER
+extern Pixmap dbuf;
+#endif
+
+/* Bad hack for problems with the DECstation. . . don't know why */
+#ifdef UniqueContextProblem
+#undef XUniqueContext
+XContext XUniqueContext()
+{
+ return XrmUniqueQuark();
+}
+#endif
+/* End of bad hack. . . */
+
+/*----------------------------------------------------------------------*/
+/* Initial Resource Management */
+/*----------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+static XtResource resources[] = {
+
+ /* schematic layout colors */
+
+ { "globalpincolor", "GlobalPinColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, globalcolor), XtRString, "Orange2"},
+ { "localpincolor", "LocalPinColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, localcolor), XtRString, "Red"},
+ { "infolabelcolor", "InfoLabelColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, infocolor), XtRString, "SeaGreen"},
+ { "ratsnestcolor", "RatsNestColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, ratsnestcolor), XtRString, "Tan4"},
+
+ /* non-schematic layout colors */
+
+ { "bboxcolor", "BBoxColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, bboxpix), XtRString, "greenyellow"},
+ { "clipcolor", "ClipColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, clipcolor), XtRString, "powderblue"},
+
+ /* GUI Color scheme 1 */
+
+ { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, fg), XtRString, "Black"},
+ { XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, bg), XtRString, "White"},
+ { "gridcolor", "GridColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, gridpix), XtRString, "Gray95"},
+ { "snapcolor", "SnapColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, snappix), XtRString, "Red"},
+ { "selectcolor", "SelectColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, selectpix), XtRString, "Gold3"},
+ { "filtercolor", "FilterColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, filterpix), XtRString, "SteelBlue3"},
+ { "axescolor", "AxesColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, axespix), XtRString, "Antique White"},
+ { "offbuttoncolor", "OffButtonColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, buttonpix), XtRString, "Gray85"},
+ { "auxiliarycolor", "AuxiliaryColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, auxpix), XtRString, "Green3"},
+ { "barcolor", "BarColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, barpix), XtRString, "Tan"},
+ { "paramcolor", "ParamColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, parampix), XtRString, "Plum3"},
+
+ /* GUI Color scheme 2 */
+
+ { "foreground2", XtCForeground, XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, fg2), XtRString, "White"},
+ { "background2", XtCBackground, XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, bg2), XtRString, "DarkSlateGray"},
+ { "gridcolor2", "GridColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, gridpix2), XtRString, "Gray40"},
+ { "snapcolor2", "SnapColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, snappix2), XtRString, "Red"},
+ { "selectcolor2", "SelectColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, selectpix2), XtRString, "Gold"},
+ { "axescolor2", "AxesColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, axespix2), XtRString, "NavajoWhite4"},
+ { "offbuttoncolor2", "OffButtonColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, buttonpix2), XtRString, "Gray50"},
+ { "auxiliarycolor2", "AuxiliaryColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, auxpix2), XtRString, "Green"},
+ { "paramcolor2", "ParamColor", XtRPixel, sizeof(Pixel),
+ XtOffset(ApplicationDataPtr, parampix2), XtRString, "Plum3"},
+
+ /* Other XDefaults-set properties */
+
+ { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(ApplicationDataPtr, xcfont), XtRString,
+ "-*-times-bold-r-normal--14-*"},
+ { "helpfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(ApplicationDataPtr, helpfont), XtRString,
+ "-*-helvetica-medium-r-normal--10-*"},
+ { "filelistfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(ApplicationDataPtr, filefont), XtRString,
+ "-*-helvetica-medium-r-normal--14-*"},
+ { "textfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(ApplicationDataPtr, textfont), XtRString,
+ "-*-courier-medium-r-normal--14-*"},
+ { "titlefont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ XtOffset(ApplicationDataPtr, titlefont), XtRString,
+ "-*-times-bold-i-normal--14-*"},
+ { XtNwidth, XtCWidth, XtRInt, sizeof(int),
+ XtOffset(ApplicationDataPtr, width), XtRString, "950"},
+ { XtNheight, XtCHeight, XtRInt, sizeof(int),
+ XtOffset(ApplicationDataPtr, height), XtRString, "760"},
+ { "timeout", "TimeOut", XtRInt, sizeof(int),
+ XtOffset(ApplicationDataPtr, timeout), XtRString, "10"}
+};
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Add a new color button to the color menu */
+/* called if new color button needs to be made */
+/*----------------------------------------------------------------------*/
+
+int addnewcolorentry(int ccolor)
+{
+ xcWidget colormenu, newbutton;
+ Arg wargs[2];
+ int i, n = 0;
+
+ /* check to see if entry is already in the color list */
+
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == ccolor) break;
+
+ /* make new entry in the menu */
+
+ if (i == number_colors) {
+
+ colormenu = xcParent(ColorAddNewColorButton);
+ XtnSetArg(XtNlabelType, XwRECT);
+ XtnSetArg(XtNrectColor, ccolor);
+
+ newbutton = XtCreateWidget("NewColor", XwmenubuttonWidgetClass,
+ colormenu, wargs, n);
+ XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setcolor, NULL);
+ XtManageChild(newbutton);
+
+ addtocolorlist(newbutton, ccolor);
+ }
+ return i;
+}
+
+/*----------------------------------------------------------------------*/
+/* This recursive function looks down the button menu hierarchy and */
+/* creates the necessary buttons and submenus. */
+/* Menu entries are marked if the corresponding "size" entry in the */
+/* menu structure is > 0. */
+/*----------------------------------------------------------------------*/
+
+void makesubmenu(char *menuname, char *attachname, menuptr buttonmenu,
+ int arraysize, xcWidget manager)
+{
+ short i, n = 0;
+ int cval;
+ xcWidget popupshell, cascade;
+ Arg wargs[6];
+ menuptr p;
+ char popupname[30];
+
+ sprintf(popupname, "popup%s", menuname);
+ popupshell = XtCreatePopupShell (popupname, transientShellWidgetClass,
+ manager, NULL, 0);
+
+ XtnSetArg(XtNattachTo, attachname);
+ XtnSetArg(XtNfont, appdata.titlefont);
+ cascade = XtCreateManagedWidget (menuname, XwcascadeWidgetClass,
+ popupshell, wargs, n);
+
+ for (p = buttonmenu, i = 0; p < buttonmenu + arraysize; p++, i++) {
+ n = 0;
+ if (p->size > 0 && p->submenu == NULL) { /* This denotes a marked entry */
+ XtnSetArg(XtNsetMark, True);
+ }
+ XtnSetArg(XtNfont, appdata.xcfont);
+
+ if (p->submenu != NULL) {
+ xcWidget newbutton = XtCreateWidget(p->name, XwmenubuttonWidgetClass,
+ cascade, wargs, n);
+ makesubmenu(p->name, p->name, p->submenu, p->size, manager);
+ XtManageChild (newbutton);
+ }
+ else if (p->name[0] == ' ') {
+ /* This is a separator, made from a PushButton widget */
+
+ xcWidget newbutton = XtCreateWidget(p->name, XwmenuButtonWidgetClass,
+ cascade, wargs, n); n = 0;
+ XtManageChild (newbutton);
+
+ XtnSetArg(XtNheight, 5);
+ XtnSetArg(XtNsensitive, False);
+ XtSetValues(newbutton, wargs, n);
+ }
+ else {
+ if (p->name[0] == '_') { /* Color button */
+ cval = xc_alloccolor(p->name + 1);
+ XtnSetArg(XtNlabelType, XwRECT);
+ XtnSetArg(XtNrectColor, cval);
+ }
+ else if (p->name[0] == ':') { /* Stipple button */
+ XtnSetArg(XtNlabelType, XwRECT);
+ if (((pointertype)(p->passeddata) == (OPAQUE | FILLED | FILLSOLID))) {
+ XtnSetArg(XtNrectColor, BlackPixel(dpy,DefaultScreen(dpy)));
+ }
+ else {
+ XtnSetArg(XtNrectStipple, STIPPLE[((pointertype)(p->passeddata) &
+ FILLSOLID) >> 5]);
+ }
+ }
+ menuwidgets[++menusize] = XtCreateWidget(p->name, XwmenubuttonWidgetClass,
+ cascade, wargs, n);
+ XtAddCallback (menuwidgets[menusize], XtNselect, (XtCallbackProc)p->func,
+ p->passeddata);
+ if (p->name[0] == '_') {
+ /* For color buttons, maintain a list of Widgets and color values */
+ addtocolorlist(menuwidgets[menusize], cval);
+ }
+
+ XtManageChild (menuwidgets[menusize]);
+ }
+ }
+}
+
+#ifdef HAVE_XPM
+
+/*----------------------------------------------------------------------*/
+/* Toolbar Creator */
+/*----------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void createtoolbar (xcWidget abform, Widget aform)
+{
+ int i, n = 0;
+ Arg wargs[12];
+ XImage *iret;
+ XpmAttributes attr;
+
+ XtnSetArg(XtNxRefWidget, aform);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNyAttachBottom, True);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNxOffset, 2);
+ XtnSetArg(XtNyOffset, 2);
+ XtnSetArg(XtNxResizable, False);
+ XtnSetArg(XtNyResizable, True);
+
+ XtnSetArg(XtNlayout, XwIGNORE);
+ toolbar = XtCreateManagedWidget("ToolBar", XwbulletinWidgetClass, abform,
+ wargs, n); n = 0;
+
+ /* Fix for limited-color capability video. Thanks to */
+ /* Frankie Liu <frankliu@stanford.edu> */
+
+ attr.valuemask = XpmSize | XpmCloseness;
+ attr.closeness = 65536;
+
+ for (i = 0; i < toolbuttons; i++) {
+ XpmCreateImageFromData(dpy, ToolBar[i].icon_data, &iret, NULL, &attr);
+ XtnSetArg(XtNlabelType, XwIMAGE);
+ XtnSetArg(XtNlabelImage, iret);
+ XtnSetArg(XtNwidth, attr.width + 4);
+ XtnSetArg(XtNheight, attr.height + 4);
+ XtnSetArg(XtNborderWidth, TBBORDER);
+ XtnSetArg(XtNnoPad, True);
+ XtnSetArg(XtNhint, ToolBar[i].hint);
+ XtnSetArg(XtNhintProc, Wprintf);
+
+ menuwidgets[++menusize] = XtCreateManagedWidget(ToolBar[i].name,
+ XwmenuButtonWidgetClass, toolbar, wargs, n); n = 0;
+ XtAddCallback(menuwidgets[menusize], XtNselect,
+ (XtCallbackProc)ToolBar[i].func, ToolBar[i].passeddata);
+ }
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Toolbar Resize */
+/*----------------------------------------------------------------------*/
+
+void resizetoolbar()
+{
+ int i, n = 0, bcol = 0;
+ int max_width = 0, max_height = 0, tot_width = 0;
+ Arg wargs[5];
+ xcWidget bwptr, lbwptr, bmax, lbmax;
+ Dimension t_height, bheight, bwidth;
+ xcWidget *tool_list = NULL;
+ int pytools = 0;
+
+ if (!xcIsRealized(toolbar)) return;
+
+ /* Avoid recursive calls to self and extra calls to the main draw routine */
+
+ XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
+ XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
+
+ /* Find the height of the toolbar from the parent widget */
+
+ XtnSetArg(XtNheight, &t_height);
+ XtGetValues(xcParent(toolbar), wargs, n); n = 0;
+
+#ifdef HAVE_PYTHON
+ tool_list = pytoolbuttons(&pytools);
+#endif
+
+ /* Realign the tool buttons inside the fixed space */
+
+ for (i = 0; i < toolbuttons + pytools; i++) {
+#ifdef HAVE_PYTHON
+ if (i >= toolbuttons)
+ bwptr = tool_list[i - toolbuttons];
+ else
+#endif
+ bwptr = XtNameToWidget(toolbar, ToolBar[i].name);
+ if (bwptr == (Widget)NULL) break;
+
+ XtnSetArg(XtNheight, &bheight);
+ XtnSetArg(XtNwidth, &bwidth);
+ XtGetValues(bwptr, wargs, n); n = 0;
+ bheight += (TBBORDER << 1);
+ max_height += bheight;
+ if (max_height > t_height) {
+ bcol++;
+ lbmax = bmax;
+ tot_width += max_width;
+ max_width = 0;
+ max_height = (int)bheight;
+ }
+ if (bwidth > max_width) {
+ max_width = (int)bwidth;
+ bmax = bwptr;
+ }
+
+ XtnSetArg(XtNx, tot_width);
+ XtnSetArg(XtNy, max_height - bheight);
+ XtSetValues(bwptr, wargs, n); n = 0;
+ lbwptr = bwptr;
+ }
+
+ XtnSetArg(XtNwidth, tot_width + max_width);
+ XtSetValues(toolbar, wargs, n); n = 0;
+
+ /* Reinstate callbacks */
+ XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
+ XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
+
+#ifdef HAVE_PYTHON
+ if (tool_list != NULL) free(tool_list);
+#endif
+}
+
+#endif /* HAVE_XPM */
+
+/*----------------------------------------------------------------------*/
+/* Hierarchical Menu Creator */
+/* This function creates the top level of buttons which are arranged */
+/* across the top starting at the left edge. For each button */
+/* that has a submenu, a Popup manager is created, and then menu */
+/* panes are attached to the manager in a hierarchical fashion. */
+/* Note: Returns widget for last button on top level */
+/*----------------------------------------------------------------------*/
+
+void createmenus (xcWidget form, xcWidget *firstbutton, xcWidget *lastbutton)
+{
+ int i, maxmgrs = 0, n = 0, j = 0;
+ WidgetList buttonw, mgr_shell, menu_mgr;
+ Arg wargs[6];
+
+ menusize = -1;
+
+ for (i = 0; i < maxbuttons; i++)
+ if (TopButtons[i].submenu != NULL) maxmgrs++;
+
+ buttonw = (WidgetList) XtMalloc(maxbuttons * sizeof(Widget));
+ mgr_shell = (WidgetList) XtMalloc(maxmgrs * sizeof(Widget));
+ menu_mgr = (WidgetList) XtMalloc(maxmgrs * sizeof(Widget));
+
+ for (i = 0; i < maxbuttons; i++) {
+
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNlabel, TopButtons[i].name);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ if (i > 0) {
+ XtnSetArg(XtNxRefWidget, buttonw[i - 1]);
+ XtnSetArg(XtNxAddWidth, True);
+ }
+ buttonw[i] = XtCreateWidget(TopButtons[i].name,
+ XwmenuButtonWidgetClass, form, wargs, n); n = 0;
+
+ if (!strcmp(TopButtons[i].name, "Netlist")) {
+ netbutton = buttonw[i];
+ XtManageChild(buttonw[i]);
+ }
+ else
+ XtManageChild(buttonw[i]);
+
+ if(TopButtons[i].submenu == NULL)
+ XtAddCallback(buttonw[i], XtNselect,
+ (XtCallbackProc)TopButtons[i].func, NULL);
+ else {
+ mgr_shell[j] = XtCreatePopupShell("mgr_shell", shellWidgetClass,
+ buttonw[i], NULL, 0);
+ menu_mgr[j] = XtCreateManagedWidget("menu_mgr", XwpopupmgrWidgetClass,
+ mgr_shell[j], NULL, 0);
+ makesubmenu(TopButtons[i].name, "menu_mgr", TopButtons[i].submenu,
+ TopButtons[i].size, menu_mgr[j]);
+ j++;
+ }
+ }
+ *firstbutton = buttonw[0];
+ *lastbutton = buttonw[i - 1];
+}
+
+/*----------------------------------------------*/
+/* Check for conditions to approve program exit */
+/*----------------------------------------------*/
+
+void quitcheck(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ char *promptstr;
+ Boolean doprompt = False;
+ buttonsave *savebutton;
+
+ /* enable default interrupt signal handler during this time, so that */
+ /* a double Control-C will ALWAYS exit. */
+
+ signal(SIGINT, SIG_DFL);
+ promptstr = (char *)malloc(22);
+ strcpy(promptstr, "Unsaved changes in: ");
+
+ /* Check all page objects for unsaved changes */
+
+ doprompt = (countchanges(&promptstr) > 0) ? True : False;
+
+ /* If any changes have not been saved, generate a prompt */
+
+ if (doprompt) {
+ promptstr = (char *)realloc(promptstr, strlen(promptstr) + 15);
+ strcat(promptstr, "\nQuit anyway?");
+ savebutton = getgeneric(w, quitcheck, NULL);
+ popupprompt(w, promptstr, NULL, quit, savebutton, NULL);
+ free(promptstr);
+ }
+ else {
+ free(promptstr);
+ quit(areawin->area, NULL);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Popup dialog box routines */
+/*-------------------------------------------------------------------------*/
+/* Propogate any key event from the dialog box into the textedit widget */
+/*-------------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void propevent(xcWidget w, xcWidget editwidget, XEvent *event)
+{
+ Window ewin = xcWindow(editwidget);
+
+ event->xany.window = ewin;
+ XSendEvent(dpy, ewin, False, KeyPressMask, event);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Destroy an interactive text-editing popup box */
+/*-------------------------------------------------------------------------*/
+
+void destroypopup(xcWidget button, popupstruct *callstruct, caddr_t calldata)
+{
+ Arg wargs[1];
+
+ if(XtNameToWidget(callstruct->popup, "help2") != NULL) {
+ help_up = False;
+ XFreePixmap(dpy, helppix);
+ helppix = (Pixmap)NULL;
+ }
+
+ if (callstruct->buttonptr->button != NULL) {
+
+ /* return the button to its normal state */
+
+ XtSetArg(wargs[0], XtNforeground, callstruct->buttonptr->foreground);
+ XtSetValues(callstruct->buttonptr->button, wargs, 1);
+
+ XtAddCallback(callstruct->buttonptr->button, XtNselect,
+ (XtCallbackProc)callstruct->buttonptr->buttoncall,
+ callstruct->buttonptr->dataptr);
+ }
+
+ XtDestroyWidget(callstruct->popup);
+ popups--;
+
+ /* free the allocated structure space */
+
+ free(callstruct->buttonptr);
+ if (callstruct->filter != NULL) free(callstruct->filter);
+ free(callstruct);
+
+ /* in the case of "quitcheck", we want to make sure that the signal */
+ /* handler is reset to default behavior if the quit command is */
+ /* canceled from inside the popup prompt window. */
+
+ signal(SIGINT, dointr);
+}
+
+/*----------------------------------------------------------------------*/
+/* Toggle button showing number of pages of output. */
+/* Erase the filename and set everything accordingly. */
+/*----------------------------------------------------------------------*/
+
+void linkset(xcWidget button, propstruct *callstruct, caddr_t calldata)
+{
+ Arg wargs[1];
+
+ free(xobjs.pagelist[areawin->page]->filename);
+ xobjs.pagelist[areawin->page]->filename = (char *)malloc(1);
+ xobjs.pagelist[areawin->page]->filename[0] = '\0';
+
+ XwTextClearBuffer(callstruct->textw);
+ getproptext(button, callstruct, calldata);
+
+ /* Change the select button back to "Apply" */
+ XtSetArg(wargs[0], XtNlabel, "Apply");
+ XtSetValues(callstruct->buttonw, wargs, 1);
+
+ /* Pop down the toggle button */
+ XtUnmanageChild(button);
+}
+
+/*----------------------------------------------------------------------*/
+/* Pull text from the popup prompt buffer into a global string variable */
+/*----------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void xcgettext(xcWidget button, popupstruct *callstruct, caddr_t calldata)
+{
+ if (callstruct->textw != NULL) {
+ sprintf(_STR2, "%.249s", XwTextCopyBuffer(callstruct->textw));
+
+ /* functions which use the file selector should look for directory name */
+ /* in string rather than a file name, and take appropriate action. */
+
+ if (callstruct->filew != NULL) {
+ if (lookdirectory(_STR2, 249)) {
+ newfilelist(callstruct->filew, callstruct);
+ return;
+ }
+ }
+ }
+
+ /* Pop down the widget now (for functions like execscript() which */
+ /* may want to interactively control the window contents), but do */
+ /* not destroy it until the function has returned. */
+
+ XtPopdown(callstruct->popup);
+
+ /* call the function which sets the variable according to type */
+ /* This is in format (function)(calling-widget, ptr-to-data) */
+
+ (*(callstruct->setvalue))(callstruct->buttonptr->button,
+ callstruct->buttonptr->dataptr);
+
+ if (callstruct->filew != NULL)
+ newfilelist(callstruct->filew, callstruct);
+
+ destroypopup(button, callstruct, calldata);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Grab text from the "output properties" window */
+/*-------------------------------------------------------------------------*/
+
+void getproptext(xcWidget button, propstruct *callstruct, caddr_t calldata)
+{
+ /* xobjs.pagelist[areawin->page]->filename can be realloc'd by the */
+ /* call to *(callstruct->setvalue), so callstruct->dataptr may no */
+ /* longer be pointing to the data. */
+
+ Arg wargs[1];
+ short file_yes = (callstruct->setvalue == setfilename);
+
+ sprintf(_STR2, "%.249s", XwTextCopyBuffer(callstruct->textw));
+ (*(callstruct->setvalue))(button, callstruct->dataptr);
+
+ /* special stuff for filename changes */
+
+ if (file_yes) {
+ char blabel[1024];
+ short num_linked;
+ xcWidget wrbutton, ltoggle;
+ struct stat statbuf;
+
+ /* get updated file information */
+
+ if (strstr(xobjs.pagelist[areawin->page]->filename, ".") == NULL)
+ sprintf(blabel, "%s.ps", xobjs.pagelist[areawin->page]->filename);
+ else sprintf(blabel, "%s", xobjs.pagelist[areawin->page]->filename);
+ if (stat(blabel, &statbuf) == 0) {
+ sprintf(blabel, " Overwrite File ");
+ if (beeper) XBell(dpy, 100);
+ Wprintf(" Warning: File exists");
+ }
+ else {
+ sprintf(blabel, " Write File ");
+ if (errno == ENOTDIR)
+ Wprintf("Error: Incorrect pathname");
+ else if (errno == EACCES)
+ Wprintf("Error: Path not readable");
+ W3printf(" ");
+ }
+
+ wrbutton = XtNameToWidget(xcParent(button), "Write File");
+ XtSetArg(wargs[0], XtNlabel, blabel);
+ XtSetValues(wrbutton, wargs, 1);
+
+ num_linked = pagelinks(areawin->page);
+ if (num_linked > 1) {
+ ltoggle = XtNameToWidget(xcParent(button), "LToggle");
+ sprintf(blabel, "%d Pages", num_linked);
+ XtSetArg(wargs[0], XtNlabel, blabel);
+ XtSetValues(ltoggle, wargs, 1);
+ XtManageChild(ltoggle);
+ }
+ }
+
+ /* topobject->name is not malloc'd, so is not changed by call to */
+ /* *(callstruct->setvalue). */
+
+ else if (callstruct->dataptr == topobject->name) {
+ printname(topobject);
+ renamepage(areawin->page);
+ }
+
+ /* Button title changes from "Apply" to "Okay" */
+
+ XtSetArg(wargs[0], XtNlabel, "Okay");
+ XtSetValues(callstruct->buttonw, wargs, 1);
+}
+
+/*----------------------------------------------------------------------*/
+/* Update scale, width, and height in response to change of one of them */
+/*----------------------------------------------------------------------*/
+
+void updatetext(xcWidget button, xcWidgetList callstruct, caddr_t calldata)
+{
+ float oscale, psscale;
+ char edit[3][50];
+ short i, n, posit;
+ char *pdptr;
+ Arg wargs[2];
+ int width, height;
+
+ /* auto-fit may override any changes to the scale */
+
+ autoscale(areawin->page);
+ writescalevalues(edit[0], edit[1], edit[2]);
+ for (i = 0; i < 3; i++) {
+ n = 0;
+ XtnSetArg(XtNstring, edit[i]);
+ pdptr = strchr(edit[i], '.');
+ posit = (pdptr != NULL) ? (short)(pdptr - edit[i]) : strlen(edit[i]);
+ XtnSetArg(XtNinsertPosition, posit);
+ XtSetValues(callstruct[i + 2], wargs, n);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Update the object name in response to a change in filename */
+/*-------------------------------------------------------------------------*/
+
+void updatename(xcWidget button, xcWidgetList callstruct, caddr_t calldata)
+{
+ short n, posit;
+ char *rootptr;
+ Arg wargs[2];
+
+ if (strstr(topobject->name, "Page ") != NULL || strstr(topobject->name,
+ "Page_") != NULL || topobject->name[0] == '\0') {
+
+ rootptr = strrchr(xobjs.pagelist[areawin->page]->filename, '/');
+ if (rootptr == NULL) rootptr = xobjs.pagelist[areawin->page]->filename;
+ else rootptr++;
+
+ sprintf(topobject->name, "%.79s", rootptr);
+
+ n = 0;
+ posit = strlen(topobject->name);
+ XtnSetArg(XtNstring, topobject->name);
+ XtnSetArg(XtNinsertPosition, posit);
+ XtSetValues(callstruct[1], wargs, n);
+ printname(topobject);
+ renamepage(areawin->page);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Create a popup window with "OK" and "Cancel" buttons, */
+/* and text and label fields. */
+/*-------------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void popupprompt(xcWidget button, char *request, char *current, void (*function)(),
+ buttonsave *datastruct, const char *filter)
+{
+ Arg wargs[9];
+ xcWidget popup, dialog, okbutton, cancelbutton, entertext;
+ xcWidget staticarea;
+ XWMHints *wmhints; /* for proper input focus */
+ Position xpos, ypos;
+ short n = 0;
+ Dimension height, width, areawidth, areaheight, bwidth, owidth;
+ static char defaultTranslations[] = "<Key>Return: execute()";
+ popupstruct *okaystruct;
+
+ height = (current == NULL) ? ROWHEIGHT * 4 : ROWHEIGHT * 5;
+ if (filter) height += LISTHEIGHT;
+
+ width = XTextWidth(appdata.xcfont, request, strlen(request)) + 20;
+ bwidth = XTextWidth(appdata.xcfont, "Cancel", strlen("Cancel")) + 50;
+ owidth = XTextWidth(appdata.xcfont, "Okay", strlen("Okay")) + 50;
+ if (width < 400) width = 400;
+
+ XtnSetArg(XtNwidth, &areawidth);
+ XtnSetArg(XtNheight, &areaheight);
+ XtGetValues(areawin->area, wargs, n); n = 0;
+ XtTranslateCoords(areawin->area, (Position) (areawidth / 2 - width
+ / 2 + popups * 20), (Position) (areaheight / 2 - height / 2 +
+ popups * 20), &xpos, &ypos);
+ XtnSetArg(XtNx, xpos);
+ XtnSetArg(XtNy, ypos);
+ popup = XtCreatePopupShell("prompt", transientShellWidgetClass,
+ button == NULL ? areawin->area : button, wargs, n); n = 0;
+ popups++;
+
+ XtnSetArg(XtNlayout, XwIGNORE);
+ XtnSetArg(XtNwidth, width);
+ XtnSetArg(XtNheight, height);
+ dialog = XtCreateManagedWidget("dialog", XwbulletinWidgetClass,
+ popup, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, ROWHEIGHT - 10 + (filter ? LISTHEIGHT : 0));
+ XtnSetArg(XtNstring, request);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ staticarea = XtCreateManagedWidget("static", XwstaticTextWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, height - ROWHEIGHT - 10);
+ XtnSetArg(XtNwidth, owidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ okbutton = XtCreateManagedWidget("Okay", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ okaystruct = (popupstruct *) malloc(sizeof(popupstruct));
+ okaystruct->buttonptr = datastruct;
+ okaystruct->popup = popup;
+ okaystruct->filter = (filter == NULL) ? NULL : strdup(filter);
+ okaystruct->setvalue = function;
+ okaystruct->textw = NULL;
+ okaystruct->filew = NULL;
+
+ XtnSetArg(XtNx, width - bwidth - 20);
+ XtnSetArg(XtNy, height - ROWHEIGHT - 10);
+ XtnSetArg(XtNwidth, bwidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ cancelbutton = XtCreateManagedWidget("Cancel", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtAddCallback(cancelbutton, XtNselect, (XtCallbackProc)destroypopup, okaystruct);
+
+ /* Event handler for WM_DELETE_WINDOW message. */
+ XtAddEventHandler(popup, NoEventMask, True, (XtEventHandler)delwin, okaystruct);
+
+ if (current != NULL) { /* A Text Edit widget is required */
+ char *pdptr;
+ short posit;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, ROWHEIGHT + 10 + (filter ? LISTHEIGHT : 0));
+ XtnSetArg(XtNheight, ROWHEIGHT + 5);
+ XtnSetArg(XtNwidth, width - 40);
+ XtnSetArg(XtNstring, current);
+ pdptr = strchr(current, '.');
+ posit = (pdptr != NULL) ? (short)(pdptr - current) : strlen(current);
+ XtnSetArg(XtNinsertPosition, posit);
+ XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
+ XtnSetArg(XtNwrap, XwWrapOff);
+ XtnSetArg(XtNfont, appdata.textfont);
+ entertext = XtCreateManagedWidget("Edit", XwtextEditWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ okaystruct->textw = entertext;
+
+ XtAddEventHandler(dialog, KeyPressMask, False,
+ (XtEventHandler)propevent, entertext);
+ XtAddEventHandler(staticarea, KeyPressMask, False,
+ (XtEventHandler)propevent, entertext);
+ XtOverrideTranslations(entertext, XtParseTranslationTable
+ (defaultTranslations));
+ XtAddCallback(entertext, XtNexecute, (XtCallbackProc)xcgettext, okaystruct);
+
+ /* Generate file prompting widget */
+
+ if (filter) genfilelist(dialog, okaystruct, width);
+ }
+ XtAddCallback(okbutton, XtNselect, (XtCallbackProc)xcgettext, okaystruct);
+
+ XtPopup(popup, XtGrabNone);
+
+ /* set the input focus for the window */
+
+ wmhints = XGetWMHints(dpy, xcWindow(popup));
+ wmhints->flags |= InputHint;
+ wmhints->input = True;
+ XSetWMHints(dpy, xcWindow(popup), wmhints);
+ XSetTransientForHint(dpy, xcWindow(popup), xcWindow(top));
+ XFree(wmhints);
+
+ if (current != NULL) XDefineCursor(dpy, xcWindow(entertext),
+ TEXTPTR);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Create a popup window for property changes */
+/*-------------------------------------------------------------------------*/
+
+#define MAXPROPS 7
+#define MARGIN 15
+
+propstruct okstruct[MAXPROPS], fpokstruct;
+
+#ifndef XC_WIN32
+
+void outputpopup(xcWidget button, caddr_t clientdata, caddr_t calldata)
+{
+ buttonsave *savebutton;
+ Arg wargs[9];
+ xcWidget popup, dialog, okbutton, titlearea, wrbutton;
+ xcWidget fpentertext, fpokay, autobutton, allpages;
+ xcWidgetList staticarea, entertext, okays;
+ XWMHints *wmhints; /* for proper input focus */
+ short num_linked;
+ Position xpos, ypos;
+ short n = 0;
+ Dimension height, width, areawidth, areaheight, bwidth, owidth, wwidth;
+ Pagedata *curpage;
+ char *pdptr;
+ short posit, i;
+ popupstruct *donestruct;
+ void (*function[MAXPROPS])();
+ void (*update[MAXPROPS])();
+ char statics[MAXPROPS][50], edit[MAXPROPS][75], request[150];
+ char fpedit[75], outname[75], pstr[20];
+ void *data[MAXPROPS];
+ struct stat statbuf;
+ static char defaultTranslations[] = "<Key>Return: execute()";
+
+ if (is_page(topobject) == -1) {
+ Wprintf("Can only save a top-level page!");
+ return;
+ }
+ if (button == NULL) button = FileWriteXcircuitPSButton;
+ savebutton = getgeneric(button, outputpopup, NULL);
+
+ curpage = xobjs.pagelist[areawin->page];
+
+ sprintf(request, "PostScript output properties (Page %d):",
+ areawin->page + 1);
+ sprintf(statics[0], "Filename:");
+ sprintf(statics[1], "Page label:");
+ sprintf(statics[2], "Scale:");
+ if (curpage->coordstyle == CM) {
+ sprintf(statics[3], "X Size (cm):");
+ sprintf(statics[4], "Y Size (cm):");
+ }
+ else {
+ sprintf(statics[3], "X Size (in):");
+ sprintf(statics[4], "Y Size (in):");
+ }
+ sprintf(statics[5], "Orientation:");
+ sprintf(statics[6], "Mode:");
+
+ if (curpage->filename)
+ sprintf(edit[0], "%s", curpage->filename);
+ else
+ sprintf(edit[0], "Page %d", areawin->page + 1);
+ sprintf(edit[1], "%s", topobject->name);
+
+ /* recompute bounding box and auto-scale, if set */
+ calcbbox(areawin->topinstance);
+ if (curpage->pmode & 2) autoscale(areawin->page);
+ writescalevalues(edit[2], edit[3], edit[4]);
+ sprintf(edit[5], "%s", (curpage->orient == 0) ? "Portrait" : "Landscape");
+ sprintf(edit[6], "%s", (curpage->pmode & 1)
+ ? "Full page" : "Embedded (EPS)");
+ function[0] = setfilename;
+ function[1] = setpagelabel;
+ function[2] = setfloat;
+ function[3] = setscalex;
+ function[4] = setscaley;
+ function[5] = setorient;
+ function[6] = setpmode;
+ update[0] = updatename;
+ update[1] = update[6] = NULL;
+ update[2] = updatetext;
+ update[3] = updatetext;
+ update[4] = updatetext;
+ update[5] = updatetext;
+ data[0] = &(curpage->filename);
+ data[1] = topobject->name;
+ data[2] = data[3] = data[4] = &(curpage->outscale);
+ data[5] = &(curpage->orient);
+ data[6] = &(curpage->pmode);
+
+ entertext = (xcWidgetList) XtMalloc (7 * sizeof (xcWidget));
+ staticarea = (xcWidgetList) XtMalloc (7 * sizeof (xcWidget));
+ okays = (xcWidgetList) XtMalloc (6 * sizeof (xcWidget));
+
+ /* get file information */
+
+ if (strstr(edit[0], ".") == NULL)
+ sprintf(outname, "%s.ps", edit[0]);
+ else sprintf(outname, "%s", edit[0]);
+ if (stat(outname, &statbuf) == 0) {
+ sprintf(outname, "Overwrite File");
+ Wprintf(" Warning: File exists");
+ }
+ else {
+ sprintf(outname, "Write File");
+ if (errno == ENOTDIR)
+ Wprintf("Error: Incorrect pathname");
+ else if (errno == EACCES)
+ Wprintf("Error: Path not readable");
+ else
+ W3printf(" ");
+ }
+
+ height = ROWHEIGHT * 17; /* 3 + (2 * MAXPROPS) */
+ width = XTextWidth(appdata.xcfont, request, strlen(request)) + 20;
+ bwidth = XTextWidth(appdata.xcfont, "Close", strlen("Close")) + 50;
+ owidth = XTextWidth(appdata.xcfont, "Apply", strlen("Apply")) + 50;
+ wwidth = XTextWidth(appdata.xcfont, outname, strlen(outname)) + 80;
+ if (width < 500) width = 500;
+
+ XtnSetArg(XtNwidth, &areawidth);
+ XtnSetArg(XtNheight, &areaheight);
+ XtGetValues(areawin->area, wargs, n); n = 0;
+ XtTranslateCoords(areawin->area, (Position) (areawidth / 2 - width
+ / 2 + popups * 20), (Position) (areaheight / 2 - height / 2 +
+ popups * 20), &xpos, &ypos);
+ XtnSetArg(XtNx, xpos);
+ XtnSetArg(XtNy, ypos);
+ popup = XtCreatePopupShell("prompt", transientShellWidgetClass,
+ areawin->area, wargs, n); n = 0;
+ popups++;
+
+ XtnSetArg(XtNlayout, XwIGNORE);
+ XtnSetArg(XtNwidth, width);
+ XtnSetArg(XtNheight, height);
+ dialog = XtCreateManagedWidget("dialog", XwbulletinWidgetClass,
+ popup, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, ROWHEIGHT - 10);
+ XtnSetArg(XtNstring, request);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNbackground, BARCOLOR);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ titlearea = XtCreateManagedWidget("title", XwstaticTextWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, height - ROWHEIGHT - 10);
+ XtnSetArg(XtNwidth, owidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ okbutton = XtCreateManagedWidget("Close", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, width - wwidth - 20);
+ XtnSetArg(XtNy, height - ROWHEIGHT - 10);
+ XtnSetArg(XtNwidth, wwidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNlabel, outname);
+ wrbutton = XtCreateManagedWidget("Write File", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ for (i = 0; i < MAXPROPS; i++) {
+ XtnSetArg(XtNx, 20);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + 5 + (i * 2 * ROWHEIGHT));
+ XtnSetArg(XtNstring, statics[i]);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ staticarea[i] = XtCreateManagedWidget("static", XwstaticTextWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, 150);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (i * 2 * ROWHEIGHT));
+ if (i < 5) {
+ XtnSetArg(XtNheight, ROWHEIGHT + 5);
+ XtnSetArg(XtNstring, edit[i]);
+ XtnSetArg(XtNwidth, width - owidth - 190);
+ pdptr = strchr(edit[i], '.');
+ posit = (pdptr != NULL) ? (short)(pdptr - edit[i]) : strlen(edit[i]);
+ XtnSetArg(XtNinsertPosition, posit);
+ XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
+ XtnSetArg(XtNwrap, XwWrapOff);
+ XtnSetArg(XtNfont, appdata.textfont);
+ entertext[i] = XtCreateManagedWidget("Edit", XwtextEditWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, width - owidth - 20);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (i * 2 * ROWHEIGHT));
+ XtnSetArg(XtNwidth, owidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ okays[i] = XtCreateManagedWidget("Apply", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ okstruct[i].textw = entertext[i];
+ okstruct[i].buttonw = okays[i];
+ okstruct[i].setvalue = function[i];
+ okstruct[i].dataptr = data[i];
+
+ XtAddCallback(okays[i], XtNselect, (XtCallbackProc)getproptext, &okstruct[i]);
+ if (update[i] != NULL)
+ XtAddCallback(okays[i], XtNselect, (XtCallbackProc)update[i], entertext);
+ XtOverrideTranslations(entertext[i], XtParseTranslationTable
+ (defaultTranslations));
+ XtAddCallback(entertext[i], XtNexecute, (XtCallbackProc)getproptext,
+ &okstruct[i]);
+ if (update[i] != NULL) XtAddCallback(entertext[i], XtNexecute,
+ (XtCallbackProc)update[i], entertext);
+
+ }
+ else {
+ XtnSetArg(XtNlabel, edit[i]);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ entertext[i] = XtCreateManagedWidget("Toggle", XwpushButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+ XtAddCallback(entertext[i], XtNselect, (XtCallbackProc)function[i], data[i]);
+ if (update[i] != NULL)
+ XtAddCallback(entertext[i], XtNselect, (XtCallbackProc)update[i], entertext);
+ }
+ }
+
+ /* If this filename is linked to other pages (multi-page output), add a button */
+ /* which will unlink the page name from the other pages when toggled. */
+
+ num_linked = pagelinks(areawin->page);
+ XtnSetArg(XtNx, width - wwidth - 20);
+ XtnSetArg(XtNy, ROWHEIGHT - 10);
+ XtnSetArg(XtNset, True);
+ XtnSetArg(XtNsquare, True);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ sprintf(pstr, "%d Pages", num_linked);
+ XtnSetArg(XtNlabel, pstr);
+ allpages = XtCreateWidget("LToggle", XwtoggleWidgetClass, dialog, wargs, n); n = 0;
+ XtAddCallback(allpages, XtNrelease, (XtCallbackProc)linkset, &okstruct[0]);
+
+ /* If full-page pmode is chosen, there is an additional text structure.
+ Make this text structure always but allow it to be managed and
+ unmanaged as necessary. */
+
+ XtnSetArg(XtNx, 240);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (10 * ROWHEIGHT));
+ XtnSetArg(XtNset, (curpage->pmode & 2) ? True : False);
+ XtnSetArg(XtNsquare, True);
+ XtnSetArg(XtNborderWidth, 0);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ autobutton = XtCreateWidget("Auto-fit", XwtoggleWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ if (curpage->coordstyle == CM) {
+ sprintf(fpedit, "%3.2f x %3.2f cm",
+ (float)curpage->pagesize.x / IN_CM_CONVERT,
+ (float)curpage->pagesize.y / IN_CM_CONVERT);
+ }
+ else {
+ sprintf(fpedit, "%3.2f x %3.2f in",
+ (float)curpage->pagesize.x / 72.0,
+ (float)curpage->pagesize.y / 72.0);
+ }
+ XtnSetArg(XtNx, 240);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (12 * ROWHEIGHT));
+ XtnSetArg(XtNheight, ROWHEIGHT + 5);
+ XtnSetArg(XtNstring, fpedit);
+ XtnSetArg(XtNwidth, width - owidth - 280);
+ pdptr = strchr(fpedit, '.');
+ posit = (pdptr != NULL) ? (short)(pdptr - fpedit) : strlen(fpedit);
+ XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
+ XtnSetArg(XtNwrap, XwWrapOff);
+ XtnSetArg(XtNfont, appdata.textfont);
+ XtnSetArg(XtNinsertPosition, posit);
+ fpentertext = XtCreateWidget("fpedit", XwtextEditWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ XtnSetArg(XtNx, width - owidth - 20);
+ XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (12 * ROWHEIGHT));
+ XtnSetArg(XtNwidth, owidth);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNlabel, "Apply");
+ fpokay = XtCreateWidget("fpokay", XwmenuButtonWidgetClass,
+ dialog, wargs, n); n = 0;
+
+ fpokstruct.textw = fpentertext;
+ fpokstruct.buttonw = fpokay;
+ fpokstruct.setvalue = setpagesize;
+ fpokstruct.dataptr = &(curpage->pagesize);
+
+ XtAddCallback(fpokay, XtNselect, (XtCallbackProc)getproptext, &fpokstruct);
+ XtAddCallback(fpokay, XtNselect, (XtCallbackProc)updatetext, entertext);
+ XtOverrideTranslations(fpentertext, XtParseTranslationTable
+ (defaultTranslations));
+ XtAddCallback(fpentertext, XtNexecute, (XtCallbackProc)getproptext, &fpokstruct);
+ XtAddCallback(fpentertext, XtNexecute, (XtCallbackProc)updatetext, entertext);
+ XtAddCallback(autobutton, XtNselect, (XtCallbackProc)autoset, entertext);
+ XtAddCallback(autobutton, XtNrelease, (XtCallbackProc)autostop, NULL);
+
+ if (curpage->pmode & 1) {
+ XtManageChild(fpentertext);
+ XtManageChild(fpokay);
+ XtManageChild(autobutton);
+ }
+
+ if (num_linked > 1) {
+ XtManageChild(allpages);
+ }
+
+ /* end of pagesize extra Widget definitions */
+
+ donestruct = (popupstruct *) malloc(sizeof(popupstruct));
+ donestruct->popup = popup;
+ donestruct->buttonptr = savebutton;
+ donestruct->filter = NULL;
+ XtAddCallback(okbutton, XtNselect, (XtCallbackProc)destroypopup, donestruct);
+
+ /* Send setfile() the widget entertext[0] in case because user sometimes
+ forgets to type "okay" but buffer contains the expected filename */
+
+ XtAddCallback(wrbutton, XtNselect, (XtCallbackProc)setfile, entertext[0]);
+
+ /* Begin Popup */
+
+ XtPopup(popup, XtGrabNone);
+
+ /* set the input focus for the window */
+
+ wmhints = XGetWMHints(dpy, xcWindow(popup));
+ wmhints->flags |= InputHint;
+ wmhints->input = True;
+ XSetWMHints(dpy, xcWindow(popup), wmhints);
+ XSetTransientForHint(dpy, xcWindow(popup), xcWindow(top));
+ XFree(wmhints);
+
+ for (i = 0; i < 5; i++)
+ XDefineCursor(dpy, xcWindow(entertext[i]), TEXTPTR);
+}
+
+#endif
+
+/*-------------------------------------------------*/
+/* Print a string to the message widget. */
+/* Note: Widget message must be a global variable. */
+/* For formatted strings, format first into _STR */
+/*-------------------------------------------------*/
+
+void clrmessage(XtPointer clientdata, xcIntervalId *id)
+{
+ char buf1[50], buf2[50];
+
+ /* Don't write over the report of the edit string contents, */
+ /* if we're in one of the label edit modes */
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE)
+ charreport(TOLABEL(EDITPART));
+ else {
+ measurestr(xobjs.pagelist[areawin->page]->gridspace, buf1);
+ measurestr(xobjs.pagelist[areawin->page]->snapspace, buf2);
+ Wprintf("Grid %.50s : Snap %.50s", buf1, buf2);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* This is the non-Tcl version of tcl_vprintf() */
+/*----------------------------------------------------------------------*/
+
+void xc_vprintf(xcWidget widget, const char *fmt, va_list args_in)
+{
+ va_list args;
+ static char outstr[128];
+ char *outptr, *bigstr = NULL;
+ int nchars;
+ Arg wargs[1];
+
+ outstr[0] = '\0';
+ outptr = outstr;
+
+ /* This mess circumvents problems with systems which do not have */
+ /* va_copy() defined. Some define __va_copy(); otherwise we must */
+ /* assume that args = args_in is valid. */
+
+ va_copy(args, args_in);
+ nchars = vsnprintf(outptr, 127, fmt, args);
+ va_end(args);
+
+ if (nchars >= 127) {
+ va_copy(args, args_in);
+ bigstr = (char *)malloc(nchars + 2);
+ bigstr[0] = '\0';
+ outptr = bigstr;
+ vsnprintf(outptr, nchars + 2, fmt, args);
+ va_end(args);
+ }
+ else if (nchars == -1) nchars = 126;
+
+ XtSetArg(wargs[0], XtNstring, outptr);
+ XtSetValues(widget, wargs, 1);
+ XtSetArg(wargs[0], XtNheight, ROWHEIGHT);
+ XtSetValues(widget, wargs, 1);
+
+ if (bigstr != NULL) free(bigstr);
+
+ if (widget == message3) {
+ if (printtime_id != 0) {
+ xcRemoveTimeOut(printtime_id);
+ printtime_id = 0;
+ }
+ }
+
+ /* 10 second timeout */
+ if (widget == message3) {
+ printtime_id = xcAddTimeOut(app, 10000, clrmessage, NULL);
+ }
+}
+
+/*------------------------------------------------------------------------------*/
+/* W3printf is the same as Wprintf because the non-Tcl based version does not */
+/* duplicate output to stdout/stderr. */
+/*------------------------------------------------------------------------------*/
+
+void W3printf(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xc_vprintf(message3, format, ap);
+ va_end(ap);
+}
+
+/*------------------------------------------------------------------------------*/
+
+void Wprintf(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xc_vprintf(message3, format, ap);
+ va_end(ap);
+}
+
+/*------------------------------------------------------------------------------*/
+
+void W1printf(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xc_vprintf(message1, format, ap);
+ va_end(ap);
+}
+
+/*------------------------------------------------------------------------------*/
+
+void W2printf(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xc_vprintf(message2, format, ap);
+ va_end(ap);
+}
+
+/*------------------------------------------------------------------------------*/
+
+#ifndef XC_WIN32
+
+void getcommand(xcWidget cmdw, caddr_t clientdata, caddr_t calldata)
+{
+ sprintf(_STR2, "%.249s", XwTextCopyBuffer(cmdw));
+#ifdef HAVE_PYTHON
+ execcommand(0, _STR2 + 4);
+#else
+ execcommand(0, _STR2 + 2);
+#endif
+ XtRemoveEventHandler(areawin->area, KeyPressMask, False,
+ (XtEventHandler)propevent, cmdw);
+ XtAddCallback(areawin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
+ XtAddCallback(areawin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
+ XtUnmanageChild(cmdw);
+}
+
+/*------------------------------------------------------------------------------*/
+/* "docommand" overlays the message3 widget temporarily with a TextEdit widget. */
+/*------------------------------------------------------------------------------*/
+
+void docommand()
+{
+ Arg wargs[12];
+ int n = 0;
+ Dimension w;
+ Position x, y;
+ static char defaultTranslations[] = "<Key>Return: execute()";
+
+ if (overlay == NULL) {
+ XtnSetArg(XtNy, &y);
+ XtnSetArg(XtNx, &x);
+ XtnSetArg(XtNwidth, &w);
+ XtGetValues(message3, wargs, n); n = 0;
+
+ XtnSetArg(XtNy, y);
+ XtnSetArg(XtNx, x);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNwidth, w);
+
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNwrap, XwWrapOff);
+ overlay = XtCreateManagedWidget("Command", XwtextEditWidgetClass,
+ top, wargs, n); n = 0;
+
+ XtOverrideTranslations(overlay, XtParseTranslationTable(defaultTranslations));
+ XtAddCallback(overlay, XtNexecute, (XtCallbackProc)getcommand, NULL);
+ }
+ else {
+ XtManageChild(overlay);
+ }
+
+ XwTextClearBuffer(overlay);
+#ifdef HAVE_PYTHON
+ XwTextInsert(overlay, ">>> ");
+#else
+ XwTextInsert(overlay, "? ");
+#endif
+
+ /* temporarily redirect all text into the overlay widget */
+
+ XtRemoveCallback(areawin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
+ XtRemoveCallback(areawin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
+ XtAddEventHandler(areawin->area, KeyPressMask, False,
+ (XtEventHandler)propevent, overlay);
+}
+
+/*------------------------------------------------------------------------------*/
+/* When all else fails, install your own colormap */
+/*------------------------------------------------------------------------------*/
+
+int installowncmap()
+{
+ Colormap newcmap;
+
+ Fprintf(stdout, "Installing my own colormap\n");
+
+ /* allocate a new colormap */
+
+ newcmap = XCopyColormapAndFree(dpy, cmap);
+ if (newcmap == (Colormap)NULL) return (-1);
+ cmap = newcmap;
+
+ if (areawin->area != (xcWidget)NULL) {
+ if (xcIsRealized(areawin->area)) {
+ xcWidget colormenu = xcParent(ColorAddNewColorButton);
+
+ XSetWindowColormap(dpy, xcWindow(top), cmap);
+ XSetWindowColormap(dpy, areawin->window, cmap);
+ if (colormenu != (xcWidget)NULL)
+ XSetWindowColormap(dpy, xcWindow(colormenu), cmap);
+ }
+ }
+ return(1);
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Event handler for input focus */
+/*----------------------------------------------------------------------*/
+
+#ifdef INPUT_FOCUS
+
+void mappinghandler(xcWidget w, caddr_t clientdata, XEvent *event)
+{
+ if (!xcIsRealized(w)) return;
+ switch(event->type) {
+ case MapNotify:
+ /* Fprintf(stderr, "Window top was mapped. Setting input focus\n"); */
+ areawin->mapped = True;
+ XSetInputFocus(dpy, xcWindow(w), RevertToPointerRoot, CurrentTime);
+ break;
+ case UnmapNotify:
+ /* Fprintf(stderr, "Window top was unmapped\n"); */
+ areawin->mapped = False;
+ break;
+ }
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+
+void clientmessagehandler(xcWidget w, caddr_t clientdata, XEvent *event)
+{
+ if (!xcIsRealized(w)) return;
+
+ if (event->type == ClientMessage) {
+ if (render_client(event) == False)
+ return;
+
+#ifdef INPUT_FOCUS
+ if (areawin->mapped == True) {
+ /* Fprintf(stderr, "Forcing input focus\n"); */
+ XSetInputFocus(dpy, xcWindow(w), RevertToPointerRoot, CurrentTime);
+ }
+#endif
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* Event handler for WM_DELETE_WINDOW message. */
+/*----------------------------------------------------------------------*/
+
+void delwin(xcWidget w, popupstruct *bstruct, XClientMessageEvent *event)
+{
+ if (event->type != ClientMessage)
+ return;
+
+ if((event->message_type == wprot) && (event->data.l[0] == wmprop[0])) {
+ if (w == top)
+ quitcheck(w, NULL, NULL);
+ else
+ destroypopup(w, bstruct, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/* GUI_init() --- generate the widget structures, allocate colormaps */
+/* and graphics contexts, generate menus and toolbar, and assign */
+/* callback functions and event handlers. */
+/*----------------------------------------------------------------------*/
+
+#ifdef XC_WIN32
+
+XCWindowData* GUI_init(int argc, char *argv[]);
+
+#else
+
+XCWindowData *GUI_init(int argc, char *argv[])
+{
+
+#ifdef HAVE_XPM
+ xcWidget abform;
+#endif
+ xcWidget form, aform, firstbutton, lastbutton, corner;
+ XGCValues values;
+ XWMHints *wmhints; /* for proper input focus */
+ Arg wargs[12];
+ Pixmap icon;
+ Window win;
+ XCWindowData *newwin;
+ short i, n = 0;
+
+ /* Things to do the first time around */
+ if (dpy == NULL) {
+
+ char *argfb[] = { /* Fallback resources */
+ "xcircuit*foreground : brown4", /* These are the values that */
+ "xcircuit*background : beige", /* not or cannot be explicitly */
+ "xcircuit.foreground : black", /* initialized by */
+ "xcircuit.background : white", /* XtGetApplicationResources() */
+ "xcircuit*borderWidth : 2", /* below. */
+ "xcircuit*borderColor : Red",
+ NULL /* Sentinel */
+ };
+
+ XtSetLanguageProc(NULL, NULL, NULL);
+
+ /*-------------------------------------------------------------------*/
+ /* Set pointer to own XDefaults file, but allow an external override */
+ /*-------------------------------------------------------------------*/
+
+#ifdef HAVE_PUTENV
+ if (getenv("XAPPLRESDIR") == NULL)
+ putenv("XAPPLRESDIR=" RESOURCES_DIR);
+#else
+ setenv("XAPPLRESDIR", RESOURCES_DIR, 0);
+#endif
+
+ /*-----------------------------*/
+ /* Create the widget hierarchy */
+ /*-----------------------------*/
+
+ top = XtOpenApplication(&app, "XCircuit", NULL, 0, &argc, argv,
+ argfb, applicationShellWidgetClass, NULL, 0);
+
+ dpy = XtDisplay(top);
+ win = DefaultRootWindow(dpy);
+ cmap = DefaultColormap(dpy, DefaultScreen(dpy));
+
+ /*-------------------------*/
+ /* Create stipple patterns */
+ /*-------------------------*/
+
+ for (i = 0; i < STIPPLES; i++)
+ STIPPLE[i] = XCreateBitmapFromData(dpy, win, STIPDATA[i], 4, 4);
+
+ /*----------------------------------------*/
+ /* Allocate space for the basic color map */
+ /*----------------------------------------*/
+
+ number_colors = 0;
+ colorlist = (colorindex *)malloc(sizeof(colorindex));
+ appcolors = (int *) malloc(NUMBER_OF_COLORS * sizeof(int));
+
+ /*-----------------------------------------------------------*/
+ /* Xw must add these translations for the popup manager */
+ /*-----------------------------------------------------------*/
+ XwAppInitialize(app);
+
+ /*-------------------------------*/
+ /* Get the application resources */
+ /*-------------------------------*/
+
+ XtAppAddConverter(app, XtRString, XtRPixel, (XtConverter)CvtStringToPixel,
+ NULL, 0);
+ XtGetApplicationResources(top, &appdata, resources, XtNumber(resources),
+ NULL, 0);
+ }
+ else { /* Not the first time---display has already been opened */
+
+ top = XtAppCreateShell("XCircuit", "XCircuit", applicationShellWidgetClass,
+ dpy, NULL, 0);
+ }
+
+ n = 0;
+ XtnSetArg(XtNwidth, appdata.width);
+ XtnSetArg(XtNheight, appdata.height);
+ XtnSetArg(XtNforeground, appdata.fg);
+ XtnSetArg(XtNbackground, appdata.bg);
+ XtnSetArg(XtNcolormap, cmap);
+ XtSetValues(top, wargs, n); n = 0;
+
+ form = XtCreateManagedWidget("Form", XwformWidgetClass, top, NULL, 0);
+
+ /* Generate a new window data structure */
+
+ newwin = create_new_window();
+
+ /* Set up the buttons and Graphics drawing area */
+
+ createmenus(form, &firstbutton, &lastbutton);
+
+ XtnSetArg(XtNxRefWidget, lastbutton);
+ XtnSetArg(XtNyRefWidget, form);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ sprintf(_STR, " Welcome to Xcircuit Version %2.1f", PROG_VERSION);
+ XtnSetArg(XtNstring, _STR);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNwrap, False);
+ XtnSetArg(XtNstrip, False);
+ message1 = XtCreateManagedWidget("Message1", XwstaticTextWidgetClass,
+ form, wargs, n); n = 0;
+
+#ifdef HAVE_XPM
+ /*-------------------------------------------------------------------*/
+ /* An extra form divides the main window from the toolbar */
+ /*-------------------------------------------------------------------*/
+
+ XtnSetArg(XtNyRefWidget, firstbutton);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyOffset, 2);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNborderWidth, 0);
+ abform = XtCreateManagedWidget("ABForm", XwformWidgetClass, form, wargs, n);
+ n = 0;
+
+ /*-------------------------------------------------------------------*/
+ /* The main window and its scrollbars rest in a separate form window */
+ /*-------------------------------------------------------------------*/
+
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNyAttachBottom, True);
+ aform = XtCreateManagedWidget("AForm", XwformWidgetClass, abform, wargs, n);
+ n = 0;
+#else
+#define abform aform
+
+ /*-------------------------------------------------------------------*/
+ /* The main window and its scrollbars rest in a separate form window */
+ /*-------------------------------------------------------------------*/
+
+ XtnSetArg(XtNyRefWidget, firstbutton);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNxResizable, True);
+ aform = XtCreateManagedWidget("AForm", XwformWidgetClass, form, wargs, n);
+ n = 0;
+
+#endif
+
+ /*------------------------*/
+ /* add scrollbar widget */
+ /*------------------------*/
+
+ XtnSetArg(XtNxResizable, False);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNwidth, SBARSIZE);
+ XtnSetArg(XtNborderWidth, 1);
+ newwin->scrollbarv = XtCreateManagedWidget("SBV", XwworkSpaceWidgetClass,
+ aform, wargs, n); n = 0;
+
+ /*----------------------------------------------------------*/
+ /* A button in the scrollbar corner for the sake of beauty. */
+ /*----------------------------------------------------------*/
+
+ XtnSetArg(XtNyRefWidget, newwin->scrollbarv);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyAttachBottom, True);
+ XtnSetArg(XtNheight, SBARSIZE);
+ XtnSetArg(XtNwidth, SBARSIZE);
+ XtnSetArg(XtNborderWidth, 1);
+ XtnSetArg(XtNlabel, "");
+ corner = XtCreateManagedWidget("corner", XwpushButtonWidgetClass,
+ aform, wargs, n); n = 0;
+
+ /*-------------------------*/
+ /* The main drawing window */
+ /*-------------------------*/
+
+ XtnSetArg(XtNxOffset, SBARSIZE);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNyResizable, True);
+ XtnSetArg(XtNxAttachRight, True);
+ newwin->area = XtCreateManagedWidget("Area", XwworkSpaceWidgetClass,
+ aform, wargs, n); n = 0;
+
+ /*-------------------------*/
+ /* and the other scrollbar */
+ /*-------------------------*/
+
+ XtnSetArg(XtNyRefWidget, newwin->area);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNxRefWidget, newwin->scrollbarv);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNheight, SBARSIZE);
+ XtnSetArg(XtNyResizable, False);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNborderWidth, 1);
+ newwin->scrollbarh = XtCreateManagedWidget("SBH", XwworkSpaceWidgetClass,
+ aform, wargs, n); n = 0;
+
+ /*------------------------------------------------*/
+ /* Supplementary message widgets go at the bottom */
+ /*------------------------------------------------*/
+
+ XtnSetArg(XtNxResizable, False);
+ XtnSetArg(XtNyRefWidget, abform);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyOffset, -5);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNforeground, appdata.buttonpix);
+ XtnSetArg(XtNbackground, appdata.buttonpix);
+ wsymb = XtCreateWidget("Symbol", XwpushButtonWidgetClass,
+ form, wargs, n); n = 0;
+ XtManageChild(wsymb);
+
+ XtnSetArg(XtNxRefWidget, wsymb);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNxResizable, False);
+ XtnSetArg(XtNyRefWidget, abform);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyOffset, -5);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNforeground, appdata.bg);
+ XtnSetArg(XtNbackground, appdata.snappix);
+ wschema = XtCreateWidget("Schematic", XwpushButtonWidgetClass,
+ form, wargs, n); n = 0;
+ XtManageChild(wschema);
+
+
+ XtnSetArg(XtNxRefWidget, wschema);
+ XtnSetArg(XtNxAddWidth, True);
+
+ XtnSetArg(XtNyRefWidget, abform);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyOffset, -5);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNstring, "Editing: Page 1");
+ XtnSetArg(XtNxResizable, False);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNwrap, False);
+ message2 = XtCreateManagedWidget("Message2", XwstaticTextWidgetClass,
+ form, wargs, n); n = 0;
+
+ XtnSetArg(XtNyRefWidget, abform);
+ XtnSetArg(XtNyAddHeight, True);
+ XtnSetArg(XtNyOffset, -5);
+ XtnSetArg(XtNxAttachRight, True);
+ XtnSetArg(XtNxRefWidget, message2);
+ XtnSetArg(XtNxAddWidth, True);
+ XtnSetArg(XtNheight, ROWHEIGHT);
+ XtnSetArg(XtNxResizable, True);
+ XtnSetArg(XtNfont, appdata.xcfont);
+ XtnSetArg(XtNwrap, False);
+ XtnSetArg(XtNgravity, WestGravity);
+ XtnSetArg(XtNstring, "Don't Panic");
+ message3 = XtCreateManagedWidget("Message3", XwstaticTextWidgetClass,
+ form, wargs, n); n = 0;
+
+ /*-------------------------------*/
+ /* optional Toolbar on the right */
+ /*-------------------------------*/
+
+#ifdef HAVE_XPM
+ createtoolbar(abform, aform);
+ XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
+#endif
+
+ /* Setup callback routines for the area widget */
+ /* Use Button1Press event to add the callback which tracks motion; this */
+ /* will reduce the number of calls serviced during normal operation */
+
+ XtAddCallback(newwin->area, XtNexpose, (XtCallbackProc)drawarea, NULL);
+ XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
+
+ XtAddCallback(newwin->area, XtNselect, (XtCallbackProc)buttonhandler, NULL);
+ XtAddCallback(newwin->area, XtNrelease, (XtCallbackProc)buttonhandler, NULL);
+ XtAddCallback(newwin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
+ XtAddCallback(newwin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
+
+ XtAddEventHandler(newwin->area, Button1MotionMask | Button2MotionMask,
+ False, (XtEventHandler)xlib_drag, NULL);
+
+ /* Setup callback routines for the scrollbar widgets */
+
+ XtAddEventHandler(newwin->scrollbarh, ButtonMotionMask, False,
+ (XtEventHandler)panhbar, NULL);
+ XtAddEventHandler(newwin->scrollbarv, ButtonMotionMask, False,
+ (XtEventHandler)panvbar, NULL);
+
+ XtAddCallback(newwin->scrollbarh, XtNrelease, (XtCallbackProc)endhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNrelease, (XtCallbackProc)endvbar, NULL);
+
+ XtAddCallback(newwin->scrollbarh, XtNexpose, (XtCallbackProc)drawhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNexpose, (XtCallbackProc)drawvbar, NULL);
+ XtAddCallback(newwin->scrollbarh, XtNresize, (XtCallbackProc)drawhbar, NULL);
+ XtAddCallback(newwin->scrollbarv, XtNresize, (XtCallbackProc)drawvbar, NULL);
+
+ /* Event handler for WM_DELETE_WINDOW message. */
+ XtAddEventHandler(top, NoEventMask, True, (XtEventHandler)delwin, NULL);
+
+ XtAddCallback(corner, XtNselect, (XtCallbackProc)zoomview, Number(1));
+ XtAddCallback (wsymb, XtNselect, (XtCallbackProc)xlib_swapschem, Number(0));
+ XtAddCallback (wschema, XtNselect, (XtCallbackProc)xlib_swapschem, Number(0));
+
+ /*--------------------*/
+ /* Realize the Widget */
+ /*--------------------*/
+
+ areawin = newwin;
+ XtRealizeWidget(top);
+
+ wprot = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ wmprop[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ wmprop[1] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+ XSetWMProtocols(dpy, xcWindow(top), wmprop, 2);
+
+ /*----------------------------------------------------*/
+ /* Let the window manager set the input focus for the */
+ /* window and inform the window manager of the icon */
+ /* pixmap (which may or may not be useful, depending */
+ /* on the particular window manager). */
+ /*----------------------------------------------------*/
+
+ wmhints = XGetWMHints(dpy, xcWindow(top));
+ wmhints->input = True;
+
+#ifdef HAVE_XPM
+ /* Create the xcircuit icon pixmap */
+ XpmCreatePixmapFromData(dpy, win, xcircuit_xpm, &icon, NULL, NULL);
+
+ wmhints->flags |= InputHint | IconPixmapHint;
+ wmhints->icon_pixmap = icon;
+#else
+ wmhints->flags |= InputHint;
+#endif
+
+ XSetWMHints(dpy, xcWindow(top), wmhints);
+ XFree(wmhints);
+
+/* Don't know why this is necessary, but otherwise keyboard input focus */
+/* is screwed up under the WindowMaker window manager and possibly others. */
+
+#ifdef INPUT_FOCUS
+ XtAddEventHandler(top, SubstructureNotifyMask,
+ TRUE, (XtEventHandler)mappinghandler, NULL);
+#endif
+
+ XtAddEventHandler(top, NoEventMask, TRUE,
+ (XtEventHandler)clientmessagehandler, NULL);
+
+ /* Set the area widget width and height, center userspace (0, 0) on screen */
+ XtSetArg(wargs[0], XtNwidth, &newwin->width);
+ XtSetArg(wargs[1], XtNheight, &newwin->height);
+ XtGetValues(newwin->area, wargs, 2);
+
+ /*---------------------------------------------------*/
+ /* Define basic display variables */
+ /* Redefine win to be just the drawing area window */
+ /*---------------------------------------------------*/
+
+ newwin->window = xcWindow(newwin->area);
+
+ /*-----------------------------*/
+ /* Create the Graphics Context */
+ /*-----------------------------*/
+
+ values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
+ values.background = WhitePixel(dpy, DefaultScreen(dpy));
+ values.font = appdata.xcfont->fid;
+
+ newwin->gc = XCreateGC(dpy, newwin->window,
+ GCForeground | GCBackground | GCFont, &values);
+
+ newwin->clipmask = XCreatePixmap(dpy, newwin->window, newwin->width,
+ newwin->height, 1);
+
+ values.foreground = 0;
+ values.background = 0;
+ newwin->cmgc = XCreateGC(dpy, newwin->clipmask, GCForeground
+ | GCBackground, &values);
+
+ return newwin;
+}
+
+#endif
+
+/*----------------------------------------------------------------------*/
+/* When not using ToolScript, this is the standard X loop (XtMainLoop())*/
+/*----------------------------------------------------------------------*/
+
+int local_xloop()
+{
+ XtAppMainLoop(app);
+ return EXIT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------*/
+/* Main entry point when used as a standalone program */
+/*----------------------------------------------------------------------*/
+
+int main(int argc, char **argv)
+{
+ char *argv0; /* find root of argv[0] */
+ short initargc = argc; /* because XtInitialize() absorbs the */
+ /* -schem flag and renumbers argc! (bug?) */
+ short k = 0;
+
+ /*-----------------------------------------------------------*/
+ /* Find the root of the command called from the command line */
+ /*-----------------------------------------------------------*/
+
+ argv0 = strrchr(argv[0], '/');
+ if (argv0 == NULL)
+ argv0 = argv[0];
+ else
+ argv0++;
+
+ pre_initialize();
+
+ /*---------------------------*/
+ /* Check for schematic flag */
+ /*---------------------------*/
+
+ for (k = argc - 1; k > 0; k--) {
+ if (!strncmp(argv[k], "-2", 2)) {
+ pressmode = 1; /* 2-button mouse indicator */
+ break;
+ }
+ }
+
+ areawin = GUI_init(argc, argv);
+ post_initialize();
+
+ /*-------------------------------------*/
+ /* Initialize the ghostscript renderer */
+ /*-------------------------------------*/
+
+ ghostinit();
+
+ /*----------------------------------------------------------*/
+ /* Check home directory for initial settings & other loads; */
+ /* Load the (default) built-in set of objects */
+ /*----------------------------------------------------------*/
+
+#ifdef HAVE_PYTHON
+ init_interpreter();
+#endif
+
+ loadrcfile();
+ pressmode = 0; /* Done using this to mark 2-button mouse mode */
+
+ composelib(PAGELIB); /* make sure we have a valid page list */
+ composelib(LIBLIB); /* and library directory */
+
+ /*----------------------------------------------------*/
+ /* Parse the command line for initial file to load. */
+ /* Otherwise, look for possible crash-recovery files. */
+ /*----------------------------------------------------*/
+
+ if (argc == 2 + (k != 0) || initargc == 2 + (k != 0)) {
+ strcpy(_STR2, argv[(k == 1) ? 2 : 1]);
+ startloadfile(-1); /* change the argument to load into library other
+ than the User Library */
+ }
+ else {
+ findcrashfiles();
+ }
+
+ xobjs.suspend = -1;
+ return local_xloop(); /* No return---exit through quit() callback */
+}
+
+/*----------------------------------------------------------------------*/
+#endif /* !TCL_WRAPPER */